From 98d8375c16147e4aab0362681ec3545c35fcdb92 Mon Sep 17 00:00:00 2001 From: tomikun <60690056+alexytomi@users.noreply.github.com> Date: Wed, 26 Aug 2026 15:47:34 +0800 Subject: [PATCH] tie up the rewritening --- app_pojavlauncher/src/main/jni/Android.mk | 2 +- .../nsbypass.c | 21 ++- .../internal_android_dlopen_hook/hook.c | 63 --------- .../turnip/hook.c | 81 +++++++++++ .../src/main/jni/driver_helper/nsbypass.c | 62 --------- .../src/main/jni/driver_helper/nsbypass.h | 13 -- app_pojavlauncher/src/main/jni/egl_bridge.c | 49 +++---- .../nsbypass.h | 124 +---------------- .../nsbypass_t.h | 127 ++++++++++++++++++ 9 files changed, 248 insertions(+), 294 deletions(-) delete mode 100644 app_pojavlauncher/src/main/jni/driver_helper/internal_android_dlopen_hook/hook.c create mode 100644 app_pojavlauncher/src/main/jni/driver_helper/internal_android_dlopen_hook/turnip/hook.c delete mode 100644 app_pojavlauncher/src/main/jni/driver_helper/nsbypass.c delete mode 100644 app_pojavlauncher/src/main/jni/driver_helper/nsbypass.h create mode 100644 app_pojavlauncher/src/main/jni/include/android_linker_namespace_bypass/nsbypass_t.h diff --git a/app_pojavlauncher/src/main/jni/Android.mk b/app_pojavlauncher/src/main/jni/Android.mk index 70a9b547e..d1670ed27 100644 --- a/app_pojavlauncher/src/main/jni/Android.mk +++ b/app_pojavlauncher/src/main/jni/Android.mk @@ -78,7 +78,7 @@ include $(BUILD_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := linkerhook LOCAL_C_INCLUDES := $(LOCAL_PATH)/include -LOCAL_SRC_FILES := driver_helper/internal_android_dlopen_hook/hook.c +LOCAL_SRC_FILES := driver_helper/internal_android_dlopen_hook/turnip/hook.c # If you add LOCAL_SHARED_LIBRARIES here, it might load those NEEDED as duplicates # in wherever namespace this is put inside of. Please just do not. # Use dlopen if at all possible, the plt/got is a lie!! 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 ade0a0cdf..094833194 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 @@ -399,7 +399,7 @@ bool test_namespace_funcs(private_namespace_funcs nsFuncs) { ANDROID_NAMESPACE_TYPE_SHARED, NULL, NULL, - __builtin_return_address(0)); + &dlopen); if (escapeNs) { LOGI("android_create_namespace successfully made escapeNs"); } else { @@ -446,7 +446,7 @@ bool test_namespace_funcs(private_namespace_funcs nsFuncs) { private_dl_funcs g_privateDlFuncs = {0}; private_namespace_funcs g_linkerFuncs = {0}; -clns_funcs g_clnsFuncs = {0}; +clns_funcs g_clnsFuncs = {0}; //TODO: DELETE struct android_namespace_t* escapeNs; /** @@ -454,7 +454,7 @@ struct android_namespace_t* escapeNs; * Fails hard if any of them are not. */ __attribute__((constructor)) void resolve_global_symbols() { - // NOTE: This might be too slow, this might be blocking dlopen, didn't check. + // NOTE: Tests are fast enough. Probably still disable tho. g_privateDlFuncs = get_private_dl_functions(); test_dlfuncs(g_privateDlFuncs); g_linkerFuncs = get_private_namespace_functions(g_privateDlFuncs); @@ -468,6 +468,21 @@ __attribute__((constructor)) void resolve_global_symbols() { LOGE("Failed to resolve Android linker namespace functions! Cannot run nsbypass."); return; } + + if (!escapeNs){ + escapeNs = g_linkerFuncs.create_namespace( + "g_default_namespace_copy", + NULL, + NULL, + ANDROID_NAMESPACE_TYPE_SHARED, + NULL, + NULL, + &dlopen); + if (!escapeNs) { + LOGD("Failed to create escapeNs!"); + exit(120); // idk it felt like a 120 + } + } } // dlopen in a specific namespace diff --git a/app_pojavlauncher/src/main/jni/driver_helper/internal_android_dlopen_hook/hook.c b/app_pojavlauncher/src/main/jni/driver_helper/internal_android_dlopen_hook/hook.c deleted file mode 100644 index 3b1905018..000000000 --- a/app_pojavlauncher/src/main/jni/driver_helper/internal_android_dlopen_hook/hook.c +++ /dev/null @@ -1,63 +0,0 @@ -// -// Created by maks on 05.06.2023. -// -#include -#include -#include -#include -#include "log.h" -#include -// Silence the warnings about using reserved identifiers (we need to link to these to not pollute the global symtab) -//NOLINTBEGIN -static void* (*android_dlopen_ext_p)(const char* filename, - int flags, - const android_dlextinfo* extinfo, - const void* caller_addr); -static struct android_namespace_t* (*android_get_exported_namespace_p)(const char* name); -//NOLINTEND -static void* ready_handle; - -static const char *sphal_namespaces[3] = { - "sphal", "vendor", "default" -}; - - -__attribute__((visibility("default"), used)) void app__pojav_linkerhook_pass_handles(void* data, void* android_dlopen_ext_pp, - void* android_get_exported_namespace) { - // Calling android_dlopen_ext here locates the hook, not the real func. - // dlsym will give you the real func, will need libdl handle - ready_handle = data; - android_dlopen_ext_p = android_dlopen_ext_pp; - android_get_exported_namespace_p = android_get_exported_namespace; -} - -__attribute__((visibility("default"), used)) void *android_dlopen_ext(const char *filename, int flags, const android_dlextinfo *extinfo) { - __android_log_print(ANDROID_LOG_DEBUG, "DLHOOK", "dlopen ext activated"); - if(!strstr(filename, "vulkan.")) - return android_dlopen_ext_p(filename, flags, extinfo, &android_dlopen_ext); - return ready_handle; -} - -__attribute__((visibility("default"), used)) void *android_load_sphal_library(const char *filename, int flags) { - if(strstr(filename, "vulkan.")) { - return ready_handle; - } - //printf("__loader_android_get_exported_namespace = %p\n__loader_android_dlopen_ext = %p\n", __loader_android_get_exported_namespace, - // __loader_android_dlopen_ext); - struct android_namespace_t* androidNamespace; - for(int i = 0; i < 3; i++) { - androidNamespace = android_get_exported_namespace_p(sphal_namespaces[i]); - if(androidNamespace != NULL) break; - } - android_dlextinfo info = {0}; - info.flags = ANDROID_DLEXT_USE_NAMESPACE; - info.library_namespace = androidNamespace; - return android_dlopen_ext_p(filename, flags, &info, &android_dlopen_ext); -} - -// This is done for older android versions which don't -// export this function. Technically this is wrong -// but for our usage it's fine enough -__attribute__((visibility("default"), used)) uint64_t atrace_get_enabled_tags() { - return 0; -} \ No newline at end of file diff --git a/app_pojavlauncher/src/main/jni/driver_helper/internal_android_dlopen_hook/turnip/hook.c b/app_pojavlauncher/src/main/jni/driver_helper/internal_android_dlopen_hook/turnip/hook.c new file mode 100644 index 000000000..678acc655 --- /dev/null +++ b/app_pojavlauncher/src/main/jni/driver_helper/internal_android_dlopen_hook/turnip/hook.c @@ -0,0 +1,81 @@ +#include +#include +#include +#include "android_linker_namespace_bypass/nsbypass_t.h" +#include "android_linker_namespace_bypass/platform.h" + +static void* turnipHandle; +static const char *sphal_namespaces[3] = { + "sphal", "vendor", "default" +}; + +static private_namespace_funcs *privateNamespaceFuncs; +static private_dl_funcs *privateDlFuncs; +static void* (*linker_ns_dlopen)(const char* name, int flag, struct android_namespace_t* ns); +static void* (*linker_ns_dlopen_unique)(const char* tmpDir, const char* libDir, const char* libName, int flag, struct android_namespace_t* ns); + +static struct android_namespace_t* turnipNs; + +static uint64_t (*atrace_get_enabled_tags_p)(); + +__attribute__((constructor)) void init_handles() { + // dlopen manually so the linker dependency is more explicit. + // don't want it to do anything funny. + void* libandroidnsbypassHandle = dlopen("libandroid_linker_namespace_bypass.so", RTLD_LOCAL | RTLD_LAZY); + privateNamespaceFuncs = dlsym(libandroidnsbypassHandle, "g_linkerFuncs"); + privateDlFuncs = dlsym(libandroidnsbypassHandle, "g_privateDlFuncs"); + atrace_get_enabled_tags_p = privateDlFuncs->dlsym( + privateDlFuncs->dlopen("libcutils.so", RTLD_LOCAL | RTLD_LAZY, &dlopen), + "atrace_get_enabled_tags_p", + &dlopen + ); + linker_ns_dlopen = dlsym(libandroidnsbypassHandle, "linker_ns_dlopen"); + linker_ns_dlopen_unique = dlsym(libandroidnsbypassHandle, "linker_ns_dlopen_unique"); +} + +__attribute__((visibility("default"), used)) void *android_dlopen_ext(const char *filename, int flags, const android_dlextinfo *extinfo) { + if(!strstr(filename, "vulkan.")) + return privateDlFuncs->dlopen_ext(filename, flags, extinfo, &android_dlopen_ext); + if (!turnipHandle){ + // We aren't checking for flags haha. + turnipNs = privateNamespaceFuncs->create_namespace( + "turnip-driver-NS", + NULL, + NULL, + ANDROID_NAMESPACE_TYPE_ISOLATED, + NULL, + NULL, + extinfo->library_namespace // libvulkan should feed itself here + ); + void* turnip_driver_handle = linker_ns_dlopen("libvulkan_freedreno.so", RTLD_LOCAL | RTLD_NOW, turnipNs); + if(turnip_driver_handle == NULL) { + printf("AdrenoSupp: Failed to load Turnip!\n%s\n", dlerror()); + return NULL; + } + } + return turnipHandle; +} + +__attribute__((visibility("default"), used)) void *android_load_sphal_library(const char *filename, int flags) { + if(strstr(filename, "vulkan.")) { + return turnipHandle; + } + //printf("__loader_android_get_exported_namespace = %p\n__loader_android_dlopen_ext = %p\n", __loader_android_get_exported_namespace, + // __loader_android_dlopen_ext); + struct android_namespace_t* androidNamespace; + for(int i = 0; i < 3; i++) { + androidNamespace = privateNamespaceFuncs->get_exported_namespace(sphal_namespaces[i]); + if(androidNamespace != NULL) break; + } + android_dlextinfo info = {0}; + info.flags = ANDROID_DLEXT_USE_NAMESPACE; + info.library_namespace = androidNamespace; + return privateDlFuncs->dlopen_ext(filename, flags, &info, &android_dlopen_ext); +} + +// This is done for older android versions which don't +// export this function. Technically this is wrong +// but for our usage it's fine enough +__attribute__((visibility("default"), used)) uint64_t atrace_get_enabled_tags() { + return atrace_get_enabled_tags_p(); +} \ No newline at end of file diff --git a/app_pojavlauncher/src/main/jni/driver_helper/nsbypass.c b/app_pojavlauncher/src/main/jni/driver_helper/nsbypass.c deleted file mode 100644 index e5c3b4818..000000000 --- a/app_pojavlauncher/src/main/jni/driver_helper/nsbypass.c +++ /dev/null @@ -1,62 +0,0 @@ -// -// Created by maks on 05.06.2023. -// - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "android_linker_namespace_bypass/nsbypass.h" - -/* upper 6 bits of an ARM64 instruction are the instruction name */ -#define OP_MS 0b11111100000000000000000000000000 -/* Branch Label instruction opcode and immediate mask */ -#define BL_OP 0b10010100000000000000000000000000 -#define BL_IM 0b00000011111111111111111111111111 -/* Library search path */ -#define SEARCH_PATH "/system/lib64" -#define ELF_EHDR Elf64_Ehdr -#define ELF_SHDR Elf64_Shdr -#define ELF_HALF Elf64_Half -#define ELF_XWORD Elf64_Xword -#define ELF_DYN Elf64_Dyn -#define ELF_SYM Elf64_Sym - -//#define ADRENO_POSSIBLE -bool linker_ns_load(const char* lib_search_path, struct android_namespace_t** ns) { - // assemble the full path search path - char full_path[strlen(SEARCH_PATH) + strlen(lib_search_path) + 2 + 1]; - sprintf(full_path, "%s:%s", SEARCH_PATH, lib_search_path); - *ns = g_linkerFuncs.create_namespace("pojav-driver", - full_path, - full_path, - 3 /* TYPE_SHAFED | TYPE_ISOLATED */, - "/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. - // Not doing this fucks up internal __loader symbol lookup - // inside the new driver_namespace, thus breaking it on - // a lot of android versions - // FoldCraft got trolled because they copied the - // old broken code verbatim and didn't even test it thoroughly - g_linkerFuncs.link_namespaces(*ns, NULL, "ld-android.so"); - // Also establish links to use the libnativeloader(_lazy).so libraries - // from the global namespace. This is a workaround for an EMUI issue where - // the newly loaded libnativeloader_lazy for some unknown reason links - // to itself and causes a deadlock when loading the vulkan driver. - g_linkerFuncs.link_namespaces(*ns, NULL, "libnativeloader.so"); - g_linkerFuncs.link_namespaces(*ns, NULL, "libnativeloader_lazy.so"); - return true; -} \ No newline at end of file diff --git a/app_pojavlauncher/src/main/jni/driver_helper/nsbypass.h b/app_pojavlauncher/src/main/jni/driver_helper/nsbypass.h deleted file mode 100644 index 905ea77e2..000000000 --- a/app_pojavlauncher/src/main/jni/driver_helper/nsbypass.h +++ /dev/null @@ -1,13 +0,0 @@ - -// -// Created by maks on 05.06.2023. -// - -#ifndef POJAVLAUNCHER_NSBYPASS_H -#define POJAVLAUNCHER_NSBYPASS_H - -#include -struct android_namespace_t; -bool linker_ns_load(const char* lib_search_path, struct android_namespace_t** ns); - -#endif //POJAVLAUNCHER_NSBYPASS_H diff --git a/app_pojavlauncher/src/main/jni/egl_bridge.c b/app_pojavlauncher/src/main/jni/egl_bridge.c index 5411d2363..29fb7cc13 100644 --- a/app_pojavlauncher/src/main/jni/egl_bridge.c +++ b/app_pojavlauncher/src/main/jni/egl_bridge.c @@ -12,7 +12,6 @@ #include #include #include "ctxbridges/osmesa_loader.h" -#include "driver_helper/nsbypass.h" #include "android_linker_namespace_bypass/nsbypass.h" #ifdef GLES_TEST #include @@ -96,39 +95,29 @@ Java_net_kdt_pojavlaunch_utils_JREUtils_releaseBridgeWindow(ABI_COMPAT JNIEnv *e EXTERNAL_API void* pojavGetCurrentContext() { return br_get_current(); } -static struct android_namespace_t* driver_namespace; +static struct android_namespace_t* vulkanLoaderNs; void* load_turnip_vulkan() { // if(getenv("POJAV_LOAD_TURNIP") == NULL) return NULL; const char* native_dir = getenv("POJAV_NATIVEDIR"); const char* cache_dir = getenv("TMPDIR"); - if(driver_namespace == NULL && !linker_ns_load(native_dir, &driver_namespace)) return NULL; - void* linkerhook = linker_ns_dlopen("liblinkerhook.so", RTLD_LOCAL | RTLD_NOW, driver_namespace); - // lldb debugger console will return android_dlopen_ext from the new new after this - // but its a lie, android_dlopen_ext still resolves properly here. - if(linkerhook == NULL) return NULL; - void* turnip_driver_handle = linker_ns_dlopen("libvulkan_freedreno.so", RTLD_LOCAL | RTLD_NOW, driver_namespace); - if(turnip_driver_handle == NULL) { - printf("AdrenoSupp: Failed to load Turnip!\n%s\n", dlerror()); - dlclose(linkerhook); - return NULL; - } - void* dl_android = linker_ns_dlopen("libdl_android.so", RTLD_LOCAL | RTLD_LAZY, driver_namespace); - if(dl_android == NULL) { - dlclose(linkerhook); - dlclose(turnip_driver_handle); - return NULL; - } - void* android_get_exported_namespace = dlsym(dl_android, "android_get_exported_namespace"); - void (*linkerhook_pass_handles)(void*, void*, void*) = dlsym(linkerhook, "app__pojav_linkerhook_pass_handles"); - if(linkerhook_pass_handles == NULL || android_get_exported_namespace == NULL) { - dlclose(dl_android); - dlclose(linkerhook); - dlclose(turnip_driver_handle); - return NULL; - } - linkerhook_pass_handles(turnip_driver_handle, android_dlopen_ext, android_get_exported_namespace); - void* libvulkan = linker_ns_dlopen_unique(cache_dir, SEARCH_PATH, "libvulkan.so", RTLD_LOCAL | RTLD_NOW, driver_namespace); - return libvulkan; + vulkanLoaderNs = g_linkerFuncs.create_namespace( + "vulkan-loader-NS", + NULL, + NULL, + ANDROID_NAMESPACE_TYPE_SHARED_ISOLATED, + NULL, + NULL, + __builtin_return_address(0) + ); + // Grants the namespace access to system libs. + g_linkerFuncs.link_namespaces_all_libs(vulkanLoaderNs, escapeNs); + + return linker_ns_dlopen_unique( + cache_dir, + SEARCH_PATH, + "libvulkan.so", + RTLD_LOCAL | RTLD_NOW, + vulkanLoaderNs);; } static void set_vulkan_ptr(void* ptr) { 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 1be6e519d..34e3c7fd9 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 @@ -2,11 +2,8 @@ // Created by tom on 8/22/26. // -#include -#include -#include - -#include "android_linker_namespace_bypass/platform.h" +#include "platform.h" +#include "nsbypass_t.h" #ifndef AMETHYST_NSBYPASS_H #define AMETHYST_NSBYPASS_H @@ -52,123 +49,6 @@ static void* find_branch_label(void* func_start) { return t; } #endif -// 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_namespace, - const void* caller_addr); - -typedef bool (*private_link_namespaces_t)( - struct android_namespace_t* from, - struct android_namespace_t* to, - const char* shared_libs_sonames); - -typedef bool (*private_link_namespaces_all_libs_t)( - struct android_namespace_t* from, - struct android_namespace_t* to); - -typedef struct android_namespace_t* (*private_get_exported_namespace_t)( - const char* name); - -// https://cs.android.com/android/platform/superproject/+/329d792f6d5e33e8a6fc5a02809c795ce17774ab:bionic/linker/dlfcn.cpp;drc=fda4c10ddf33a1c4cb56c58fae98dd9c2239fdc9;l=82-85 -typedef int (*private_dlclose_function_t)( - void *handle); - -typedef void *(*private_dlopen_function_t)( - const char* filename, - int flags, - const void* caller_addr); - -typedef void *(*private_dlsym_function_t)( - void* handle, - const char* symbol, - const void* caller_addr); - -// http://cs.android.com/android/platform/superproject/+/329d792f6d5e33e8a6fc5a02809c795ce17774ab:bionic/linker/dlfcn.cpp;drc=fda4c10ddf33a1c4cb56c58fae98dd9c2239fdc9;l=58-61 -// Just pass __builtin_return_address(0); for caller_addr -// extinfo is nullable and doing so is equivalent to calling __loader_dlopen -typedef void *(*private_dlopen_ext_function_t)(const char* filename, - int flags, - const android_dlextinfo* extinfo, - const void* caller_addr); - -// https://cs.android.com/android/platform/superproject/+/329d792f6d5e33e8a6fc5a02809c795ce17774ab:bionic/libdl/libdl.cpp;drc=a493fe415304efd19f089cbfc7d78c9db7d7263c;l=135-138 -typedef void *(*android_dlopen_ext_t)( - const char* filename, - int flag, - const android_dlextinfo* extinfo); - -// https://cs.android.com/android/platform/superproject/+/android-latest-release:bionic/libdl/libdl_android.cpp;drc=8e5de06bc59b02641a9fb4a86f921f9534a3bef5;l=117-119 -typedef struct android_namespace_t *(*android_get_exported_namespace_t)( - const char* name); - -// https://cs.android.com/android/platform/superproject/+/0a492a4685377d41fef2b12e9af4ebfa6feef9c2:art/libnativeloader/include/nativeloader/dlext_namespaces.h;l=25;bpv=1;bpt=1 -enum { - /* A regular namespace is the namespace with a custom search path that does - * not impose any restrictions on the location of native libraries. - */ - ANDROID_NAMESPACE_TYPE_REGULAR = 0, - - /* An isolated namespace requires all the libraries to be on the search path - * or under permitted_when_isolated_path. The search path is the union of - * ld_library_path and default_library_path. - */ - ANDROID_NAMESPACE_TYPE_ISOLATED = 1, - - /* The shared namespace clones the list of libraries of the caller namespace upon creation - * which means that they are shared between namespaces - the caller namespace and the new one - * will use the same copy of a library if it was loaded prior to android_create_namespace call. - * - * Note that libraries loaded after the namespace is created will not be shared. - * - * Shared namespaces can be isolated or regular. Note that they do not inherit the search path nor - * permitted_path from the caller's namespace. - */ - ANDROID_NAMESPACE_TYPE_SHARED = 2, - - /* This flag instructs linker to enable exempt-list workaround for the namespace. - * See http://b/26394120 for details. - */ - ANDROID_NAMESPACE_TYPE_EXEMPT_LIST_ENABLED = 0x08000000, - - /* This flag instructs linker to use this namespace as the anonymous - * namespace. The anonymous namespace is used in the case when linker cannot - * identify the caller of dlopen/dlsym. This happens for the code not loaded - * by dynamic linker; for example calls from the mono-compiled code. There can - * be only one anonymous namespace in a process. If there already is an - * anonymous namespace in the process, using this flag when creating a new - * namespace causes an error. - */ - ANDROID_NAMESPACE_TYPE_ALSO_USED_AS_ANONYMOUS = 0x10000000, - - 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_namespaces_all_libs; - private_get_exported_namespace_t get_exported_namespace; -} private_namespace_funcs; - -typedef struct { - private_dlopen_function_t dlopen; - private_dlopen_ext_function_t dlopen_ext; - private_dlclose_function_t dlclose; - private_dlsym_function_t dlsym; -} private_dl_funcs; - -// These are pointers which are likely to be hooked by whoever is using this library. -typedef struct { - android_dlopen_ext_t clns_android_dlopen_ext; -} clns_funcs; extern clns_funcs g_clnsFuncs; extern private_namespace_funcs g_linkerFuncs; diff --git a/app_pojavlauncher/src/main/jni/include/android_linker_namespace_bypass/nsbypass_t.h b/app_pojavlauncher/src/main/jni/include/android_linker_namespace_bypass/nsbypass_t.h new file mode 100644 index 000000000..abcba70c6 --- /dev/null +++ b/app_pojavlauncher/src/main/jni/include/android_linker_namespace_bypass/nsbypass_t.h @@ -0,0 +1,127 @@ +// +// Created by tom on 8/26/26. +// + +#include + +#ifndef AMETHYST_NSBYPASS_T_H +#define AMETHYST_NSBYPASS_T_H +// 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_namespace, + const void* caller_addr); + +typedef bool (*private_link_namespaces_t)( + struct android_namespace_t* from, + struct android_namespace_t* to, + const char* shared_libs_sonames); + +typedef bool (*private_link_namespaces_all_libs_t)( + struct android_namespace_t* from, + struct android_namespace_t* to); + +typedef struct android_namespace_t* (*private_get_exported_namespace_t)( + const char* name); + +// https://cs.android.com/android/platform/superproject/+/329d792f6d5e33e8a6fc5a02809c795ce17774ab:bionic/linker/dlfcn.cpp;drc=fda4c10ddf33a1c4cb56c58fae98dd9c2239fdc9;l=82-85 +typedef int (*private_dlclose_function_t)( + void *handle); + +typedef void *(*private_dlopen_function_t)( + const char* filename, + int flags, + const void* caller_addr); + +typedef void *(*private_dlsym_function_t)( + void* handle, + const char* symbol, + const void* caller_addr); + +// http://cs.android.com/android/platform/superproject/+/329d792f6d5e33e8a6fc5a02809c795ce17774ab:bionic/linker/dlfcn.cpp;drc=fda4c10ddf33a1c4cb56c58fae98dd9c2239fdc9;l=58-61 +// Just pass __builtin_return_address(0); for caller_addr +// extinfo is nullable and doing so is equivalent to calling __loader_dlopen +typedef void *(*private_dlopen_ext_function_t)(const char* filename, + int flags, + const android_dlextinfo* extinfo, + const void* caller_addr); + +// https://cs.android.com/android/platform/superproject/+/329d792f6d5e33e8a6fc5a02809c795ce17774ab:bionic/libdl/libdl.cpp;drc=a493fe415304efd19f089cbfc7d78c9db7d7263c;l=135-138 +typedef void *(*android_dlopen_ext_t)( + const char* filename, + int flag, + const android_dlextinfo* extinfo); + +// https://cs.android.com/android/platform/superproject/+/android-latest-release:bionic/libdl/libdl_android.cpp;drc=8e5de06bc59b02641a9fb4a86f921f9534a3bef5;l=117-119 +typedef struct android_namespace_t *(*android_get_exported_namespace_t)( + const char* name); + +// https://cs.android.com/android/platform/superproject/+/0a492a4685377d41fef2b12e9af4ebfa6feef9c2:art/libnativeloader/include/nativeloader/dlext_namespaces.h;l=25;bpv=1;bpt=1 +enum { + /* A regular namespace is the namespace with a custom search path that does + * not impose any restrictions on the location of native libraries. + */ + ANDROID_NAMESPACE_TYPE_REGULAR = 0, + + /* An isolated namespace requires all the libraries to be on the search path + * or under permitted_when_isolated_path. The search path is the union of + * ld_library_path and default_library_path. + */ + ANDROID_NAMESPACE_TYPE_ISOLATED = 1, + + /* The shared namespace clones the list of libraries of the caller namespace upon creation + * which means that they are shared between namespaces - the caller namespace and the new one + * will use the same copy of a library if it was loaded prior to android_create_namespace call. + * + * Note that libraries loaded after the namespace is created will not be shared. + * + * Shared namespaces can be isolated or regular. Note that they do not inherit the search path nor + * permitted_path from the caller's namespace. + */ + ANDROID_NAMESPACE_TYPE_SHARED = 2, + + /* This flag instructs linker to enable exempt-list workaround for the namespace. + * See http://b/26394120 for details. + */ + ANDROID_NAMESPACE_TYPE_EXEMPT_LIST_ENABLED = 0x08000000, + + /* This flag instructs linker to use this namespace as the anonymous + * namespace. The anonymous namespace is used in the case when linker cannot + * identify the caller of dlopen/dlsym. This happens for the code not loaded + * by dynamic linker; for example calls from the mono-compiled code. There can + * be only one anonymous namespace in a process. If there already is an + * anonymous namespace in the process, using this flag when creating a new + * namespace causes an error. + */ + ANDROID_NAMESPACE_TYPE_ALSO_USED_AS_ANONYMOUS = 0x10000000, + + 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_namespaces_all_libs; + private_get_exported_namespace_t get_exported_namespace; +} private_namespace_funcs; + +typedef struct { + private_dlopen_function_t dlopen; + private_dlopen_ext_function_t dlopen_ext; + private_dlclose_function_t dlclose; + private_dlsym_function_t dlsym; +} private_dl_funcs; + +// These are pointers which are likely to be hooked by whoever is using this library. +typedef struct { + android_dlopen_ext_t clns_android_dlopen_ext; +} clns_funcs; + +#endif //AMETHYST_NSBYPASS_T_H