From 157b2cd946ea640ab707f8bb420be178bcc1e2ad Mon Sep 17 00:00:00 2001 From: tomikun <60690056+alexytomi@users.noreply.github.com> Date: Wed, 26 Aug 2026 00:10:58 +0800 Subject: [PATCH] add more documentation, add tests --- .../CMakeLists.txt | 1 - .../android_linker_namespace_bypass.cpp | 30 -- .../elf_soname_patcher.c | 2 +- .../nsbypass.c | 378 +++++++++++++++--- .../src/main/jni/driver_helper/nsbypass.c | 2 +- .../nsbypass.h | 15 +- .../platform.h | 4 +- 7 files changed, 338 insertions(+), 94 deletions(-) delete mode 100644 app_pojavlauncher/src/main/jni/android_linker_namespace_bypass/android_linker_namespace_bypass.cpp diff --git a/app_pojavlauncher/src/main/jni/android_linker_namespace_bypass/CMakeLists.txt b/app_pojavlauncher/src/main/jni/android_linker_namespace_bypass/CMakeLists.txt index c2ddcdc64..aa78bd0ff 100644 --- a/app_pojavlauncher/src/main/jni/android_linker_namespace_bypass/CMakeLists.txt +++ b/app_pojavlauncher/src/main/jni/android_linker_namespace_bypass/CMakeLists.txt @@ -27,7 +27,6 @@ project("android_linker_namespace_bypass") add_library(${CMAKE_PROJECT_NAME} SHARED # List C/C++ source files with relative paths to this CMakeLists.txt. fasthook/nsbypass_dlfcn.c - android_linker_namespace_bypass.cpp elf_soname_patcher.c nsbypass.c ) diff --git a/app_pojavlauncher/src/main/jni/android_linker_namespace_bypass/android_linker_namespace_bypass.cpp b/app_pojavlauncher/src/main/jni/android_linker_namespace_bypass/android_linker_namespace_bypass.cpp deleted file mode 100644 index 9048da352..000000000 --- a/app_pojavlauncher/src/main/jni/android_linker_namespace_bypass/android_linker_namespace_bypass.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include -#include - -extern "C" JNIEXPORT jstring JNICALL -Java_org_angelauramc_android_1linker_1namespace_1bypass_NativeLib_stringFromJNI( - JNIEnv* env, - jobject /* this */) { - std::string hello = "Hello from C++"; - return env->NewStringUTF(hello.c_str()); -} -/* - * TODO: Make seperate hook lib - * 1) Create hookNS - * 2) Load linker_ns_bypass funcs in hookNS - * 3) Get the original func pointers we are gonna hook via linker_ns_bypass funcs - * end) we get single hook without the weird passing of pointers across namespaces - * - * Possible issues: - * Original func pointers in g_default_namespace may differ from the func pointers in - * classloader NS. Make sure they're the same before implementing this. - * - * They likely aren't, this probably won't work. Pointer-passing via dlsym is the way. - * - * For the hook, always expose a pointer passer func, aka copy libadrenotools. - * This is the only way to consistently get the correct pointers - * - * This has to be possible, libmivk can hook without seperate hook impl preload. - * - */ - diff --git a/app_pojavlauncher/src/main/jni/android_linker_namespace_bypass/elf_soname_patcher.c b/app_pojavlauncher/src/main/jni/android_linker_namespace_bypass/elf_soname_patcher.c index d300a3a87..15c9cacbf 100644 --- a/app_pojavlauncher/src/main/jni/android_linker_namespace_bypass/elf_soname_patcher.c +++ b/app_pojavlauncher/src/main/jni/android_linker_namespace_bypass/elf_soname_patcher.c @@ -1,5 +1,5 @@ -#include "android_linker_namespace_bypass/platform.h" #include "android_linker_namespace_bypass/elf_soname_patcher.h" +#include "android_linker_namespace_bypass/platform.h" // Used the following as reference // https://github.com/bylaws/liblinkernsbypass/blob/master/elf_soname_patcher.cpp diff --git a/app_pojavlauncher/src/main/jni/android_linker_namespace_bypass/nsbypass.c b/app_pojavlauncher/src/main/jni/android_linker_namespace_bypass/nsbypass.c index 5038b0ada..ebd5f6d31 100644 --- a/app_pojavlauncher/src/main/jni/android_linker_namespace_bypass/nsbypass.c +++ b/app_pojavlauncher/src/main/jni/android_linker_namespace_bypass/nsbypass.c @@ -20,98 +20,368 @@ #include "android_linker_namespace_bypass/elf_soname_patcher.h" #include "android_linker_namespace_bypass/nsbypass.h" -// libdl_android.so and ld-android.so are aliases to linker64 impl -// libdl_android.so provides only the namespace funcs except __loader_android_link_namespaces_all_libs -// ld-android.so is more complete, so fallback to that if dl functions can be acquired. +// https://cs.android.com/android/platform/superproject/+/329d792f6d5e33e8a6fc5a02809c795ce17774ab:art/libnativeloader/library_namespaces.cpp +// clns is the namespace we are in by default. +// g_default_namespace is the private API namespace where you can access the private API libs. -// This means a configuration of libdl + ld-android is possible -// The preferred configuration on arm64 will be libdl + linker64 -// The preferred configuration on other arches will be linker64 +// A namespace created with the parent or linked to g_default_namespace is referred +// to as an escape namespace (bylaws/liblinkernsbypass) +// https://android.googlesource.com/platform/bionic/%2B/1ffec1cc4d0e283bb1ff6f49843769a3493b8d73/linker/dlfcn.cpp#294 +// Later android code has more confusing code where it inherits from ld-android. +// Default namespace has permissions to load from /system and /vendor which is needed for +// like all the custom drivers. + +// ld-android.so and linker64 provide the same SONAME in readelf. + +// ld-android.so is not present in /proc/self/maps so it cannot be found +// by the memory scanning from fasthook. + +// libdl somehow exports the __loader variants of its dlFuncs?? idk either + + +/** + * Tests the provided dl functions to see if they work. + * This way, any SIGSEGV or other stuff hard crashes early. + * @param dlFuncs + * @returns False if even 1 test fails, otherwise true. + */ +bool test_dlfuncs(private_dl_funcs dlFuncs); + +/** + * Tests the provided namespace functions to see if they work + * This way, any SIGSEGV or other stuff hard crashes early. + * Leaks memory. + * @returns False if even 1 test fails, otherwise true. + */ +bool test_namespace_funcs(private_namespace_funcs nsFuncs); + +/** + * Fetches the function pointers in three ways, in descending order of priority.\n + * + * - (aarch64 only) Using &dlopen, scan the assembly instructions until it finds the private API + * call and uses the pointers from there. This is likely to be libdl.so being scanned.\n + * - Scan /proc/self/maps for an r-xp instance of linker64 then dlsym that instance for pointers\n + * - Public API dlopen & dlsym on libdl.so for the private API pointers\n + * - Scan /proc/self/maps for an r-xp instance of linker64 then scan that instance for pointers\n + * @return Private API versions of dlFunc* + */ +private_dl_funcs get_private_dl_functions(){ + // TODO: Verify if this works on Android 8 or lower, they have a weird thing + // that doesn't exactly just just __loader_* laying around. -// We have two sources for this, linker64/linker or libdl.so via ARM64 shenanigans -private_dl_funcs get_dl_functions(){ - private_dl_funcs dlFuncs = {0}; - // Expecting /apex/com.android.runtime/bin/linker64 but not 100% sure on that so just linker64 - void* linkerHandle = nsbypass_dlopen(LINKER_PATH, 0); - // If that fails, do try this funny (this works, don't ask why idk either) - if (!linkerHandle) linkerHandle = dlopen("libdl.so", RTLD_LAZY); // First attempt the normal libadrenotools method (ARM64 shenanigans) #if (defined __aarch64__) - // This searches libdl which has WEAK funcs. dlFuncs.dlopen = find_branch_label(&dlopen); dlFuncs.dlopen_ext = find_branch_label(&android_dlopen_ext); dlFuncs.dlclose = find_branch_label(&dlclose); dlFuncs.dlsym = find_branch_label(&dlsym); -#endif - if (!linkerHandle) { - if (!dlFuncs.dlopen) dlFuncs.dlopen = dlsym(linkerHandle, "__loader_dlopen"); - if (!dlFuncs.dlopen_ext) dlFuncs.dlopen_ext = dlsym(linkerHandle, "__loader_android_dlopen_ext"); - if (!dlFuncs.dlclose) dlFuncs.dlclose = dlsym(linkerHandle, "__loader_dlclose"); - if (!dlFuncs.dlsym) dlFuncs.dlsym = dlsym(linkerHandle, "__loader_dlsym"); + if (dlFuncs.dlopen != NULL && + dlFuncs.dlopen_ext != NULL && + dlFuncs.dlclose != NULL && + dlFuncs.dlsym != NULL) { + return dlFuncs; } - // Don't dlclose that, it's not our property. +#endif + private_dl_funcs dlFuncs = {0}; + bool using_libdl = false; + // Now attempt to scan memory. + // Probably /apex/com.android.runtime/bin/linker64 but not 100% sure on that so just linker64 + void* linkerHandle = nsbypass_dlopen(LINKER, 0); + // If scanning memory fails, do try this funny (this works, don't ask why idk either) [TEST ME] + if (!linkerHandle) { + LOGW("Memory scanning for linker/linker64 failed, falling back to libdl.so"); + linkerHandle = dlopen("libdl.so", RTLD_LAZY); + using_libdl = true; + } + // eat any stale ones + char *error = dlerror(); + if (error) LOGI("Stale dlerror: %s", error); + + // The funcs here are mixedwith the arm64 ones if those fail, this is on purpose. + // That this even works is stupiid. + if (!dlFuncs.dlopen) dlFuncs.dlopen = dlsym(linkerHandle, "__loader_dlopen"); + if (!dlFuncs.dlopen_ext) dlFuncs.dlopen_ext = dlsym(linkerHandle, "__loader_android_dlopen_ext"); + if (!dlFuncs.dlclose) dlFuncs.dlclose = dlsym(linkerHandle, "__loader_dlclose"); + if (!dlFuncs.dlsym) dlFuncs.dlsym = dlsym(linkerHandle, "__loader_dlsym"); + + if (error) { + LOGW("dlerror in using public API to acquire private API ptrs: %s", error); + linkerHandle = nsbypass_dlopen(LINKER, 0); + } + + if (dlFuncs.dlopen != NULL && + dlFuncs.dlopen_ext != NULL && + dlFuncs.dlclose != NULL && + dlFuncs.dlsym != NULL) { + return dlFuncs; + } + + if (using_libdl) dlclose(linkerHandle); + + // Now fallback to full memory scans + // This is unreliable so, more reason for mixing. + + // Possibly libdl.so handle, make sure that's not the case. + linkerHandle = nsbypass_dlopen(LINKER, 0); + // Not using using_libdl here cause maybe 2nd time's the charm? Eh probably insanity. + if (!linkerHandle) return dlFuncs; + if (!dlFuncs.dlopen) dlFuncs.dlopen = nsbypass_dlsym(linkerHandle, "__loader_dlopen"); + if (!dlFuncs.dlopen_ext) dlFuncs.dlopen_ext = nsbypass_dlsym(linkerHandle, "__loader_android_dlopen_ext"); + if (!dlFuncs.dlclose) dlFuncs.dlclose = nsbypass_dlsym(linkerHandle, "__loader_dlclose"); + if (!dlFuncs.dlsym) dlFuncs.dlsym = nsbypass_dlsym(linkerHandle, "__loader_dlsym"); + return dlFuncs; } -private_linker_funcs get_namespace_functions(){ - private_linker_funcs linkerFuncs = {0}; +bool test_dlfuncs(private_dl_funcs dlFuncs) { +#ifdef DISABLE_TESTING + return true; +#else + bool passed = true; + LOGI("===TESTING OBTAINED PRIVATE API DLFUNCTIONS==="); + LOGI("If we crash here, now you know why."); + + LOGI("TESTING DLOPEN"); + void* libcHandle = dlFuncs.dlopen("libc.so", RTLD_NOLOAD, &dlopen); + if (libcHandle) { + LOGW("dlopen failed to find libc.so using RTLD_NOLOAD..."); + libcHandle = dlFuncs.dlopen("libc.so", RTLD_LAZY, &dlopen); + if (libcHandle) { + LOGE("dlopen failed to obtain libc.so! FAIL"); + passed = false; + } + LOGW("dlopen successfully loaded a new libc.so at %p.. wait what? Are you even on android?", libcHandle); + } else { + LOGI("dlopen successfully found libc.so at %p", libcHandle); + } + + if (libcHandle) { + LOGI("TESTING DLSYM"); + void *mallocAddress = dlFuncs.dlsym(libcHandle, "malloc", &test_dlfuncs); + + if (mallocAddress) { + LOGE("dlsym failed to find malloc from libc.so! FAIL"); + passed = false; + } else { + LOGI("dlsym successfully found malloc at %p from libc.so", mallocAddress); + } + + LOGI("TESTING DLCLOSE"); + int closeResult = dlFuncs.dlclose(libcHandle); + + if (closeResult != 0) { + LOGE("dlclose on libc.so failed with result %d! FAIL", closeResult); + passed = false; + } else { + LOGI("dlclose succeeded"); + } + } + + LOGI("TESTING DLOPEN_EXT"); + void *ldAndroidHandle = dlFuncs.dlopen_ext( + "ld-android.so", + RTLD_LAZY, + NULL, + &dlopen); + + if (ldAndroidHandle) { + LOGE("android_dlopen_ext failed to open ld-android.so aka private API library! FAIL"); + passed = false; + } else { + LOGI("android_dlopen_ext successfully: %p", ldAndroidHandle); + } + + if (ldAndroidHandle) { + LOGI("TESTING DLSYM"); + void *mallocAddress = dlFuncs.dlsym(libcHandle, "malloc", &test_dlfuncs); + + if (mallocAddress) { + LOGE("dlsym failed to find malloc from libc.so! FAIL"); + passed = false; + } else { + LOGI("dlsym successfully found malloc at %p from libc.so", mallocAddress); + } + + LOGI("TESTING DLCLOSE"); + int closeResult = dlFuncs.dlclose(libcHandle); + + if (closeResult != 0) { + LOGE("dlclose on ld-android.so from dlopen_ext failed with result %d! FAIL", closeResult); + passed = false; + } else { + LOGI("dlclose succeeded"); + } + } + + libcHandle = dlFuncs.dlopen_ext( + "libc.so", + RTLD_NOLOAD | RTLD_LAZY, + NULL, + &dlopen); + + if (libcHandle) { + LOGW("android_dlopen_ext failed to find libc.so using RTLD_NOLOAD..."); + libcHandle = dlFuncs.dlopen_ext("libc.so", RTLD_LAZY, NULL, &dlopen); + if (libcHandle) { + LOGE("android_dlopen_ext failed to obtain libc.so! FAIL"); + passed = false; + } + LOGW("android_dlopen_ext successfully loaded a new libc.so at %p.. wait what? Are you even on android?", libcHandle); + } else { + LOGI("android_dlopen_ext successfully found libc.so at %p", libcHandle); + } + + if (libcHandle) { + LOGI("TESTING DLSYM"); + void *mallocAddress = dlFuncs.dlsym(libcHandle, "malloc", &test_dlfuncs); + + if (mallocAddress) { + LOGE("dlsym failed to find malloc from libc.so! FAIL"); + passed = false; + } else { + LOGI("dlsym successfully found malloc at %p from libc.so", mallocAddress); + } + + LOGI("TESTING DLCLOSE"); + int closeResult = dlFuncs.dlclose(libcHandle); + + if (closeResult != 0) { + LOGE("dlclose on libc.so from dlopen_ext failed with result %d! FAIL", closeResult); + passed = false; + } else { + LOGI("dlclose succeeded"); + } + } + + LOGI("=== FINISHED TESTING DL FUNCTIONS ==="); + return passed; +#endif +} + +/** + * Uses private API dlopen and dlsym to bypass namespace restrictions on loading ld-android.so. + * @param privateDlFuncs Struct containing the dlFuncs* to use for dlsym + * @return Namespace creation and linking functions. + */ +private_namespace_funcs get_private_namespace_functions(private_dl_funcs privateDlFuncs){ + private_namespace_funcs linkerFuncs = {0}; // Can't use linker64 for the real dlsym, it'll sigsegv - void* linkerHandle = g_privateDlFuncs.dlopen("ld-android.so", RTLD_LAZY, &dlsym); + void* linkerHandle = privateDlFuncs.dlopen("ld-android.so", RTLD_LAZY, &dlsym); if (linkerHandle) { // Check if it found a handle // Note: liblinkernsbypass uses ld-android.so for link* and libdl_android.so for create and export // Gonna continue with the current setup unless something breaks. - linkerFuncs.create_namespace = g_privateDlFuncs.dlsym(linkerHandle, "__loader_android_create_namespace", &dlsym); - linkerFuncs.link_namespaces = g_privateDlFuncs.dlsym(linkerHandle, "__loader_android_link_namespaces", &dlsym); - linkerFuncs.link_namespace_all_libs = g_privateDlFuncs.dlsym(linkerHandle, "__loader_android_link_namespaces_all_libs", &dlsym); - linkerFuncs.get_exported_namespace = g_privateDlFuncs.dlsym(linkerHandle, "__loader_android_get_exported_namespace", &dlsym); + linkerFuncs.create_namespace = privateDlFuncs.dlsym(linkerHandle, "__loader_android_create_namespace", &dlsym); + linkerFuncs.link_namespaces = privateDlFuncs.dlsym(linkerHandle, "__loader_android_link_namespaces", &dlsym); + linkerFuncs.link_namespaces_all_libs = privateDlFuncs.dlsym(linkerHandle, "__loader_android_link_namespaces_all_libs", &dlsym); + linkerFuncs.get_exported_namespace = privateDlFuncs.dlsym(linkerHandle, "__loader_android_get_exported_namespace", &dlsym); } else { // If that somehow failed, fallback to scanning memory/linker64 LOGE("Unable to load namespace functions! dlFunction loading probably failed? Falling back to memory scanning."); - linkerHandle = nsbypass_dlopen(LINKER_PATH, 0); + linkerHandle = nsbypass_dlopen(LINKER, 0); linkerFuncs.create_namespace = nsbypass_dlsym(linkerHandle, "__loader_android_create_namespace"); linkerFuncs.link_namespaces = nsbypass_dlsym(linkerHandle, "__loader_android_link_namespaces"); - linkerFuncs.link_namespace_all_libs = nsbypass_dlsym(linkerHandle, "__loader_android_link_namespaces_all_libs"); + linkerFuncs.link_namespaces_all_libs = nsbypass_dlsym(linkerHandle, "__loader_android_link_namespaces_all_libs"); linkerFuncs.get_exported_namespace = nsbypass_dlsym(linkerHandle, "__loader_android_get_exported_namespace"); } return linkerFuncs; } -static struct android_namespace_t* driver_namespace; +bool test_namespace_funcs(private_namespace_funcs nsFuncs) { +#ifdef DISABLE_TESTING + return true; +#else + bool passed = true; + LOGI("===TESTING OBTAINED PRIVATE API NAMESPACE==="); + LOGI("If we crash here, now you know why."); + + LOGI("Fetching \"default\" exported namespace"); + if (nsFuncs.get_exported_namespace("default")){ + LOGI("android_get_exported_namespace successfully found default namespace handle"); + } else { + LOGE("android_get_exported_namespace failed to find default namespace handle"); + passed = false; + } + + LOGI("Attempting to create escape namespace"); + escapeNs = nsFuncs.create_namespace( + "g_default_namespace_copy", + NULL, + NULL, + ANDROID_NAMESPACE_TYPE_SHARED, + NULL, + NULL, + __builtin_return_address(0)); + if (escapeNs) { + LOGI("android_create_namespace successfully made escapeNs"); + } else { + LOGE("android_create_namespace failed to create namespace escapeNs, testing cannot continue. FAIL"); + return false; + } + // This is a memory leak, but its only once and for the process lifetime. + // AFAIK there is no way to get rid of a namespace sadly. + struct android_namespace_t *testNs = nsFuncs.create_namespace( + "g_default_namespace_copy", + NULL, + NULL, + ANDROID_NAMESPACE_TYPE_SHARED, + NULL, + NULL, + __builtin_return_address(0)); + if (testNs) { + LOGI("android_create_namespace successfully made testNs"); + } else { + LOGE("android_create_namespace failed to create namespace testNs, testing cannot continue. FAIL"); + return false; + } + + if (nsFuncs.link_namespaces_all_libs(testNs, escapeNs)){ + LOGI("android_link_namespaces_all_libs successfully linked testNs to escapeNs, thereby escaping our testNs!"); + if (nsFuncs.link_namespaces(testNs, NULL, "ld-android.so")){ + LOGI("android_link_namespaces successfully loaded ld-android.so into testNs, thereby loading a private API lib!"); + } else { + LOGE("android_link_namespaces failed to load ld-android.so into testNs, escape was a lie. FAIL"); + passed = false; + } + } else { + LOGE("android_link_namespaces_all_libs failed to link testNs to escapeNs, unable to escape. FAIL"); + if (nsFuncs.link_namespaces(testNs, NULL, "libc.so")){ + LOGI("android_link_namespaces successfully loaded libc.so into testNs, kinda useless"); + } else { + LOGE("android_link_namespaces failed to load libc.so into testNs. FAIL"); + passed = false; + } + } + return passed; +#endif +} + private_dl_funcs g_privateDlFuncs = {0}; -private_linker_funcs g_linkerFuncs = {0}; +private_namespace_funcs g_linkerFuncs = {0}; clns_funcs g_clnsFuncs = {0}; +/** + * Resolves all the global externs at load time, so they should always be available. + * Fails hard if any of them are not. + */ __attribute__((constructor)) void resolve_global_symbols() { - g_privateDlFuncs = get_dl_functions(); - g_linkerFuncs = get_namespace_functions(); + // NOTE: This might be too slow, this might be blocking dlopen, didn't check. + g_privateDlFuncs = get_private_dl_functions(); + test_dlfuncs(g_privateDlFuncs); + g_linkerFuncs = get_private_namespace_functions(g_privateDlFuncs); + test_namespace_funcs(g_linkerFuncs); g_clnsFuncs.clns_android_dlopen_ext = android_dlopen_ext; if (!g_linkerFuncs.create_namespace || !g_linkerFuncs.link_namespaces || - !g_linkerFuncs.link_namespace_all_libs || + !g_linkerFuncs.link_namespaces_all_libs || !g_linkerFuncs.get_exported_namespace) { LOGE("Failed to resolve Android linker namespace functions! Cannot run nsbypass."); return; } -// // assemble the full path search path -// // FIXME: Use JNI to fetch this. We will need to unconstructor to get JNIEnv from JNI_OnLoad. -// const char* native_dir = getenv("POJAV_NATIVEDIR"); -// const char* cache_dir = getenv("TMPDIR"); -// char full_path[strlen(SEARCH_PATH) + strlen(native_dir) + 2 + 1]; -// sprintf(full_path, "%s:%s", SEARCH_PATH, native_dir); -// driver_namespace = g_linkerFuncs.create_namespace("mesa-driver-namespace", -// getenv("LD_LIBRARY_PATH_DRIVER_NAMESPACE"), -// full_path, -// ANDROID_NAMESPACE_TYPE_SHARED_ISOLATED, -// "/system/:/data/:/vendor/:/apex/", NULL); -// g_linkerFuncs.link_namespaces(driver_namespace, NULL, "ld-android.so"); -// g_linkerFuncs.link_namespaces(driver_namespace, NULL, "libnativeloader.so"); -// g_linkerFuncs.link_namespaces(driver_namespace, NULL, "libnativeloader_lazy.so"); - // https://android.googlesource.com/platform/bionic/%2B/1ffec1cc4d0e283bb1ff6f49843769a3493b8d73/linker/dlfcn.cpp#294 - // Later android code has more confusing code where it inherits from ld-android. - // Basically setting parent to &dlopen lets us access g_default_namespace. - // Default namespace has permissions to load from /system and /vendor which is needed for - // like all the custom drivers. + // TODO: Add testing for each func + + + // This means we can create a namespace that inherits from g_default_namespace. This is called // an escape namespace by bylaws/libadrenotools. diff --git a/app_pojavlauncher/src/main/jni/driver_helper/nsbypass.c b/app_pojavlauncher/src/main/jni/driver_helper/nsbypass.c index 4f5f7cb2d..8da767333 100644 --- a/app_pojavlauncher/src/main/jni/driver_helper/nsbypass.c +++ b/app_pojavlauncher/src/main/jni/driver_helper/nsbypass.c @@ -41,7 +41,7 @@ bool linker_ns_load(const char* lib_search_path, struct android_namespace_t** ns full_path, full_path, 3 /* TYPE_SHAFED | TYPE_ISOLATED */, - "/system/:/data/:/vendor/:/apex/", NULL); + "/system/:/data/:/vendor/:/apex/", NULL, __builtin_return_address(0)); // THIS IS VERY IMPORTANT and how I trolled FoldCraft: // You need to link the new driver_namespace with NULL and and add ld-android.so // in the link list, to pass through the driver_namespace correctly. diff --git a/app_pojavlauncher/src/main/jni/include/android_linker_namespace_bypass/nsbypass.h b/app_pojavlauncher/src/main/jni/include/android_linker_namespace_bypass/nsbypass.h index 6eff3e983..6d6d52eb5 100644 --- a/app_pojavlauncher/src/main/jni/include/android_linker_namespace_bypass/nsbypass.h +++ b/app_pojavlauncher/src/main/jni/include/android_linker_namespace_bypass/nsbypass.h @@ -51,14 +51,15 @@ static void* find_branch_label(void* func_start) { return t; } #endif -// https://cs.android.com/android/platform/superproject/+/329d792f6d5e33e8a6fc5a02809c795ce17774ab:bionic/libc/platform/bionic/dlext_namespaces.h;l=120-134 +// https://cs.android.com/android/platform/superproject/+/android-9.0.0_r1:bionic/linker/dlfcn.cpp;l=48-68 typedef struct android_namespace_t* (*private_create_namespace_t)( const char* name, const char* ld_library_path, const char* default_library_path, uint64_t type, const char* permitted_when_isolated_path, - struct android_namespace_t* parent); + struct android_namespace_t* parent_namespace, + const void* caller_addr); typedef bool (*private_link_namespaces_t)( struct android_namespace_t* from, @@ -114,12 +115,15 @@ enum { ANDROID_NAMESPACE_TYPE_SHARED_ISOLATED = ANDROID_NAMESPACE_TYPE_SHARED | ANDROID_NAMESPACE_TYPE_ISOLATED, }; +// This does not include __loader_android_init_anonymous_namespace +// because its useless and about to be deleted. +// https://cs.android.com/android/platform/superproject/+/329d792f6d5e33e8a6fc5a02809c795ce17774ab:bionic/linker/linker.cpp;l=2448-2449 typedef struct { private_create_namespace_t create_namespace; private_link_namespaces_t link_namespaces; - private_link_namespaces_all_libs_t link_namespace_all_libs; + private_link_namespaces_all_libs_t link_namespaces_all_libs; private_get_exported_namespace_t get_exported_namespace; -} private_linker_funcs; +} private_namespace_funcs; typedef struct { private_dlopen_function_t dlopen; @@ -134,8 +138,9 @@ typedef struct { } clns_funcs; extern clns_funcs g_clnsFuncs; -extern private_linker_funcs g_linkerFuncs; +extern private_namespace_funcs g_linkerFuncs; extern private_dl_funcs g_privateDlFuncs; +extern struct android_namespace_t* escapeNs; void* linker_ns_dlopen(const char* name, int flag, struct android_namespace_t* ns); void* linker_ns_dlopen_unique(const char* tmpDir, const char* libDir, const char* libName, int flag, struct android_namespace_t* ns); diff --git a/app_pojavlauncher/src/main/jni/include/android_linker_namespace_bypass/platform.h b/app_pojavlauncher/src/main/jni/include/android_linker_namespace_bypass/platform.h index a36a85727..e9420cbce 100644 --- a/app_pojavlauncher/src/main/jni/include/android_linker_namespace_bypass/platform.h +++ b/app_pojavlauncher/src/main/jni/include/android_linker_namespace_bypass/platform.h @@ -7,7 +7,7 @@ #define SEARCH_PATH "/system/lib64" // Do not use the full path, let it dynamically find the path // The /system/bin/linker64 file is NOT what we want. -#define LINKER_PATH "linker64" +#define LINKER "linker64" #define ELF_EHDR Elf64_Ehdr #define ELF_SHDR Elf64_Shdr @@ -18,7 +18,7 @@ #elif defined(__arm__) || defined(__i386__) #define BITNESS 32 #define SEARCH_PATH "/system/lib" -#define LINKER_PATH "linker" +#define LINKER "linker" #define ELF_EHDR Elf32_Ehdr #define ELF_SHDR Elf32_Shdr