You've already forked ReZygisk
mirror of
https://github.com/PerformanC/ReZygisk.git
synced 2025-09-06 06:37:01 +00:00
add: drop soinfo for libzygisk.so
1. fix typo vsdo -> vdso and allow this symbol to be not found, which is the case for the 32bit linkers on some devices 2. use soinfo_free to fully remove the soinfo record of libzygisk.so 3. set `soinfo.size = 0` to avoid the library being unmapped while removing its soinfo record 4. add more debug logs for troubleshooting
This commit is contained in:
@@ -11,20 +11,27 @@ namespace SoList {
|
|||||||
class SoInfo {
|
class SoInfo {
|
||||||
public:
|
public:
|
||||||
#ifdef __LP64__
|
#ifdef __LP64__
|
||||||
inline static size_t solist_next_offset = 0x30;
|
inline static size_t solist_size_offset = 0x18;
|
||||||
|
inline static size_t solist_next_offset = 0x28;
|
||||||
constexpr static size_t solist_realpath_offset = 0x1a8;
|
constexpr static size_t solist_realpath_offset = 0x1a8;
|
||||||
#else
|
#else
|
||||||
|
inline static size_t solist_size_offset = 0x90;
|
||||||
inline static size_t solist_next_offset = 0xa4;
|
inline static size_t solist_next_offset = 0xa4;
|
||||||
constexpr static size_t solist_realpath_offset = 0x174;
|
constexpr static size_t solist_realpath_offset = 0x174;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
inline static const char *(*get_realpath_sym)(SoInfo *) = NULL;
|
inline static const char *(*get_realpath_sym)(SoInfo *) = NULL;
|
||||||
inline static const char *(*get_soname_sym)(SoInfo *) = NULL;
|
inline static const char *(*get_soname_sym)(SoInfo *) = NULL;
|
||||||
|
inline static void (*soinfo_free)(SoInfo *) = NULL;
|
||||||
|
|
||||||
inline SoInfo *get_next() {
|
inline SoInfo *get_next() {
|
||||||
return *(SoInfo **) ((uintptr_t) this + solist_next_offset);
|
return *(SoInfo **) ((uintptr_t) this + solist_next_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline size_t get_size() {
|
||||||
|
return *(size_t *) ((uintptr_t) this + solist_size_offset);
|
||||||
|
}
|
||||||
|
|
||||||
inline const char *get_path() {
|
inline const char *get_path() {
|
||||||
if (get_realpath_sym) return get_realpath_sym(this);
|
if (get_realpath_sym) return get_realpath_sym(this);
|
||||||
|
|
||||||
@@ -40,6 +47,10 @@ namespace SoList {
|
|||||||
void set_next(SoInfo *si) {
|
void set_next(SoInfo *si) {
|
||||||
*(SoInfo **) ((uintptr_t) this + solist_next_offset) = si;
|
*(SoInfo **) ((uintptr_t) this + solist_next_offset) = si;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_size(size_t size) {
|
||||||
|
*(size_t *) ((uintptr_t) this + solist_size_offset) = size;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class ProtectedDataGuard {
|
class ProtectedDataGuard {
|
||||||
@@ -69,8 +80,8 @@ namespace SoList {
|
|||||||
private:
|
private:
|
||||||
using FuncType = void (ProtectedDataGuard::*)();
|
using FuncType = void (ProtectedDataGuard::*)();
|
||||||
|
|
||||||
static FuncType ctor;
|
inline static FuncType ctor = NULL;
|
||||||
static FuncType dtor;
|
inline static FuncType dtor = NULL;
|
||||||
|
|
||||||
union MemFunc {
|
union MemFunc {
|
||||||
FuncType f;
|
FuncType f;
|
||||||
@@ -86,8 +97,6 @@ namespace SoList {
|
|||||||
static SoInfo *solist = NULL;
|
static SoInfo *solist = NULL;
|
||||||
static SoInfo *somain = NULL;
|
static SoInfo *somain = NULL;
|
||||||
static SoInfo **sonext = NULL;
|
static SoInfo **sonext = NULL;
|
||||||
ProtectedDataGuard::FuncType ProtectedDataGuard::ctor = NULL;
|
|
||||||
ProtectedDataGuard::FuncType ProtectedDataGuard::dtor = NULL;
|
|
||||||
|
|
||||||
static bool Initialize();
|
static bool Initialize();
|
||||||
|
|
||||||
@@ -103,23 +112,22 @@ namespace SoList {
|
|||||||
LOGE("Failed to initialize solist");
|
LOGE("Failed to initialize solist");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SoInfo *prev = NULL;
|
|
||||||
for (auto iter = solist; iter; iter = iter->get_next()) {
|
for (auto iter = solist; iter; iter = iter->get_next()) {
|
||||||
if (prev != NULL && iter->get_name() && iter->get_path() && strstr(iter->get_path(), target_path)) {
|
if (iter->get_name() && iter->get_path() && strstr(iter->get_path(), target_path)) {
|
||||||
SoList::ProtectedDataGuard guard;
|
SoList::ProtectedDataGuard guard;
|
||||||
prev->set_next(iter->get_next());
|
LOGI("dropping solist record for %s loaded at %s with size %zu", iter->get_name(), iter->get_path(), iter->get_size());
|
||||||
if (iter == *sonext) {
|
if (iter->get_size() > 0) {
|
||||||
*sonext = prev;
|
iter->set_size(0);
|
||||||
|
SoInfo::soinfo_free(iter);
|
||||||
}
|
}
|
||||||
LOGI("Dropped solist record for %s loaded at %s", iter->get_name(), iter->get_path());
|
|
||||||
}
|
}
|
||||||
prev = iter;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool Initialize() {
|
static bool Initialize() {
|
||||||
SandHook::ElfImg linker("/linker");
|
SandHook::ElfImg linker("/linker");
|
||||||
if (!ProtectedDataGuard::setup(linker)) return false;
|
if (!ProtectedDataGuard::setup(linker)) return false;
|
||||||
|
LOGD("found symbol ProtectedDataGuard");
|
||||||
|
|
||||||
/* INFO: Since Android 15, the symbol names for the linker have a suffix,
|
/* INFO: Since Android 15, the symbol names for the linker have a suffix,
|
||||||
this makes it impossible to hardcode the symbol names. To allow
|
this makes it impossible to hardcode the symbol names. To allow
|
||||||
@@ -131,6 +139,11 @@ namespace SoList {
|
|||||||
|
|
||||||
std::string_view solist_sym_name = linker.findSymbolNameByPrefix("__dl__ZL6solist");
|
std::string_view solist_sym_name = linker.findSymbolNameByPrefix("__dl__ZL6solist");
|
||||||
if (solist_sym_name.empty()) return false;
|
if (solist_sym_name.empty()) return false;
|
||||||
|
LOGD("found symbol name %s", solist_sym_name.data());
|
||||||
|
|
||||||
|
std::string_view soinfo_free_name = linker.findSymbolNameByPrefix("__dl__ZL11soinfo_freeP6soinfo");
|
||||||
|
if (soinfo_free_name.empty()) return false;
|
||||||
|
LOGD("found symbol name %s", soinfo_free_name.data());
|
||||||
|
|
||||||
/* INFO: The size isn't a magic number, it's the size for the string: .llvm.7690929523238822858 */
|
/* INFO: The size isn't a magic number, it's the size for the string: .llvm.7690929523238822858 */
|
||||||
char llvm_sufix[25 + 1];
|
char llvm_sufix[25 + 1];
|
||||||
@@ -143,6 +156,7 @@ namespace SoList {
|
|||||||
|
|
||||||
solist = getStaticPointer<SoInfo>(linker, solist_sym_name.data());
|
solist = getStaticPointer<SoInfo>(linker, solist_sym_name.data());
|
||||||
if (solist == NULL) return false;
|
if (solist == NULL) return false;
|
||||||
|
LOGD("found symbol solist");
|
||||||
|
|
||||||
char somain_sym_name[sizeof("__dl__ZL6somain") + sizeof(llvm_sufix)];
|
char somain_sym_name[sizeof("__dl__ZL6somain") + sizeof(llvm_sufix)];
|
||||||
snprintf(somain_sym_name, sizeof(somain_sym_name), "__dl__ZL6somain%s", llvm_sufix);
|
snprintf(somain_sym_name, sizeof(somain_sym_name), "__dl__ZL6somain%s", llvm_sufix);
|
||||||
@@ -150,30 +164,51 @@ namespace SoList {
|
|||||||
char sonext_sym_name[sizeof("__dl__ZL6sonext") + sizeof(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);
|
snprintf(sonext_sym_name, sizeof(somain_sym_name), "__dl__ZL6sonext%s", llvm_sufix);
|
||||||
|
|
||||||
char vsdo_sym_name[sizeof("__dl__ZL4vdso") + sizeof(llvm_sufix)];
|
char vdso_sym_name[sizeof("__dl__ZL4vdso") + sizeof(llvm_sufix)];
|
||||||
snprintf(vsdo_sym_name, sizeof(vsdo_sym_name), "__dl__ZL4vdso%s", llvm_sufix);
|
snprintf(vdso_sym_name, sizeof(vdso_sym_name), "__dl__ZL4vdso%s", llvm_sufix);
|
||||||
|
|
||||||
somain = getStaticPointer<SoInfo>(linker, somain_sym_name);
|
somain = getStaticPointer<SoInfo>(linker, somain_sym_name);
|
||||||
if (somain == NULL) return false;
|
if (somain == NULL) return false;
|
||||||
|
LOGD("found symbol somain");
|
||||||
|
|
||||||
sonext = linker.getSymbAddress<SoInfo **>(sonext_sym_name);
|
sonext = linker.getSymbAddress<SoInfo **>(sonext_sym_name);
|
||||||
if (sonext == NULL) return false;
|
if (sonext == NULL) return false;
|
||||||
|
LOGD("found symbol sonext");
|
||||||
|
|
||||||
SoInfo *vsdo = getStaticPointer<SoInfo>(linker, vsdo_sym_name);
|
SoInfo *vdso = getStaticPointer<SoInfo>(linker, vdso_sym_name);
|
||||||
if (vsdo == NULL) return false;
|
if (vdso != NULL) {
|
||||||
|
LOGD("found symbol vdso");
|
||||||
|
} else {
|
||||||
|
LOGD("symbol vdso is missing");
|
||||||
|
}
|
||||||
|
|
||||||
SoInfo::get_realpath_sym = reinterpret_cast<decltype(SoInfo::get_realpath_sym)>(linker.getSymbAddress("__dl__ZNK6soinfo12get_realpathEv"));
|
SoInfo::get_realpath_sym = reinterpret_cast<decltype(SoInfo::get_realpath_sym)>(linker.getSymbAddress("__dl__ZNK6soinfo12get_realpathEv"));
|
||||||
|
if (SoInfo::get_realpath_sym == NULL) return false;
|
||||||
|
LOGD("found symbol get_realpath_sym");
|
||||||
|
|
||||||
SoInfo::get_soname_sym = reinterpret_cast<decltype(SoInfo::get_soname_sym)>(linker.getSymbAddress("__dl__ZNK6soinfo10get_sonameEv"));
|
SoInfo::get_soname_sym = reinterpret_cast<decltype(SoInfo::get_soname_sym)>(linker.getSymbAddress("__dl__ZNK6soinfo10get_sonameEv"));
|
||||||
|
if (SoInfo::get_soname_sym == NULL) return false;
|
||||||
|
LOGD("found symbol get_soname_sym");
|
||||||
|
|
||||||
|
SoInfo::soinfo_free = reinterpret_cast<decltype(SoInfo::soinfo_free)>(linker.getSymbAddress(soinfo_free_name));
|
||||||
|
if (SoInfo::soinfo_free == NULL) return false;
|
||||||
|
LOGD("found symbol soinfo_free");
|
||||||
|
|
||||||
|
|
||||||
for (size_t i = 0; i < 1024 / sizeof(void *); i++) {
|
for (size_t i = 0; i < 1024 / sizeof(void *); i++) {
|
||||||
auto *possible_next = *(void **) ((uintptr_t) solist + i * sizeof(void *));
|
auto possible_field = (uintptr_t) solist + i * sizeof(void *);
|
||||||
if (possible_next == somain || (vsdo != NULL && possible_next == vsdo)) {
|
auto possible_size_of_somain = *(size_t *)((uintptr_t) somain + i * sizeof(void *));
|
||||||
|
if (possible_size_of_somain < 0x100000 && possible_size_of_somain > 0x100) {
|
||||||
|
SoInfo::solist_size_offset = i * sizeof(void *);
|
||||||
|
LOGD("solist_size_offset is %zu * %zu = %p", i, sizeof(void *), (void*) SoInfo::solist_size_offset);
|
||||||
|
}
|
||||||
|
if (*(void **)possible_field == somain || (vdso != NULL && *(void **)possible_field == vdso)) {
|
||||||
SoInfo::solist_next_offset = i * sizeof(void *);
|
SoInfo::solist_next_offset = i * sizeof(void *);
|
||||||
|
LOGD("solist_next_offset is %zu * %zu = %p", i, sizeof(void *), (void*) SoInfo::solist_next_offset);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (SoInfo::get_realpath_sym != NULL && SoInfo::get_soname_sym != NULL);
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ void entry(void* addr, size_t size, const char* path) {
|
|||||||
logging::setfd(zygiskd::RequestLogcatFd());
|
logging::setfd(zygiskd::RequestLogcatFd());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
LOGI("Start hooking, call %p", hook_functions);
|
LOGI("start plt hooking");
|
||||||
hook_functions();
|
hook_functions();
|
||||||
|
clean_trace(path);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -185,14 +185,13 @@ DCL_HOOK_FUNC(int, pthread_attr_setstacksize, void *target, size_t size) {
|
|||||||
if (gettid() != getpid())
|
if (gettid() != getpid())
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
LOGV("Clean zygisk reminders");
|
|
||||||
if (should_unmap_zygisk) {
|
if (should_unmap_zygisk) {
|
||||||
unhook_functions();
|
unhook_functions();
|
||||||
if (should_unmap_zygisk) {
|
if (should_unmap_zygisk) {
|
||||||
// Because both `pthread_attr_setstacksize` and `dlclose` have the same function signature,
|
// Because both `pthread_attr_setstacksize` and `dlclose` have the same function signature,
|
||||||
// we can use `musttail` to let the compiler reuse our stack frame and thus
|
// we can use `musttail` to let the compiler reuse our stack frame and thus
|
||||||
// `dlclose` will directly return to the caller of `pthread_attr_setstacksize`.
|
// `dlclose` will directly return to the caller of `pthread_attr_setstacksize`.
|
||||||
LOGV("Unmap libzygisk.so");
|
LOGI("unmap libzygisk.so loaded at %p with size %zu", start_addr, block_size);
|
||||||
[[clang::musttail]] return munmap(start_addr, block_size);
|
[[clang::musttail]] return munmap(start_addr, block_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -584,7 +583,7 @@ void ZygiskContext::run_modules_post() {
|
|||||||
m.tryUnload();
|
m.tryUnload();
|
||||||
}
|
}
|
||||||
|
|
||||||
SoList::DropSoPath("jit-cache");
|
clean_trace("jit-cache");
|
||||||
|
|
||||||
// Remap as well to avoid checking of /memfd:jit-cache
|
// Remap as well to avoid checking of /memfd:jit-cache
|
||||||
for (auto &info : lsplt::MapInfo::Scan()) {
|
for (auto &info : lsplt::MapInfo::Scan()) {
|
||||||
@@ -816,6 +815,11 @@ static void hook_register(dev_t dev, ino_t inode, const char *symbol, void *new_
|
|||||||
#define PLT_HOOK_REGISTER(DEV, INODE, NAME) \
|
#define PLT_HOOK_REGISTER(DEV, INODE, NAME) \
|
||||||
PLT_HOOK_REGISTER_SYM(DEV, INODE, #NAME, NAME)
|
PLT_HOOK_REGISTER_SYM(DEV, INODE, #NAME, NAME)
|
||||||
|
|
||||||
|
void clean_trace(const char* path) {
|
||||||
|
LOGD("clean solist trace for path %s", path);
|
||||||
|
SoList::DropSoPath(path);
|
||||||
|
}
|
||||||
|
|
||||||
void hook_functions() {
|
void hook_functions() {
|
||||||
default_new(plt_hook_list);
|
default_new(plt_hook_list);
|
||||||
default_new(jni_hook_list);
|
default_new(jni_hook_list);
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ extern size_t block_size;
|
|||||||
|
|
||||||
void hook_functions();
|
void hook_functions();
|
||||||
|
|
||||||
|
void clean_trace(const char* path);
|
||||||
|
|
||||||
void revert_unmount_ksu();
|
void revert_unmount_ksu();
|
||||||
|
|
||||||
void revert_unmount_magisk();
|
void revert_unmount_magisk();
|
||||||
|
|||||||
Reference in New Issue
Block a user