improve: reset linker module counters

Two counters for module loading and unloading are introduced in the commit https://cs.android.com/android/_/android/platform/bionic/+/a2e83ab34845759f0999d0ec88f4cdf558c0a9f5. To remove linker traces of libzygisk.so and Zygisk modules, we should reset them properly.
This commit is contained in:
JingMatrix
2024-12-16 10:08:09 +01:00
parent 5e072bd919
commit 0671f2e497
5 changed files with 46 additions and 15 deletions
+30 -5
View File
@@ -98,6 +98,9 @@ namespace SoList {
static SoInfo *somain = NULL;
static SoInfo **sonext = NULL;
static uint64_t *g_module_load_counter = NULL;
static uint64_t *g_module_unload_counter = NULL;
static bool Initialize();
template<typename T>
@@ -127,6 +130,27 @@ namespace SoList {
return path_found;
}
static void ResetCounters(size_t load, size_t unload) {
if (solist == NULL && !Initialize()) {
LOGE("Failed to initialize solist");
return;
}
if (g_module_load_counter == NULL || g_module_unload_counter == NULL) {
LOGI("g_module counters not defined, skip reseting them");
return;
}
auto loaded_modules = *g_module_load_counter;
auto unloaded_modules = *g_module_unload_counter;
if (loaded_modules >= load) {
*g_module_load_counter = loaded_modules - load;
LOGD("reset g_module_load_counter to %zu", (size_t) *g_module_load_counter);
}
if (unloaded_modules >= unload) {
*g_module_unload_counter = unloaded_modules - unload;
LOGD("reset g_module_unload_counter to %zu", (size_t) *g_module_unload_counter);
}
}
static bool Initialize() {
SandHook::ElfImg linker("/linker");
if (!ProtectedDataGuard::setup(linker)) return false;
@@ -179,11 +203,7 @@ namespace SoList {
LOGD("found symbol sonext");
SoInfo *vdso = getStaticPointer<SoInfo>(linker, vdso_sym_name);
if (vdso != NULL) {
LOGD("found symbol vdso");
} else {
LOGD("symbol vdso is missing");
}
if (vdso != NULL) LOGD("found symbol vdso");
SoInfo::get_realpath_sym = reinterpret_cast<decltype(SoInfo::get_realpath_sym)>(linker.getSymbAddress("__dl__ZNK6soinfo12get_realpathEv"));
if (SoInfo::get_realpath_sym == NULL) return false;
@@ -197,6 +217,11 @@ namespace SoList {
if (SoInfo::soinfo_free == NULL) return false;
LOGD("found symbol soinfo_free");
g_module_load_counter = reinterpret_cast<decltype(g_module_load_counter)>(linker.getSymbAddress("__dl__ZL21g_module_load_counter"));
if (g_module_load_counter != NULL) LOGD("found symbol g_module_load_counter");
g_module_unload_counter = reinterpret_cast<decltype(g_module_unload_counter)>(linker.getSymbAddress("__dl__ZL23g_module_unload_counter"));
if (g_module_unload_counter != NULL) LOGD("found symbol g_module_unload_counter");
for (size_t i = 0; i < 1024 / sizeof(void *); i++) {
auto possible_field = (uintptr_t) solist + i * sizeof(void *);
+1 -1
View File
@@ -25,5 +25,5 @@ void entry(void* addr, size_t size, const char* path) {
LOGI("start plt hooking");
hook_functions();
clean_trace(path);
clean_trace(path, 1, 0, false);
}
+11 -6
View File
@@ -578,16 +578,21 @@ void ZygiskContext::run_modules_pre() {
void ZygiskContext::run_modules_post() {
flags[POST_SPECIALIZE] = true;
size_t modules_unloaded = 0;
for (const auto &m : modules) {
if (flags[APP_SPECIALIZE]) {
m.postAppSpecialize(args.app);
} else if (flags[SERVER_FORK_AND_SPECIALIZE]) {
m.postServerSpecialize(args.server);
}
m.tryUnload();
if (m.tryUnload()) modules_unloaded++;
}
clean_trace("jit-cache-zygisk", true);
if (modules.size() > 0) {
LOGD("modules unloaded: %zu/%zu", modules_unloaded, modules.size());
clean_trace("jit-cache-zygisk", modules.size(), modules_unloaded, true);
}
}
/* Zygisksu changed: Load module fds */
@@ -746,12 +751,12 @@ static void hook_register(dev_t dev, ino_t inode, const char *symbol, void *new_
#define PLT_HOOK_REGISTER(DEV, INODE, NAME) \
PLT_HOOK_REGISTER_SYM(DEV, INODE, #NAME, NAME)
void clean_trace(const char* path, bool spoof_maps) {
void clean_trace(const char* path, size_t load, size_t unload, bool spoof_maps) {
LOGD("cleaning trace for path %s", path);
if (!SoList::DropSoPath(path) || !spoof_maps) {
return;
}
if (load > 0 || unload >0) SoList::ResetCounters(load, unload);
bool path_found = SoList::DropSoPath(path);
if (!path_found || !spoof_maps) return;
LOGD("spoofing virtual maps for %s", path);
// spoofing map names is futile in Android, we do it simply
+3 -2
View File
@@ -1,5 +1,6 @@
#pragma once
#include <cstring>
#include <dlfcn.h>
#include "api.hpp"
@@ -209,7 +210,7 @@ case 5: \
int getModuleDir() const;
void setOption(zygisk::Option opt);
static uint32_t getFlags();
void tryUnload() const { if (unload) dlclose(handle); }
bool tryUnload() const { return unload && dlclose(handle) == 0; };
void clearApi() { memset(&api, 0, sizeof(api)); }
int getId() const { return id; }
@@ -235,4 +236,4 @@ case 5: \
} mod;
};
} // namespace
} // namespace
+1 -1
View File
@@ -7,7 +7,7 @@ extern size_t block_size;
void hook_functions();
void clean_trace(const char* path, bool spoof_maps = false);
void clean_trace(const char* path, size_t load = 1, size_t unload = 0, bool spoof_maps = false);
void revert_unmount_ksu();