#include "bionic_linker_restriction.h" #include #include #include #include #include #include #include #include #include #include #include #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 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 linker_solist; std::vector 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 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 orig_ld_library_paths = *(std::vector *)((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 paths(orig_ld_library_paths.begin(), orig_ld_library_paths.end()); orig_ld_library_paths.assign(paths.begin(), paths.end()); } } else { *(std::vector *)((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"); }