diff --git a/THIRD_PARTY_NOTICES.md b/THIRD_PARTY_NOTICES.md index 56dbb12..8c176b7 100644 --- a/THIRD_PARTY_NOTICES.md +++ b/THIRD_PARTY_NOTICES.md @@ -6,11 +6,11 @@ third-party components. ## PRoot - Project: -- Version: `5.1.107.86` +- Version: `5.1.107.101` - Source archive SHA-256: - `692da7f952ac390eb65c4117d360cad23a052525eea4eb110ae42f8a4a7d7bb8` + `a66743f50c7b0bac1913b83bf55e139d679c80a0ca2808eec76432a65640017f` - License: GNU General Public License version 2 -- Local modification: `tools/proot-ndk28.patch` +- Local patch set: `patches/proot` ## talloc @@ -21,7 +21,7 @@ third-party components. - License: GNU Lesser General Public License version 3 or later `tools/build-proot-assets.sh` downloads the pinned source archives, verifies -the hashes, applies the recorded patch, and builds the checked-in binaries. +the hashes, applies the recorded patches, and builds the checked-in binaries. Release packaging must provide the applicable full license texts and complete corresponding source alongside binary downloads. diff --git a/app/src/main/assets/runtime/arm64-v8a/proot b/app/src/main/assets/runtime/arm64-v8a/proot index 5ac5334..ef4cb34 100755 Binary files a/app/src/main/assets/runtime/arm64-v8a/proot and b/app/src/main/assets/runtime/arm64-v8a/proot differ diff --git a/app/src/main/assets/runtime/armeabi-v7a/proot b/app/src/main/assets/runtime/armeabi-v7a/proot index 6f0b7d8..446f7f1 100755 Binary files a/app/src/main/assets/runtime/armeabi-v7a/proot and b/app/src/main/assets/runtime/armeabi-v7a/proot differ diff --git a/app/src/main/assets/runtime/x86_64/proot b/app/src/main/assets/runtime/x86_64/proot index a664594..0f556c2 100755 Binary files a/app/src/main/assets/runtime/x86_64/proot and b/app/src/main/assets/runtime/x86_64/proot differ diff --git a/app/src/main/java/org/randomcoder/udroid/install/AndroidRootfsRuntime.kt b/app/src/main/java/org/randomcoder/udroid/install/AndroidRootfsRuntime.kt index 1a2aac0..5598bae 100644 --- a/app/src/main/java/org/randomcoder/udroid/install/AndroidRootfsRuntime.kt +++ b/app/src/main/java/org/randomcoder/udroid/install/AndroidRootfsRuntime.kt @@ -42,7 +42,7 @@ data class ProotRuntime( ) object ProotRuntimeInstaller { - private const val PROOT_VERSION = "5.1.107.101-1" + private const val PROOT_VERSION = "5.1.107.101-3" private const val TAR_VERSION = "1.35-1" private val supportedAbis = setOf("arm64-v8a", "armeabi-v7a", "x86_64") diff --git a/app/src/main/java/org/randomcoder/udroid/runtime/ProotApplicationLaunch.kt b/app/src/main/java/org/randomcoder/udroid/runtime/ProotApplicationLaunch.kt index 39bd255..0780916 100644 --- a/app/src/main/java/org/randomcoder/udroid/runtime/ProotApplicationLaunch.kt +++ b/app/src/main/java/org/randomcoder/udroid/runtime/ProotApplicationLaunch.kt @@ -83,6 +83,8 @@ object ProotApplicationLaunchBuilder { androidHome = context.filesDir.absolutePath, loaderPath = runtime.loader.absolutePath, temporaryDirectory = temporaryDirectory.absolutePath, + shmHelperLauncher = AndroidExecutableCommand.systemLinkerPath(), + prootPath = runtime.executable.absolutePath, ).associate { val separator = it.indexOf('=') it.substring(0, separator) to it.substring(separator + 1) diff --git a/app/src/main/java/org/randomcoder/udroid/runtime/ProotDesktopLaunch.kt b/app/src/main/java/org/randomcoder/udroid/runtime/ProotDesktopLaunch.kt index 265e888..d7f7e55 100644 --- a/app/src/main/java/org/randomcoder/udroid/runtime/ProotDesktopLaunch.kt +++ b/app/src/main/java/org/randomcoder/udroid/runtime/ProotDesktopLaunch.kt @@ -77,6 +77,8 @@ object ProotDesktopLaunchBuilder { androidHome = context.filesDir.absolutePath, loaderPath = runtime.loader.absolutePath, temporaryDirectory = temporaryDirectory.absolutePath, + shmHelperLauncher = AndroidExecutableCommand.systemLinkerPath(), + prootPath = runtime.executable.absolutePath, ).associate { val separator = it.indexOf('=') it.substring(0, separator) to it.substring(separator + 1) diff --git a/app/src/main/java/org/randomcoder/udroid/runtime/ProotTerminalLaunch.kt b/app/src/main/java/org/randomcoder/udroid/runtime/ProotTerminalLaunch.kt index 2efa52e..752e667 100644 --- a/app/src/main/java/org/randomcoder/udroid/runtime/ProotTerminalLaunch.kt +++ b/app/src/main/java/org/randomcoder/udroid/runtime/ProotTerminalLaunch.kt @@ -101,6 +101,8 @@ object ProotTerminalLaunchBuilder { androidHome = context.filesDir.absolutePath, loaderPath = runtime.loader.absolutePath, temporaryDirectory = temporaryDirectory.absolutePath, + shmHelperLauncher = linker, + prootPath = runtime.executable.absolutePath, ) return ProotTerminalLaunch( @@ -170,6 +172,8 @@ object ProotTerminalLaunchBuilder { androidHome: String, loaderPath: String, temporaryDirectory: String, + shmHelperLauncher: String, + prootPath: String, ): Array = arrayOf( "ANDROID_DATA=/data", @@ -180,6 +184,8 @@ object ProotTerminalLaunchBuilder { "PATH=/system/bin", "PROOT_LOADER=$loaderPath", "PROOT_TMP_DIR=$temporaryDirectory", + "PROOT_SHM_HELPER_LAUNCHER=$shmHelperLauncher", + "PROOT_SHM_HELPER_EXECUTABLE=$prootPath", "TMPDIR=$temporaryDirectory", ) diff --git a/app/src/test/java/org/randomcoder/udroid/runtime/ProotTerminalLaunchTest.kt b/app/src/test/java/org/randomcoder/udroid/runtime/ProotTerminalLaunchTest.kt index 36716a8..790eeea 100644 --- a/app/src/test/java/org/randomcoder/udroid/runtime/ProotTerminalLaunchTest.kt +++ b/app/src/test/java/org/randomcoder/udroid/runtime/ProotTerminalLaunchTest.kt @@ -366,6 +366,8 @@ class ProotTerminalLaunchTest { androidHome = "/data/user/0/udroid/files", loaderPath = "/data/user/0/udroid/files/runtime/libproot-loader.so", temporaryDirectory = "/data/user/0/udroid/cache/proot", + shmHelperLauncher = "/system/bin/linker64", + prootPath = "/data/user/0/udroid/files/runtime/proot", ) assertTrue("ANDROID_ROOT=/system" in environment) @@ -373,6 +375,10 @@ class ProotTerminalLaunchTest { "PROOT_LOADER=/data/user/0/udroid/files/runtime/libproot-loader.so" in environment, ) assertTrue("PROOT_TMP_DIR=/data/user/0/udroid/cache/proot" in environment) + assertTrue("PROOT_SHM_HELPER_LAUNCHER=/system/bin/linker64" in environment) + assertTrue( + "PROOT_SHM_HELPER_EXECUTABLE=/data/user/0/udroid/files/runtime/proot" in environment, + ) assertTrue("TMPDIR=/data/user/0/udroid/cache/proot" in environment) } } diff --git a/patches/proot/0001-android-runtime.patch b/patches/proot/0001-android-runtime.patch new file mode 100644 index 0000000..f6d54ad --- /dev/null +++ b/patches/proot/0001-android-runtime.patch @@ -0,0 +1,21 @@ +--- a/src/extension/ashmem_memfd/ashmem_memfd.c ++++ b/src/extension/ashmem_memfd/ashmem_memfd.c +@@ -3,4 +3,5 @@ + #include ++#include + #include + #include + #include /* __NR_memfd_create, */ +--- a/src/extension/sysvipc/sysvipc_shm.c ++++ b/src/extension/sysvipc/sysvipc_shm.c +@@ -14,0 +15 @@ ++#include /* getenv */ +@@ -156 +157,7 @@ +- execl("/proc/self/exe", "proot", "--shm-helper", NULL); ++ const char *launcher = getenv("PROOT_SHM_HELPER_LAUNCHER"); ++ const char *executable = getenv("PROOT_SHM_HELPER_EXECUTABLE"); ++ if (launcher != NULL && launcher[0] == '/' ++ && executable != NULL && executable[0] == '/') { ++ execl(launcher, launcher, executable, "--shm-helper", NULL); ++ } ++ execl("/proc/self/exe", "proot", "--shm-helper", NULL); diff --git a/patches/proot/0002-selective-android-ioctl-tracing.patch b/patches/proot/0002-selective-android-ioctl-tracing.patch new file mode 100644 index 0000000..5f30441 --- /dev/null +++ b/patches/proot/0002-selective-android-ioctl-tracing.patch @@ -0,0 +1,166 @@ +--- a/src/syscall/seccomp.c ++++ b/src/syscall/seccomp.c +@@ -38,6 +38,10 @@ + #include /* offsetof(3), */ + #include /* uint*_t, UINT*_MAX, */ + #include /* assert(3), */ ++#ifdef __ANDROID__ ++#include /* _IOW, */ ++#include /* TCGETS2, TCSETS*, */ ++#endif + + #include "syscall/seccomp.h" + #include "tracee/tracee.h" +@@ -117,9 +121,56 @@ + status = add_statements(program, LENGTH_TRACE_SYSCALL, statements); + if (status < 0) + return status; ++ ++ return 0; ++} ++ ++#ifdef __ANDROID__ ++#define LENGTH_TRACE_ANDROID_IOCTL 14 ++ ++/* Only requests rewritten in enter.c or exit.c need the ptrace round trip. */ ++static int add_trace_android_ioctl(struct sock_fprog *program, word_t syscall) ++{ ++ const uint32_t requests[] = { ++ TCSETS + 2, ++ TCGETS2, ++ TCSETS2, ++ TCSETSW2, ++ TCSETSF2, ++ _IOW(0x94, 9, int), /* FICLONE */ ++ }; ++ const size_t request_offset = offsetof(struct seccomp_data, args[1]); ++ struct sock_filter start[] = { ++ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, syscall, 0, ++ LENGTH_TRACE_ANDROID_IOCTL - 1), ++ BPF_STMT(BPF_LD + BPF_W + BPF_ABS, request_offset), ++ }; ++ size_t i; ++ int status; ++ ++ if (syscall > UINT32_MAX || request_offset > UINT32_MAX) ++ return -ERANGE; ++ ++ status = add_statements(program, sizeof(start) / sizeof(start[0]), start); ++ if (status < 0) ++ return status; ++ ++ for (i = 0; i < sizeof(requests) / sizeof(requests[0]); i++) { ++ struct sock_filter request[] = { ++ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, requests[i], 0, 1), ++ BPF_STMT(BPF_RET + BPF_K, ++ SECCOMP_RET_TRACE + FILTER_SYSEXIT), ++ }; ++ ++ status = add_statements(program, ++ sizeof(request) / sizeof(request[0]), request); ++ if (status < 0) ++ return status; ++ } + + return 0; + } ++#endif + + /** + * Append to @program->filter the statements that allow anything (if +@@ -127,7 +178,8 @@ + * sanity check. This function returns -errno if an error occurred, + * otherwise 0. + */ +-static int end_arch_section(struct sock_fprog *program, size_t nb_traced_syscalls) ++static int end_arch_section(struct sock_fprog *program, size_t nb_traced_syscalls, ++ size_t extra_length) + { + int status; + +@@ -144,7 +196,8 @@ + + /* Sanity check, see start_arch_section(). */ + if ( talloc_array_length(program->filter) - program->len +- != LENGTH_END_SECTION + nb_traced_syscalls * LENGTH_TRACE_SYSCALL) ++ != LENGTH_END_SECTION + nb_traced_syscalls * LENGTH_TRACE_SYSCALL ++ + extra_length) + return -ERANGE; + + return 0; +@@ -156,12 +209,14 @@ + * sanity check. This function returns -errno if an error occurred, + * otherwise 0. + */ +-static int start_arch_section(struct sock_fprog *program, uint32_t arch, size_t nb_traced_syscalls) ++static int start_arch_section(struct sock_fprog *program, uint32_t arch, ++ size_t nb_traced_syscalls, size_t extra_length) + { + const size_t arch_offset = offsetof(struct seccomp_data, arch); + const size_t syscall_offset = offsetof(struct seccomp_data, nr); + const size_t section_length = LENGTH_END_SECTION + +- nb_traced_syscalls * LENGTH_TRACE_SYSCALL; ++ nb_traced_syscalls * LENGTH_TRACE_SYSCALL + ++ extra_length; + int status; + + /* Sanity checks. */ +@@ -267,6 +322,7 @@ + /* For each handled architectures */ + for (i = 0; i < nb_archs; i++) { + word_t syscall; ++ size_t extra_length = 0; + + nb_traced_syscalls = 0; + +@@ -279,8 +335,17 @@ + } + } + ++#ifdef __ANDROID__ ++ for (j = 0; j < seccomp_archs[i].nb_abis; j++) { ++ syscall = detranslate_sysnum(seccomp_archs[i].abis[j], PR_ioctl); ++ if (syscall != SYSCALL_AVOIDER) ++ extra_length += LENGTH_TRACE_ANDROID_IOCTL; ++ } ++#endif ++ + /* Filter: if handled architecture */ +- status = start_arch_section(&program, seccomp_archs[i].value, nb_traced_syscalls); ++ status = start_arch_section(&program, seccomp_archs[i].value, ++ nb_traced_syscalls, extra_length); + if (status < 0) + goto end; + +@@ -298,8 +363,20 @@ + } + } + ++#ifdef __ANDROID__ ++ for (j = 0; j < seccomp_archs[i].nb_abis; j++) { ++ syscall = detranslate_sysnum(seccomp_archs[i].abis[j], PR_ioctl); ++ if (syscall == SYSCALL_AVOIDER) ++ continue; ++ ++ status = add_trace_android_ioctl(&program, syscall); ++ if (status < 0) ++ goto end; ++ } ++#endif ++ + /* Filter: allow untraced syscalls for this architecture */ +- status = end_arch_section(&program, nb_traced_syscalls); ++ status = end_arch_section(&program, nb_traced_syscalls, extra_length); + if (status < 0) + goto end; + } +@@ -356,9 +433,6 @@ + { PR_getsockname, FILTER_SYSEXIT }, + { PR_getxattr, 0 }, + { PR_inotify_add_watch, 0 }, +-#ifdef __ANDROID__ +- { PR_ioctl, FILTER_SYSEXIT }, +-#endif + { PR_lchown, 0 }, + { PR_lchown32, 0 }, + { PR_lgetxattr, 0 }, diff --git a/tools/build-proot-assets.sh b/tools/build-proot-assets.sh index b77937d..0ace0b4 100755 --- a/tools/build-proot-assets.sh +++ b/tools/build-proot-assets.sh @@ -57,8 +57,9 @@ build_abi() { ln -s "$TOOLCHAIN/llvm-readelf" "$wrappers/readelf" unzip -q "$WORK/proot.zip" -d "$abi_work/proot-source" tar -xzf "$WORK/talloc.tar.gz" -C "$abi_work/talloc" --strip-components=1 - patch -d "$abi_work/proot-source/proot-${PROOT_VERSION}" -p1 \ - < "$ROOT/tools/proot-ndk28.patch" + for patch_file in "$ROOT"/patches/proot/*.patch; do + patch -d "$abi_work/proot-source/proot-${PROOT_VERSION}" -p1 < "$patch_file" + done ( cd "$abi_work/talloc" diff --git a/tools/proot-ndk28.patch b/tools/proot-ndk28.patch deleted file mode 100644 index 6d0a341..0000000 --- a/tools/proot-ndk28.patch +++ /dev/null @@ -1,8 +0,0 @@ ---- a/src/extension/ashmem_memfd/ashmem_memfd.c -+++ b/src/extension/ashmem_memfd/ashmem_memfd.c -@@ -3,4 +3,5 @@ - #include -+#include - #include - #include - #include /* __NR_memfd_create, */