mirror of
https://github.com/AngelAuraMC/Amethyst-Android.git
synced 2026-09-17 08:49:39 -04:00
add more documentation, add tests
This commit is contained in:
1 parent
50d0e6271a
commit
157b2cd946
7 files changed
+338
-94
No files matched your search
@@ -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
|
||||
)
|
||||
|
||||
-30
@@ -1,30 +0,0 @@
|
||||
#include <jni.h>
|
||||
#include <string>
|
||||
|
||||
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.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in new issue
Block a user