mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-02-19 20:18:29 +00:00
New way to unload zygisk
Co-authored-by: 残页 <a1364259@163.com>
This commit is contained in:
parent
e48afff5e8
commit
3a4fe53f27
@ -1,3 +1,4 @@
|
||||
{
|
||||
zygisk_inject_entry;
|
||||
unload_first_stage;
|
||||
};
|
||||
|
@ -43,13 +43,10 @@ static void zygisk_cleanup_wait() {
|
||||
}
|
||||
}
|
||||
|
||||
static void *unload_first_stage(void *) {
|
||||
// Wait 10us to make sure 1st stage is done
|
||||
timespec ts = { .tv_sec = 0, .tv_nsec = 10000L };
|
||||
nanosleep(&ts, nullptr);
|
||||
extern "C" void unload_first_stage() {
|
||||
ZLOGD("unloading first stage\n");
|
||||
unmap_all(HIJACK_BIN);
|
||||
xumount2(HIJACK_BIN, MNT_DETACH);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
extern "C" void zygisk_inject_entry(void *handle) {
|
||||
@ -70,7 +67,6 @@ extern "C" void zygisk_inject_entry(void *handle) {
|
||||
unsetenv(MAGISKTMP_ENV);
|
||||
sanitize_environ();
|
||||
hook_functions();
|
||||
new_daemon_thread(&unload_first_stage, nullptr);
|
||||
}
|
||||
|
||||
// The following code runs in zygote/app process
|
||||
|
@ -259,6 +259,29 @@ DCL_HOOK_FUNC(int, selinux_android_setcontext,
|
||||
return old_selinux_android_setcontext(uid, isSystemServer, seinfo, pkgname);
|
||||
}
|
||||
|
||||
dev_t art_dev = 0;
|
||||
ino_t art_inode = 0;
|
||||
pthread_t main_thread = 0;
|
||||
DCL_HOOK_FUNC(int, pthread_attr_destroy, void* target) {
|
||||
int res = old_pthread_attr_destroy((pthread_attr_t *)target);
|
||||
|
||||
if (main_thread != pthread_self()) {
|
||||
return res;
|
||||
}
|
||||
|
||||
ZLOGD("pthread_attr_destroy(%p)\n", target);
|
||||
|
||||
lsplt::RegisterHook(art_dev, art_inode, "pthread_attr_destroy", reinterpret_cast<void*>(*old_pthread_attr_destroy), nullptr);
|
||||
lsplt::CommitHook();
|
||||
|
||||
// Directly call `dlclose` will crash because when `dlclose` returns, CPU will try to execute code at an
|
||||
// unmapped address. Because both `pthread_attr_destroy` and `dlclose` have same
|
||||
// parameter types (a pointer) and return type (an int), the way they treat arguments and results
|
||||
// are the same. We can use `musttail` to let the compiler reuse our stack frame and thus
|
||||
// dlclose will directly return to the caller of `pthread_attr_destroy`
|
||||
[[clang::musttail]] return dlclose(self_handle);
|
||||
}
|
||||
|
||||
#undef DCL_HOOK_FUNC
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
@ -646,7 +669,23 @@ void HookContext::unload_zygisk() {
|
||||
m.clearApi();
|
||||
}
|
||||
|
||||
new_daemon_thread(reinterpret_cast<thread_entry>(&dlclose), self_handle);
|
||||
// We cannot directly `dlclose` ourselves here, otherwise when `dlclose` returns, it will return
|
||||
// to our code which have been unmapped, causing a segment fault. Instead, we hook
|
||||
// `pthread_attr_destroy` which will be called when VM daemon threads start and
|
||||
// do some magic. Check comment in our replacement of the function for more info.
|
||||
for (auto &map : lsplt::MapInfo::Scan()) {
|
||||
if (map.path.ends_with("/libart.so")) {
|
||||
ZLOGD("hook pthread_attr_destroy\n");
|
||||
art_inode = map.inode;
|
||||
art_dev = map.dev;
|
||||
main_thread = pthread_self();
|
||||
lsplt::RegisterHook(art_dev, art_inode, "pthread_attr_destroy",
|
||||
reinterpret_cast<void *>(new_pthread_attr_destroy),
|
||||
reinterpret_cast<void **>(&old_pthread_attr_destroy));
|
||||
lsplt::CommitHook();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
#endif
|
||||
|
||||
__attribute__((constructor))
|
||||
static void zygisk_loader() {
|
||||
static void zygisk_loader(void) {
|
||||
android_dlextinfo info = {
|
||||
.flags = ANDROID_DLEXT_FORCE_LOAD
|
||||
};
|
||||
@ -20,5 +20,9 @@ static void zygisk_loader() {
|
||||
if (entry) {
|
||||
entry(handle);
|
||||
}
|
||||
void (*unload)(void) = dlsym(handle, "unload_first_stage");
|
||||
if (unload) {
|
||||
__attribute__((musttail)) return unload();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user