almost woorking

This commit is contained in:
tomikun committed 2026-08-25 19:21:22 +08:00
1 parent bdacac412f
commit 99b8d408fb
10 files changed
+112 -204

No files matched your search

@@ -37,6 +37,7 @@ LOCAL_MODULE := pojavexec
# LOCAL_CFLAGS += -DDEBUG
# -DGLES_TEST
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_SHARED_LIBRARIES := android_linker_namespace_bypass
LOCAL_SRC_FILES := \
bigcoreaffinity.c \
egl_bridge.c \
@@ -76,6 +77,8 @@ include $(BUILD_SHARED_LIBRARY)
#ifeq ($(TARGET_ARCH_ABI),arm64-v8a)
include $(CLEAR_VARS)
LOCAL_MODULE := linkerhook
LOCAL_SHARED_LIBRARIES := android_linker_namespace_bypass
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_SRC_FILES := driver_helper/hook.c
LOCAL_LDFLAGS := -z global
include $(BUILD_SHARED_LIBRARY)
@@ -1,4 +1,4 @@
#include "platform.h"
#include "android_linker_namespace_bypass/platform.h"
#include "android_linker_namespace_bypass/elf_soname_patcher.h"
// Used the following as reference
@@ -16,21 +16,25 @@
#include <stdlib.h>
#include <jni.h>
#include "fasthook/nsbypass_dlfcn.h"
#include "platform.h"
#include "android_linker_namespace_bypass/platform.h"
#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 WEAK symbols and missing dlFuncs. Don't use it.
// 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.
// 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
// We have two sources for this, linker64/linker or libdl.so via ARM64 shenanigans
private_dl_funcs get_dl_functions(){
private_dl_funcs dlFuncs;
void* linkerHandle = nsbypass_dlopen(LINKER_PATH, 0);
// Expecting /apex/com.android.runtime/bin/linker64 but not 100% sure on that so just linker64
void* linkerHandle = nsbypass_dlopen("linker64", 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.
@@ -39,11 +43,11 @@ private_dl_funcs get_dl_functions(){
dlFuncs.dlclose = find_branch_label(&dlclose);
dlFuncs.dlsym = find_branch_label(&dlsym);
#endif
// If that fails, try looking for it in memory
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");
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");
// Don't dlclose that, it's not our property.
return dlFuncs;
}
@@ -19,7 +19,9 @@
// SOFTWARE.
// Copyright (c) 2026 alexytomi
// Modified to remove redundancies within nsbypass library
// Modified to remove redundancies within nsbypass library and renaming things
// Added relative file support to nsbypass_dlopen
// Redirect these functions to the real implementations on Android 6 and below
// This is not actually dlfunc. It doesn't load anything.
// It bypasses normal linker restrictions by searching the memory for already loaded symbols.
@@ -33,10 +35,11 @@
#include <sys/mman.h>
#include <elf.h>
#include <android/log.h>
#include "platform.h"
#include "android_linker_namespace_bypass/platform.h"
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <dlfcn.h>
#include "fasthook/nsbypass_dlfcn.h"
struct ctx {
@@ -50,7 +53,24 @@ struct ctx {
off_t bias;
};
typedef int (*get_device_api_level_fn)(void);
// Namespace restrictions were added in android 7, stub to the normal funcs if below that
static int is_android_6_or_lower(void)
{
void *symbol;
get_device_api_level_fn get_api_level;
symbol = dlsym(dlopen("libc.so", RTLD_LAZY), "android_get_device_api_level");
if (symbol == NULL) {
// android_get_device_api_level() was added in API 24. If it's not here then we are lower.
return 1;
}
get_api_level = (get_device_api_level_fn)symbol;
return get_api_level() < 24 ? 1 : 0;
}
int nsbypass_dlclose(void *handle) {
if (is_android_6_or_lower()) return dlclose(handle);
if (handle) {
struct ctx *ctx = (struct ctx *) handle;
if (ctx->dynsym) free(ctx->dynsym); /* we're saving dynsym and dynstr */
@@ -62,9 +82,12 @@ int nsbypass_dlclose(void *handle) {
return 0;
}
void *nsbypass_dlopen(const char *libpath, int flags) {
void *nsbypass_dlopen(const char *libPath, int flags) {
if (is_android_6_or_lower()) return dlopen(libPath, flags);
FILE *maps;
char buff[256];
// Increase the buffer because we added searching for absolute file.
// 256 might not be enough buffer to get the whole path in.
char mapsSearchBuff[2048];
struct ctx *ctx = 0;
off_t load_addr, size;
int k, fd = -1, found = 0;
@@ -76,34 +99,63 @@ void *nsbypass_dlopen(const char *libpath, int flags) {
maps = fopen("/proc/self/maps", "r");
if (!maps) fatal("failed to open maps");
while (!found && fgets(buff, sizeof(buff), maps))
if (strstr(buff, "r-xp") && strstr(buff, libpath)) found = 1;
while (!found && fgets(mapsSearchBuff, sizeof(mapsSearchBuff), maps))
if (strstr(mapsSearchBuff, "r-xp") && strstr(mapsSearchBuff, libPath)) found = 1;
fclose(maps);
if (!found) fatal("%s not found in my userspace", libpath);
// If user didn't prove an absolute path we have to find the actual full path ourselves
// This is NOT the file path where the file lives in, so scan memory again.
if (libPath[0] != '/') {
// Looks through the current buffer which contains the libPath and the path
// mapsSearchBuff probably looks like
// 7a8d366000-7a8d453000 r-xp 00039000 07:60 16 /apex/com.android.runtime/bin/linker64
char *libPathStart = strstr(mapsSearchBuff, libPath); // at ..bin/[l]inker64
if (libPathStart != NULL) {
char *pathStart = libPathStart;
// Move backward until we find the spaces area.
while (pathStart > mapsSearchBuff &&
pathStart[-1] != ' ' &&
pathStart[-1] != '\t') {
--pathStart;
}
// Hopefully this is the start of the path
if (*pathStart == '/') {
libPath = pathStart;
} else {
fatal(
"An error happened while resolving the full path of %s; "
"searching stopped at %s",
libPath,
pathStart
);
}
}
}
if (sscanf(buff, "%lx", &load_addr) != 1)
fatal("failed to read load address for %s", libpath);
if (!found) fatal("%s not found in my userspace", libPath);
LOGI("%s loaded in Android at 0x%08lx", libpath, load_addr);
if (sscanf(mapsSearchBuff, "%lx", &load_addr) != 1)
fatal("failed to read load address for %s", libPath);
LOGI("%s loaded in Android at 0x%08lx", libPath, load_addr);
/* Now, mmap the same library once again */
fd = open(libpath, O_RDONLY);
if (fd < 0) fatal("failed to open %s", libpath);
fd = open(libPath, O_RDONLY);
if (fd < 0) fatal("failed to open %s", libPath);
size = lseek(fd, 0, SEEK_END);
if (size <= 0) fatal("lseek() failed for %s", libpath);
if (size <= 0) fatal("lseek() failed for %s", libPath);
elf = (ELF_EHDR *) mmap(0, size, PROT_READ, MAP_SHARED, fd, 0);
close(fd);
fd = -1;
if (elf == MAP_FAILED) fatal("mmap() failed for %s", libpath);
if (elf == MAP_FAILED) fatal("mmap() failed for %s", libPath);
ctx = (struct ctx *) calloc(1, sizeof(struct ctx));
if (!ctx) fatal("no memory for %s", libpath);
if (!ctx) fatal("no memory for %s", libPath);
ctx->load_addr = (void *) load_addr;
shoff = ((void *) elf) + elf->e_shoff;
@@ -120,17 +172,17 @@ void *nsbypass_dlopen(const char *libpath, int flags) {
switch (sh->sh_type) {
case SHT_DYNSYM:
if (ctx->dynsym) fatal("%s: duplicate DYNSYM sections", libpath); /* .dynsym */
if (ctx->dynsym) fatal("%s: duplicate DYNSYM sections", libPath); /* .dynsym */
ctx->dynsym = malloc(sh->sh_size);
if (!ctx->dynsym) fatal("%s: no memory for .dynsym", libpath);
if (!ctx->dynsym) fatal("%s: no memory for .dynsym", libPath);
memcpy(ctx->dynsym, ((void *) elf) + sh->sh_offset, sh->sh_size);
ctx->dynsym_num = (sh->sh_size / sizeof(ELF_SYM));
break;
case SHT_SYMTAB:
if (ctx->symtab) fatal("%s: duplicate SYMTAB sections", libpath); /* .symtab */
if (ctx->symtab) fatal("%s: duplicate SYMTAB sections", libPath); /* .symtab */
ctx->symtab = malloc(sh->sh_size);
if (!ctx->symtab) fatal("%s: no memory for .symtab", libpath);
if (!ctx->symtab) fatal("%s: no memory for .symtab", libPath);
memcpy(ctx->symtab, ((void *) elf) + sh->sh_offset, sh->sh_size);
ctx->symtab_num = (sh->sh_size / sizeof(ELF_SYM));
break;
@@ -139,12 +191,12 @@ void *nsbypass_dlopen(const char *libpath, int flags) {
if(!strcmp(shstr+sh->sh_name,".dynstr")) {
if (ctx->dynstr) break; /* .dynstr is guaranteed to be the first STRTAB */
ctx->dynstr = malloc(sh->sh_size);
if (!ctx->dynstr) fatal("%s: no memory for .dynstr", libpath);
if (!ctx->dynstr) fatal("%s: no memory for .dynstr", libPath);
memcpy(ctx->dynstr, ((void *) elf) + sh->sh_offset, sh->sh_size);
}else if(!strcmp(shstr+sh->sh_name,".strtab")) {
if (ctx->strtab) break;
ctx->strtab = malloc(sh->sh_size);
if (!ctx->strtab) fatal("%s: no memory for .strtab", libpath);
if (!ctx->strtab) fatal("%s: no memory for .strtab", libPath);
memcpy(ctx->strtab, ((void *) elf) + sh->sh_offset, sh->sh_size);
}
break;
@@ -161,11 +213,11 @@ void *nsbypass_dlopen(const char *libpath, int flags) {
munmap(elf, size);
elf = 0;
if (!ctx->dynstr || !ctx->dynsym) fatal("dynamic sections not found in %s", libpath);
if (!ctx->dynstr || !ctx->dynsym) fatal("dynamic sections not found in %s", libPath);
#undef fatal
LOGD("%s: ok, dynsym = %p, dynstr = %p symtab = %p strtab = %p", libpath, ctx->dynsym, ctx->dynstr, ctx->symtab, ctx->strtab);
LOGD("%s: ok, dynsym = %p, dynstr = %p symtab = %p strtab = %p", libPath, ctx->dynsym, ctx->dynstr, ctx->symtab, ctx->strtab);
return ctx;
@@ -177,6 +229,7 @@ void *nsbypass_dlopen(const char *libpath, int flags) {
}
void *nsbypass_dlsym(void *handle, const char *name) {
if (is_android_6_or_lower()) return dlsym(handle, name);
int k;
struct ctx *ctx = (struct ctx *) handle;
ELF_SYM *dynsym = (ELF_SYM *) ctx->dynsym;
@@ -1,7 +1,7 @@
//
// Created by maks on 05.06.2023.
//
#include "nsbypass.h"
#include <dlfcn.h>
#include <android/dlext.h>
#include <android/log.h>
@@ -16,6 +16,7 @@
#include <fcntl.h>
#include <sys/stat.h>
#include <elf.h>
#include "android_linker_namespace_bypass/nsbypass.h"
/* upper 6 bits of an ARM64 instruction are the instruction name */
#define OP_MS 0b11111100000000000000000000000000
@@ -32,70 +33,11 @@
#define ELF_SYM Elf64_Sym
//#define ADRENO_POSSIBLE
typedef void* (*loader_dlopen_t)(const char* filename, int flags, const void* caller_addr);
typedef struct android_namespace_t* (*ld_android_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, const void* caller_addr);
typedef void* (*ld_android_link_namespaces_t)(struct android_namespace_t* namespace_from,
struct android_namespace_t* namespace_to,
const char* shared_libs_sonames);
static ld_android_create_namespace_t android_create_namespace;
static struct android_namespace_t* driver_namespace;
struct android_namespace_t* local_android_create_namespace(
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) {
void* caller = __builtin_return_address(0);
return android_create_namespace(name, ld_library_path, default_library_path, type, permitted_when_isolated_path, parent, caller);
}
// Find the first "branch to label" function in the function provided in func_start
static void* find_branch_label(void* func_start) {
long page_size = sysconf(_SC_PAGESIZE);
// round down the pointer to get the start of the function's page
void* func_page_start = (void*)(((uintptr_t)func_start) & ~(page_size-1));
// remap to r-x to bypass "execute only" protections on MIUI
mprotect(func_page_start, page_size, PROT_READ | PROT_EXEC);
uint32_t* bl_addr = func_start;
// search for the "branch to label" opcode
while((*bl_addr & OP_MS) != BL_OP) {
bl_addr++; // walk through memory until we find it or die
}
// offset the address to find where the "branch to label" instrunction
// points to.
return ((char*)bl_addr) + (*bl_addr & BL_IM) * 4;
}
bool linker_ns_load(const char* lib_search_path) {
long page_size = sysconf(_SC_PAGESIZE);
#ifndef ADRENO_POSSIBLE
return false;
#else
// Makes bytehook stop being all crashy about hooky
if(driver_namespace != NULL) return true;
loader_dlopen_t loader_dlopen = find_branch_label(&dlopen);
// reprotecting the functions removes protection from indirect jumps
mprotect(loader_dlopen, page_size, PROT_WRITE | PROT_READ | PROT_EXEC);
void* ld_android_handle = loader_dlopen("ld-android.so", RTLD_LAZY, &dlopen);
if(ld_android_handle == NULL) {
return false;
}
// load the two functions we need
android_create_namespace = dlsym(ld_android_handle, "__loader_android_create_namespace");
ld_android_link_namespaces_t android_link_namespaces = dlsym(ld_android_handle, "__loader_android_link_namespaces");
if(android_create_namespace == NULL || android_link_namespaces == NULL) {
dlclose(ld_android_handle);
return false;
}
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);
driver_namespace = local_android_create_namespace("pojav-driver",
*ns = g_linkerFuncs.create_namespace("pojav-driver",
full_path,
full_path,
3 /* TYPE_SHAFED | TYPE_ISOLATED */,
@@ -108,102 +50,12 @@ bool linker_ns_load(const char* lib_search_path) {
// a lot of android versions
// FoldCraft got trolled because they copied the
// old broken code verbatim and didn't even test it thoroughly
android_link_namespaces(driver_namespace, NULL, "ld-android.so");
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.
android_link_namespaces(driver_namespace, NULL, "libnativeloader.so");
android_link_namespaces(driver_namespace, NULL, "libnativeloader_lazy.so");
dlclose(ld_android_handle);
g_linkerFuncs.link_namespaces(*ns, NULL, "libnativeloader.so");
g_linkerFuncs.link_namespaces(*ns, NULL, "libnativeloader_lazy.so");
return true;
#endif
}
void* linker_ns_dlopen(const char* name, int flag) {
#ifndef ADRENO_POSSIBLE
return NULL;
#else
android_dlextinfo dlextinfo;
dlextinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
dlextinfo.library_namespace = driver_namespace;
return android_dlopen_ext(name, flag, &dlextinfo);
#endif
}
/**
* @brief Overwrites the first three characters of a soname
* @note IMPORTANT: The supplied soname patch will overwrite the first strlen(sonamePatch) chars of the soname
* @param elfPath Full path to the elf to patch
* @param targetFd FD to use for storing the patched library
* @return True on success
*/
bool patch_elf_soname(int patchfd, int realfd, uint16_t patchid) {
struct stat realstat;
if(fstat(realfd, &realstat)) return false;
if(ftruncate64(patchfd, realstat.st_size) == -1) return false;
char* target = mmap(NULL, realstat.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, patchfd, 0);
if(!target) return false;
if(read(realfd, target, realstat.st_size) != realstat.st_size) {
munmap(target, realstat.st_size);
return false;
}
close(realfd);
ELF_EHDR *ehdr = (ELF_EHDR*)target;
ELF_SHDR *shdr = (ELF_SHDR*)(target + ehdr->e_shoff);
// Iterate over section headers to find the .dynamic section
for(ELF_HALF i = 0; i < ehdr->e_shnum; i++) {
ELF_SHDR *hdr = &shdr[i];
if(hdr->sh_type == SHT_DYNAMIC) {
char* strtab = target + shdr[hdr->sh_link].sh_offset;
ELF_DYN *dynEntries = (ELF_DYN*)(target + hdr->sh_offset);
// Iterate over .dynamic entries to find DT_SONAME
for(ELF_XWORD k = 0; k < (hdr->sh_size / hdr->sh_entsize);k++) {
ELF_DYN* dynEntry = &dynEntries[k];
if(dynEntry->d_tag == DT_SONAME) {
char* soname = strtab + dynEntry->d_un.d_val;
char sprb[4];
// Partially replace the old soname with the soname patch
snprintf(sprb, 4, "%03x", patchid);
memcpy(soname, sprb, 3);
munmap(target, realstat.st_size);
return true;
}
}
}
}
return false;
}
void* linker_ns_dlopen_unique(const char* tmpdir, const char* name, int flags) {
#ifndef ADRENO_POSSIBLE
return NULL;
#else
char pathbuf[PATH_MAX];
static uint16_t patch_id;
int patch_fd, real_fd;
snprintf(pathbuf,PATH_MAX,"%s/%d_p.so", tmpdir, patch_id);
patch_fd = open(pathbuf, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
if(patch_fd == -1) return NULL;
snprintf(pathbuf,PATH_MAX,"%s/%s", SEARCH_PATH, name);
real_fd = open(pathbuf, O_RDONLY);
if(real_fd == -1) {
close(patch_fd);
return NULL;
}
if(!patch_elf_soname(patch_fd, real_fd, patch_id)) {
close(patch_fd);
close(real_fd);
return NULL;
}
android_dlextinfo extinfo;
extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE | ANDROID_DLEXT_USE_LIBRARY_FD;
extinfo.library_fd = patch_fd;
extinfo.library_namespace = driver_namespace;
snprintf(pathbuf, PATH_MAX, "/proc/self/fd/%d", patch_fd);
return android_dlopen_ext(pathbuf, flags, &extinfo);
#endif
}
}
@@ -7,9 +7,7 @@
#define POJAVLAUNCHER_NSBYPASS_H
#include <stdbool.h>
bool linker_ns_load(const char* lib_search_path);
void* linker_ns_dlopen(const char* name, int flag);
void* linker_ns_dlopen_unique(const char* tmpdir, const char* name, int flag);
struct android_namespace_t;
bool linker_ns_load(const char* lib_search_path, struct android_namespace_t** ns);
#endif //POJAVLAUNCHER_NSBYPASS_H
+7 -10
View File
@@ -13,7 +13,7 @@
#include <GL/osmesa.h>
#include "ctxbridges/osmesa_loader.h"
#include "driver_helper/nsbypass.h"
#include "android_linker_namespace_bypass/nsbypass.h"
#ifdef GLES_TEST
#include <GLES2/gl2.h>
#endif
@@ -96,23 +96,21 @@ Java_net_kdt_pojavlaunch_utils_JREUtils_releaseBridgeWindow(ABI_COMPAT JNIEnv *e
EXTERNAL_API void* pojavGetCurrentContext() {
return br_get_current();
}
//#define ADRENO_POSSIBLE
#ifdef ADRENO_POSSIBLE
static struct android_namespace_t* driver_namespace;
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(!linker_ns_load(native_dir)) return NULL;
void* linkerhook = linker_ns_dlopen("liblinkerhook.so", RTLD_LOCAL | RTLD_NOW);
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);
if(linkerhook == NULL) return NULL;
void* turnip_driver_handle = linker_ns_dlopen("libvulkan_freedreno.so", RTLD_LOCAL | RTLD_NOW);
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);
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);
@@ -127,10 +125,9 @@ void* load_turnip_vulkan() {
return NULL;
}
linkerhook_pass_handles(turnip_driver_handle, android_dlopen_ext, android_get_exported_namespace);
void* libvulkan = linker_ns_dlopen_unique(cache_dir, "libvulkan.so", RTLD_LOCAL | RTLD_NOW);
void* libvulkan = linker_ns_dlopen_unique(cache_dir, SEARCH_PATH, "libvulkan.so", RTLD_LOCAL | RTLD_NOW, driver_namespace);
return libvulkan;
}
#endif
static void set_vulkan_ptr(void* ptr) {
char envval[64];
@@ -5,6 +5,7 @@
#include <android/dlext.h>
#include <sys/unistd.h>
#include <sys/mman.h>
#include "android_linker_namespace_bypass/platform.h"
#ifndef AMETHYST_NSBYPASS_H
#define AMETHYST_NSBYPASS_H
@@ -44,7 +45,7 @@ static void* find_branch_label(void* func_start) {
// Reprotecting the functions removes (BTI) protection from indirect jumps
// while technically out of scope of "find_branch_label", this is just
// cleaner overall.
if (mprotect(t, page_size, PROT_WRITE | PROT_READ | PROT_EXEC) != 0) {
if (mprotect(align_ptr_to_pagesize(t), page_size, PROT_WRITE | PROT_READ | PROT_EXEC) != 0) {
LOGW("Failed to remove BTI protection from private API page. This might fail.. %p", t);
}
return t;
@@ -3,7 +3,7 @@
//
int nsbypass_dlclose(void *handle);
void *nsbypass_dlopen(const char *libpath, int flags);
void *nsbypass_dlopen(const char *libPath, int flags);
void *nsbypass_dlsym(void *handle, const char *name);
typedef int (*dlclose_function)(