mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-11-27 20:15:29 +00:00
Unload first stage on main thread
This commit is contained in:
parent
12e9873514
commit
cf4ef54dc5
@ -16,7 +16,6 @@
|
|||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
static void *self_handle = nullptr;
|
static void *self_handle = nullptr;
|
||||||
static atomic<int> active_threads = -1;
|
|
||||||
|
|
||||||
static int zygisk_log(int prio, const char *fmt, va_list ap);
|
static int zygisk_log(int prio, const char *fmt, va_list ap);
|
||||||
|
|
||||||
@ -31,23 +30,19 @@ static void zygisk_logging() {
|
|||||||
|
|
||||||
void self_unload() {
|
void self_unload() {
|
||||||
LOGD("zygisk: Request to self unload\n");
|
LOGD("zygisk: Request to self unload\n");
|
||||||
// If deny failed, do not unload or else it will cause SIGSEGV
|
// If unhooking failed, do not unload or else it will cause SIGSEGV
|
||||||
if (!unhook_functions())
|
if (!unhook_functions())
|
||||||
return;
|
return;
|
||||||
new_daemon_thread(reinterpret_cast<thread_entry>(&dlclose), self_handle);
|
new_daemon_thread(reinterpret_cast<thread_entry>(&dlclose), self_handle);
|
||||||
active_threads--;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *unload_first_stage(void *v) {
|
static void unload_first_stage(int, siginfo_t *info, void *) {
|
||||||
// Wait 1ms to make sure first stage is completely done
|
auto path = static_cast<char *>(info->si_value.sival_ptr);
|
||||||
timespec ts = { .tv_sec = 0, .tv_nsec = 1000000L };
|
|
||||||
nanosleep(&ts, nullptr);
|
|
||||||
|
|
||||||
auto path = static_cast<const char *>(v);
|
|
||||||
unmap_all(path);
|
unmap_all(path);
|
||||||
free(v);
|
free(path);
|
||||||
active_threads--;
|
struct sigaction action{};
|
||||||
return nullptr;
|
action.sa_handler = SIG_DFL;
|
||||||
|
sigaction(SIGUSR1, &action, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure /proc/self/environ is sanitized
|
// Make sure /proc/self/environ is sanitized
|
||||||
@ -68,17 +63,8 @@ static void sanitize_environ() {
|
|||||||
|
|
||||||
__attribute__((destructor))
|
__attribute__((destructor))
|
||||||
static void zygisk_cleanup_wait() {
|
static void zygisk_cleanup_wait() {
|
||||||
if (active_threads < 0)
|
// Wait 10us to make sure none of our code is executing
|
||||||
return;
|
timespec ts = { .tv_sec = 0, .tv_nsec = 10000L };
|
||||||
|
|
||||||
// Setup 1ms
|
|
||||||
timespec ts = { .tv_sec = 0, .tv_nsec = 1000000L };
|
|
||||||
|
|
||||||
// Check flag in busy loop
|
|
||||||
while (active_threads)
|
|
||||||
nanosleep(&ts, nullptr);
|
|
||||||
|
|
||||||
// Wait another 1ms to make sure all threads left our code
|
|
||||||
nanosleep(&ts, nullptr);
|
nanosleep(&ts, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,17 +72,12 @@ static void zygisk_cleanup_wait() {
|
|||||||
|
|
||||||
static decltype(&unload_first_stage) second_stage_entry(void *handle) {
|
static decltype(&unload_first_stage) second_stage_entry(void *handle) {
|
||||||
self_handle = handle;
|
self_handle = handle;
|
||||||
|
|
||||||
unsetenv(INJECT_ENV_2);
|
unsetenv(INJECT_ENV_2);
|
||||||
unsetenv(SECOND_STAGE_PTR);
|
unsetenv(SECOND_STAGE_PTR);
|
||||||
|
|
||||||
zygisk_logging();
|
zygisk_logging();
|
||||||
LOGD("zygisk: inject 2nd stage\n");
|
LOGD("zygisk: inject 2nd stage\n");
|
||||||
active_threads = 1;
|
|
||||||
|
|
||||||
hook_functions();
|
hook_functions();
|
||||||
|
|
||||||
active_threads++;
|
|
||||||
return &unload_first_stage;
|
return &unload_first_stage;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,10 +112,23 @@ static void first_stage_entry() {
|
|||||||
char *env = getenv(SECOND_STAGE_PTR);
|
char *env = getenv(SECOND_STAGE_PTR);
|
||||||
decltype(&second_stage_entry) second_stage;
|
decltype(&second_stage_entry) second_stage;
|
||||||
sscanf(env, "%p", &second_stage);
|
sscanf(env, "%p", &second_stage);
|
||||||
auto unload = second_stage(handle);
|
auto unload_handler = second_stage(handle);
|
||||||
|
|
||||||
// Schedule to unload 1st stage
|
// Register signal handler to unload 1st stage
|
||||||
new_daemon_thread(unload, path);
|
struct sigaction action{};
|
||||||
|
action.sa_sigaction = unload_handler;
|
||||||
|
sigaction(SIGUSR1, &action, nullptr);
|
||||||
|
|
||||||
|
// Schedule to unload 1st stage 10us later
|
||||||
|
timer_t timer;
|
||||||
|
sigevent_t event{};
|
||||||
|
event.sigev_notify = SIGEV_SIGNAL;
|
||||||
|
event.sigev_signo = SIGUSR1;
|
||||||
|
event.sigev_value.sival_ptr = path;
|
||||||
|
timer_create(CLOCK_MONOTONIC, &event, &timer);
|
||||||
|
itimerspec time{};
|
||||||
|
time.it_value.tv_nsec = 10000L;
|
||||||
|
timer_settime(&timer, 0, &time, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((constructor))
|
__attribute__((constructor))
|
||||||
|
@ -265,9 +265,9 @@ void HookContext::nativeSpecializeAppProcess_post() {
|
|||||||
self_unload();
|
self_unload();
|
||||||
} else {
|
} else {
|
||||||
run_modules_post();
|
run_modules_post();
|
||||||
}
|
if (info.is_magisk_app) {
|
||||||
if (info.is_magisk_app) {
|
setenv("ZYGISK_ENABLED", "1", 1);
|
||||||
setenv("ZYGISK_ENABLED", "1", 1);
|
}
|
||||||
}
|
}
|
||||||
g_ctx = nullptr;
|
g_ctx = nullptr;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user