diff --git a/loader/src/include/solist.hpp b/loader/src/include/solist.hpp index 73ff917f..63074d26 100644 --- a/loader/src/include/solist.hpp +++ b/loader/src/include/solist.hpp @@ -36,23 +36,61 @@ namespace SoList { return ((std::string *) ((uintptr_t) this + solist_realpath_offset - sizeof(void *)))->c_str(); } - void nullify_name() { - const char **name = (const char**)get_soname_sym(this); + void set_next(SoInfo *si) { + *(SoInfo **) ((uintptr_t) this + solist_next_offset) = si; + } + }; - static const char *empty_string = ""; - *name = reinterpret_cast(&empty_string); + class ProtectedDataGuard { + public: + ProtectedDataGuard() { + if (ctor != nullptr) + (this->*ctor)(); } - void nullify_path() { - const char **name = (const char**)get_realpath_sym(this); + ~ProtectedDataGuard() { + if (dtor != nullptr) + (this->*dtor)(); + } - static const char *empty_string = ""; - *name = reinterpret_cast(&empty_string); + static bool setup(const SandHook::ElfImg &linker) { + ctor = MemFunc{.data = {.p = reinterpret_cast(linker.getSymbAddress( + "__dl__ZN18ProtectedDataGuardC2Ev")), + .adj = 0}} + .f; + dtor = MemFunc{.data = {.p = reinterpret_cast(linker.getSymbAddress( + "__dl__ZN18ProtectedDataGuardD2Ev")), + .adj = 0}} + .f; + return ctor != nullptr && dtor != nullptr; } + + ProtectedDataGuard(const ProtectedDataGuard &) = delete; + + void operator=(const ProtectedDataGuard &) = delete; + + private: + using FuncType = void (ProtectedDataGuard::*)(); + + static FuncType ctor; + static FuncType dtor; + + union MemFunc { + FuncType f; + + struct { + void *p; + std::ptrdiff_t adj; + } data; + }; }; + static SoInfo *solist = NULL; static SoInfo *somain = NULL; + static SoInfo **sonext = NULL; + ProtectedDataGuard::FuncType ProtectedDataGuard::ctor = NULL; + ProtectedDataGuard::FuncType ProtectedDataGuard::dtor = NULL; template inline T *getStaticPointer(const SandHook::ElfImg &linker, const char *name) { @@ -61,25 +99,24 @@ namespace SoList { return addr == NULL ? NULL : *addr; } - static void NullifySoName(const char* target_name) { - for (auto *iter = solist; iter; iter = iter->get_next()) { - if (iter->get_name() && iter->get_path() && strstr(iter->get_path(), target_name)) { - iter->nullify_path(); - LOGI("Cleared SOList entry for %s", target_name); - } - } - - for (auto *iter = somain; iter; iter = iter->get_next()) { - if (iter->get_name() && iter->get_path() && strstr(iter->get_path(), target_name)) { - iter->nullify_path(); - - break; + static void DropSoPath(const char* target_path) { + SoInfo *prev = NULL; + for (auto iter = solist; iter; iter = iter->get_next()) { + if (prev != NULL && iter->get_name() && iter->get_path() && strstr(iter->get_path(), target_path)) { + SoList::ProtectedDataGuard guard; + prev->set_next(iter->get_next()); + if (iter == *sonext) { + *sonext = prev; + } + LOGI("Dropped SoList entry for %s loaded at %s", iter->get_name(), iter->get_path()); } + prev = iter; } } static bool Initialize() { SandHook::ElfImg linker("/linker"); + if (!ProtectedDataGuard::setup(linker)) return false; /* INFO: Since Android 15, the symbol names for the linker have a suffix, this makes it impossible to hardcode the symbol names. To allow @@ -107,13 +144,20 @@ namespace SoList { char somain_sym_name[sizeof("__dl__ZL6somain") + sizeof(llvm_sufix)]; snprintf(somain_sym_name, sizeof(somain_sym_name), "__dl__ZL6somain%s", llvm_sufix); + char sonext_sym_name[sizeof("__dl__ZL6sonext") + sizeof(llvm_sufix)]; + snprintf(sonext_sym_name, sizeof(somain_sym_name), "__dl__ZL6sonext%s", llvm_sufix); + char vsdo_sym_name[sizeof("__dl__ZL4vdso") + sizeof(llvm_sufix)]; snprintf(vsdo_sym_name, sizeof(vsdo_sym_name), "__dl__ZL4vdso%s", llvm_sufix); somain = getStaticPointer(linker, somain_sym_name); if (somain == NULL) return false; - auto vsdo = getStaticPointer(linker, vsdo_sym_name); + sonext = linker.getSymbAddress(sonext_sym_name); + if (sonext == NULL) return false; + + SoInfo *vsdo = getStaticPointer(linker, vsdo_sym_name); + if (vsdo == NULL) return false; SoInfo::get_realpath_sym = reinterpret_cast(linker.getSymbAddress("__dl__ZNK6soinfo12get_realpathEv")); SoInfo::get_soname_sym = reinterpret_cast(linker.getSymbAddress("__dl__ZNK6soinfo10get_sonameEv")); diff --git a/loader/src/injector/hook.cpp b/loader/src/injector/hook.cpp index 4f02f6bf..f9b18871 100644 --- a/loader/src/injector/hook.cpp +++ b/loader/src/injector/hook.cpp @@ -587,7 +587,7 @@ void ZygiskContext::run_modules_post() { if (!solist_res) { LOGE("Failed to initialize SoList"); } else { - SoList::NullifySoName("jit-cache"); + SoList::DropSoPath("jit-cache"); } // Remap as well to avoid checking of /memfd:jit-cache