Path: blob/v3_openjdk/app_pojavlauncher/src/main/jni/driver_helper/nsbypass.c
2128 views
//1// Created by maks on 05.06.2023.2//3#include "nsbypass.h"4#include <dlfcn.h>5#include <android/dlext.h>6#include <android/log.h>7#include <sys/mman.h>8#include <sys/user.h>9#include <string.h>10#include <stdio.h>11#include <linux/limits.h>12#include <errno.h>13#include <unistd.h>14#include <asm/unistd.h>15#include <fcntl.h>16#include <sys/stat.h>17#include <elf.h>1819/* upper 6 bits of an ARM64 instruction are the instruction name */20#define OP_MS 0b1111110000000000000000000000000021/* Branch Label instruction opcode and immediate mask */22#define BL_OP 0b1001010000000000000000000000000023#define BL_IM 0b0000001111111111111111111111111124/* Library search path */25#define SEARCH_PATH "/system/lib64"26#define ELF_EHDR Elf64_Ehdr27#define ELF_SHDR Elf64_Shdr28#define ELF_HALF Elf64_Half29#define ELF_XWORD Elf64_Xword30#define ELF_DYN Elf64_Dyn3132//#define ADRENO_POSSIBLE3334typedef void* (*loader_dlopen_t)(const char* filename, int flags, const void* caller_addr);3536typedef struct android_namespace_t* (*ld_android_create_namespace_t)(37const char* name, const char* ld_library_path, const char* default_library_path, uint64_t type,38const char* permitted_when_isolated_path, struct android_namespace_t* parent, const void* caller_addr);3940typedef void* (*ld_android_link_namespaces_t)(struct android_namespace_t* namespace_from,41struct android_namespace_t* namespace_to,42const char* shared_libs_sonames);4344static ld_android_create_namespace_t android_create_namespace;45static struct android_namespace_t* driver_namespace;4647struct android_namespace_t* local_android_create_namespace(48const char* name, const char* ld_library_path, const char* default_library_path, uint64_t type,49const char* permitted_when_isolated_path, struct android_namespace_t* parent) {50void* caller = __builtin_return_address(0);51return android_create_namespace(name, ld_library_path, default_library_path, type, permitted_when_isolated_path, parent, caller);52}5354// Find the first "branch to label" function in the function provided in func_start55static void* find_branch_label(void* func_start) {56// round down the pointer to get the start of the function's page57void* func_page_start = (void*)(((uintptr_t)func_start) & ~(PAGE_SIZE-1));58// remap to r-x to bypass "execute only" protections on MIUI59mprotect(func_page_start, PAGE_SIZE, PROT_READ | PROT_EXEC);60uint32_t* bl_addr = func_start;61// search for the "branch to label" opcode62while((*bl_addr & OP_MS) != BL_OP) {63bl_addr++; // walk through memory until we find it or die64}65// offset the address to find where the "branch to label" instrunction66// points to.67return ((char*)bl_addr) + (*bl_addr & BL_IM) * 4;68}6970bool linker_ns_load(const char* lib_search_path) {71#ifndef ADRENO_POSSIBLE72return false;73#else74loader_dlopen_t loader_dlopen = find_branch_label(&dlopen);75// reprotecting the functions removes protection from indirect jumps76mprotect(loader_dlopen, PAGE_SIZE, PROT_WRITE | PROT_READ | PROT_EXEC);77void* ld_android_handle = loader_dlopen("ld-android.so", RTLD_LAZY, &dlopen);78if(ld_android_handle == NULL) {79return false;80}81// load the two functions we need82android_create_namespace = dlsym(ld_android_handle, "__loader_android_create_namespace");83ld_android_link_namespaces_t android_link_namespaces = dlsym(ld_android_handle, "__loader_android_link_namespaces");84if(android_create_namespace == NULL || android_link_namespaces == NULL) {85dlclose(ld_android_handle);86return false;87}88// assemble the full path search path89char full_path[strlen(SEARCH_PATH) + strlen(lib_search_path) + 2 + 1];90sprintf(full_path, "%s:%s", SEARCH_PATH, lib_search_path);91driver_namespace = local_android_create_namespace("pojav-driver",92full_path,93full_path,943 /* TYPE_SHAFED | TYPE_ISOLATED */,95"/system/:/data/:/vendor/:/apex/", NULL);96// THIS IS VERY IMPORTANT and how I trolled FoldCraft:97// You need to link the new driver_namespace with NULL and and add ld-android.so98// in the link list, to pass through the driver_namespace correctly.99// Not doing this fucks up internal __loader symbol lookup100// inside the new driver_namespace, thus breaking it on101// a lot of android versions102// FoldCraft got trolled because they copied the103// old broken code verbatim and didn't even test it thoroughly104android_link_namespaces(driver_namespace, NULL, "ld-android.so");105// Also establish links to use the libnativeloader(_lazy).so libraries106// from the global namespace. This is a workaround for an EMUI issue where107// the newly loaded libnativeloader_lazy for some unknown reason links108// to itself and causes a deadlock when loading the vulkan driver.109android_link_namespaces(driver_namespace, NULL, "libnativeloader.so");110android_link_namespaces(driver_namespace, NULL, "libnativeloader_lazy.so");111dlclose(ld_android_handle);112return true;113#endif114}115116void* linker_ns_dlopen(const char* name, int flag) {117#ifndef ADRENO_POSSIBLE118return NULL;119#else120android_dlextinfo dlextinfo;121dlextinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;122dlextinfo.library_namespace = driver_namespace;123return android_dlopen_ext(name, flag, &dlextinfo);124#endif125}126127bool patch_elf_soname(int patchfd, int realfd, uint16_t patchid) {128struct stat realstat;129if(fstat(realfd, &realstat)) return false;130if(ftruncate64(patchfd, realstat.st_size) == -1) return false;131char* target = mmap(NULL, realstat.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, patchfd, 0);132if(!target) return false;133if(read(realfd, target, realstat.st_size) != realstat.st_size) {134munmap(target, realstat.st_size);135return false;136}137close(realfd);138139140ELF_EHDR *ehdr = (ELF_EHDR*)target;141ELF_SHDR *shdr = (ELF_SHDR*)(target + ehdr->e_shoff);142for(ELF_HALF i = 0; i < ehdr->e_shnum; i++) {143ELF_SHDR *hdr = &shdr[i];144if(hdr->sh_type == SHT_DYNAMIC) {145char* strtab = target + shdr[hdr->sh_link].sh_offset;146// If there's a warning below, it's bogus, ignore it147ELF_DYN *dynEntries = (ELF_DYN*)(target + hdr->sh_offset);148for(ELF_XWORD k = 0; k < (hdr->sh_size / hdr->sh_entsize);k++) {149ELF_DYN* dynEntry = &dynEntries[k];150if(dynEntry->d_tag == DT_SONAME) {151char* soname = strtab + dynEntry->d_un.d_val;152char sprb[4];153snprintf(sprb, 4, "%03x", patchid);154memcpy(soname, sprb, 3);155munmap(target, realstat.st_size);156return true;157}158}159}160}161return false;162}163164void* linker_ns_dlopen_unique(const char* tmpdir, const char* name, int flags) {165#ifndef ADRENO_POSSIBLE166return NULL;167#else168char pathbuf[PATH_MAX];169static uint16_t patch_id;170int patch_fd, real_fd;171snprintf(pathbuf,PATH_MAX,"%s/%d_p.so", tmpdir, patch_id);172patch_fd = open(pathbuf, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);173if(patch_fd == -1) return NULL;174snprintf(pathbuf,PATH_MAX,"%s/%s", SEARCH_PATH, name);175real_fd = open(pathbuf, O_RDONLY);176if(real_fd == -1) {177close(patch_fd);178return NULL;179}180if(!patch_elf_soname(patch_fd, real_fd, patch_id)) {181close(patch_fd);182close(real_fd);183return NULL;184}185android_dlextinfo extinfo;186extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE | ANDROID_DLEXT_USE_LIBRARY_FD;187extinfo.library_fd = patch_fd;188extinfo.library_namespace = driver_namespace;189snprintf(pathbuf, PATH_MAX, "/proc/self/fd/%d", patch_fd);190return android_dlopen_ext(pathbuf, flags, &extinfo);191#endif192}193194195