Skip to content

Commit

Permalink
improve: reset linker module counters
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
JingMatrix committed Dec 16, 2024
1 parent b9ea635 commit d973745
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 14 deletions.
35 changes: 30 additions & 5 deletions loader/src/include/solist.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -127,6 +130,27 @@ namespace SoList {
return path_found;
}

static void ResetCounters(size_t reset_number) {
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 >= reset_number) {
*g_module_load_counter = loaded_modules - reset_number;
LOGD("reset g_module_load_counter to %zu", (size_t) *g_module_load_counter);
}
if (unloaded_modules >= reset_number) {
*g_module_unload_counter = unloaded_modules - reset_number;
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;
Expand Down Expand Up @@ -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;
Expand All @@ -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 *);
Expand Down
17 changes: 11 additions & 6 deletions loader/src/injector/hook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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_unloaded, true);
}
}

/* Zygisksu changed: Load module fds */
Expand Down Expand Up @@ -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 reset_number, bool spoof_maps) {
LOGD("cleaning trace for path %s", path);

if (!SoList::DropSoPath(path) || !spoof_maps) {
return;
}
if (reset_number > 0) SoList::ResetCounters(reset_number);
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
Expand Down
5 changes: 3 additions & 2 deletions loader/src/injector/module.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include <cstring>
#include <dlfcn.h>
#include "api.hpp"

Expand Down Expand Up @@ -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; }

Expand All @@ -235,4 +236,4 @@ case 5: \
} mod;
};

} // namespace
} // namespace
2 changes: 1 addition & 1 deletion loader/src/injector/zygisk.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 reset_number = 1, bool spoof_maps = false);

void revert_unmount_ksu();

Expand Down

0 comments on commit d973745

Please sign in to comment.