geode/loader/dobby/builtin-plugin/BionicLinkerRestriction/bionic_linker_restriction.cc
2022-07-30 19:24:03 +03:00

197 lines
6.6 KiB
C++

#include "bionic_linker_restriction.h"
#include <elf.h>
#include <jni.h>
#include <string>
#include <dlfcn.h>
#include <link.h>
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
#include <unordered_map>
#include <vector>
#include <set>
#include "dobby.h"
#include "dobby_symbol_resolver.h"
#include "common_header.h"
#undef LOG_TAG
#define LOG_TAG "AndroidLinkerRestriction"
#undef Q
#define Q 29
// impl at "dobby_symbol_resolver.cc"
extern void *resolve_elf_internal_symbol(const char *library_name, const char *symbol_name);
#include <sys/system_properties.h>
static int get_android_system_version() {
char os_version_str[PROP_VALUE_MAX + 1];
__system_property_get("ro.build.version.release", os_version_str);
int os_version_int = atoi(os_version_str);
return os_version_int;
}
static const char *get_android_linker_path() {
#if __LP64__
if (get_android_system_version() >= Q) {
return (const char *)"/apex/com.android.runtime/bin/linker64";
} else {
return (const char *)"/system/bin/linker64";
}
#else
if (get_android_system_version() >= Q) {
return (const char *)"/apex/com.android.runtime/bin/linker";
} else {
return (const char *)"/system/bin/linker";
}
#endif
}
PUBLIC void *linker_dlopen(const char *filename, int flag) {
typedef void *(*__loader_dlopen_t)(const char *filename, int flags, const void *caller_addr);
static __loader_dlopen_t __loader_dlopen = NULL;
if (!__loader_dlopen)
__loader_dlopen = (__loader_dlopen_t)DobbySymbolResolver(NULL, "__loader_dlopen");
// fake caller address
void *open_ptr = dlsym(RTLD_DEFAULT, "open");
return __loader_dlopen(filename, flag, (const void *)open_ptr);
}
std::vector<soinfo_t> linker_solist;
std::vector<soinfo_t> linker_get_solist() {
if (!linker_solist.empty()) {
linker_solist.clear();
}
static soinfo_t (*solist_get_head)() = NULL;
if (!solist_get_head)
solist_get_head =
(soinfo_t(*)())resolve_elf_internal_symbol(get_android_linker_path(), "__dl__Z15solist_get_headv");
static soinfo_t (*solist_get_somain)() = NULL;
if (!solist_get_somain)
solist_get_somain =
(soinfo_t(*)())resolve_elf_internal_symbol(get_android_linker_path(), "__dl__Z17solist_get_somainv");
static addr_t *solist_head = NULL;
if (!solist_head)
solist_head = (addr_t *)solist_get_head();
static addr_t somain = 0;
if (!somain)
somain = (addr_t)solist_get_somain();
// Generate the name for an offset.
#define PARAM_OFFSET(type_, member_) __##type_##__##member_##__offset_
#define STRUCT_OFFSET PARAM_OFFSET
int STRUCT_OFFSET(solist, next) = 0;
for (size_t i = 0; i < 1024 / sizeof(void *); i++) {
if (*(addr_t *)((addr_t)solist_head + i * sizeof(void *)) == somain) {
STRUCT_OFFSET(solist, next) = i * sizeof(void *);
break;
}
}
linker_solist.push_back(solist_head);
addr_t sonext = 0;
sonext = *(addr_t *)((addr_t)solist_head + STRUCT_OFFSET(solist, next));
while (sonext) {
linker_solist.push_back((void *)sonext);
sonext = *(addr_t *)((addr_t)sonext + STRUCT_OFFSET(solist, next));
}
return linker_solist;
}
char *linker_soinfo_get_realpath(soinfo_t soinfo) {
static char *(*_get_realpath)(soinfo_t) = NULL;
if (!_get_realpath)
_get_realpath =
(char *(*)(soinfo_t))resolve_elf_internal_symbol(get_android_linker_path(), "__dl__ZNK6soinfo12get_realpathEv");
return _get_realpath(soinfo);
}
uintptr_t linker_soinfo_to_handle(soinfo_t soinfo) {
static uintptr_t (*_linker_soinfo_to_handle)(soinfo_t) = NULL;
if (!_linker_soinfo_to_handle)
_linker_soinfo_to_handle =
(uintptr_t(*)(soinfo_t))resolve_elf_internal_symbol(get_android_linker_path(), "__dl__ZN6soinfo9to_handleEv");
return _linker_soinfo_to_handle(soinfo);
}
typedef void *android_namespace_t;
android_namespace_t linker_soinfo_get_primary_namespace(soinfo_t soinfo) {
static android_namespace_t (*_get_primary_namespace)(soinfo_t) = NULL;
if (!_get_primary_namespace)
_get_primary_namespace = (android_namespace_t(*)(soinfo_t))resolve_elf_internal_symbol(
get_android_linker_path(), "__dl__ZN6soinfo21get_primary_namespaceEv");
return _get_primary_namespace(soinfo);
}
void linker_iterate_soinfo(int (*cb)(soinfo_t soinfo)) {
auto solist = linker_get_solist();
for (auto it = solist.begin(); it != solist.end(); it++) {
int ret = cb(*it);
if (ret != 0)
break;
}
}
static int iterate_soinfo_cb(soinfo_t soinfo) {
android_namespace_t ns = NULL;
ns = linker_soinfo_get_primary_namespace(soinfo);
LOG(1, "lib: %s", linker_soinfo_get_realpath(soinfo));
// set is_isolated_ as false
// no need for this actually
int STRUCT_OFFSET(android_namespace_t, is_isolated_) = 0x8;
*(uint8_t *)((addr_t)ns + STRUCT_OFFSET(android_namespace_t, is_isolated_)) = false;
std::vector<std::string> ld_library_paths = {"/system/lib64", "/sytem/lib"};
if (get_android_system_version() >= Q) {
ld_library_paths.push_back("/apex/com.android.runtime/lib64");
ld_library_paths.push_back("/apex/com.android.runtime/lib");
}
int STRUCT_OFFSET(android_namespace_t, ld_library_paths_) = 0x10;
if (*(void **)((addr_t)ns + STRUCT_OFFSET(android_namespace_t, ld_library_paths_))) {
std::vector<std::string> orig_ld_library_paths =
*(std::vector<std::string> *)((addr_t)ns + STRUCT_OFFSET(android_namespace_t, ld_library_paths_));
orig_ld_library_paths.insert(orig_ld_library_paths.end(), ld_library_paths.begin(), ld_library_paths.end());
// remove duplicates
{
std::set<std::string> paths(orig_ld_library_paths.begin(), orig_ld_library_paths.end());
orig_ld_library_paths.assign(paths.begin(), paths.end());
}
} else {
*(std::vector<std::string> *)((addr_t)ns + STRUCT_OFFSET(android_namespace_t, ld_library_paths_)) =
std::move(ld_library_paths);
}
return 0;
}
bool (*orig_linker_namespace_is_is_accessible)(android_namespace_t ns, const std::string &file);
bool linker_namespace_is_is_accessible(android_namespace_t ns, const std::string &file) {
LOG(1, "check %s", file.c_str());
return true;
return orig_linker_namespace_is_is_accessible(ns, file);
}
void linker_disable_namespace_restriction() {
linker_iterate_soinfo(iterate_soinfo_cb);
// no need for this actually
void *linker_namespace_is_is_accessible_ptr = resolve_elf_internal_symbol(
get_android_linker_path(), "__dl__ZN19android_namespace_t13is_accessibleERKNSt3__112basic_"
"stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE");
DobbyHook(linker_namespace_is_is_accessible_ptr, (void *)linker_namespace_is_is_accessible,
(void **)&orig_linker_namespace_is_is_accessible);
LOG(1, "disable namespace restriction done");
}