From 72b5985398a637d83719cecf888c04d0c326c0a9 Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Thu, 9 Nov 2017 03:05:01 +0800 Subject: [PATCH] Prevent race condition on /magisk symlink --- jni/magiskhide/magiskhide.c | 2 +- jni/magiskhide/magiskhide.h | 3 +++ jni/magiskhide/proc_monitor.c | 29 +++++++++++++++++++++-------- 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/jni/magiskhide/magiskhide.c b/jni/magiskhide/magiskhide.c index a38898979..d4952353c 100644 --- a/jni/magiskhide/magiskhide.c +++ b/jni/magiskhide/magiskhide.c @@ -100,7 +100,7 @@ void stop_magiskhide(int client) { setprop(MAGISKHIDE_PROP, "0"); // Remove without actually removing persist props deleteprop2(MAGISKHIDE_PROP, 0); - pthread_kill(proc_monitor_thread, SIGUSR1); + pthread_kill(proc_monitor_thread, TERM_THREAD); write_int(client, DAEMON_SUCCESS); close(client); diff --git a/jni/magiskhide/magiskhide.h b/jni/magiskhide/magiskhide.h index a5353a37f..c9e2bb5d9 100644 --- a/jni/magiskhide/magiskhide.h +++ b/jni/magiskhide/magiskhide.h @@ -3,6 +3,9 @@ #include +#define TERM_THREAD SIGUSR1 +#define HIDE_DONE SIGUSR2 + // Kill process void kill_proc(int pid); diff --git a/jni/magiskhide/proc_monitor.c b/jni/magiskhide/proc_monitor.c index 59e8925d1..1002f1ccb 100644 --- a/jni/magiskhide/proc_monitor.c +++ b/jni/magiskhide/proc_monitor.c @@ -20,10 +20,10 @@ #include "magiskhide.h" static char init_ns[32], zygote_ns[2][32], cache_block[256]; -static int zygote_num, has_cache = 1, pipefd[2] = { -1, -1 }; +static int hide_queue = 0, zygote_num, has_cache = 1, pipefd[2] = { -1, -1 }; // Workaround for the lack of pthread_cancel -static void quit_pthread(int sig) { +static void term_thread(int sig) { LOGD("proc_monitor: running cleanup\n"); destroy_list(); hideEnabled = 0; @@ -38,6 +38,15 @@ static void quit_pthread(int sig) { pthread_exit(NULL); } +static void hide_done(int sig) { + --hide_queue; + if (hide_queue == 0) { + xmount(NULL, "/", NULL, MS_REMOUNT, NULL); + xsymlink(MOUNTPOINT, FAKEPOINT); + xmount(NULL, "/", NULL, MS_REMOUNT | MS_RDONLY, NULL); + } +} + static int read_namespace(const int pid, char* target, const size_t size) { char path[32]; snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid); @@ -63,7 +72,7 @@ static void lazy_unmount(const char* mountpoint) { LOGD("hide_daemon: Unmount Failed (%s)\n", mountpoint); } -static void hide_daemon(int pid) { +static void hide_daemon(int pid, int ppid) { LOGD("hide_daemon: start unmount for pid=[%d]\n", pid); char *line, buffer[PATH_MAX]; @@ -135,7 +144,7 @@ exit: vec_destroy(&mount_list); // Wait a while and link it back sleep(10); - xsymlink(MOUNTPOINT, FAKEPOINT); + kill(ppid, HIDE_DONE); _exit(0); } @@ -143,15 +152,17 @@ void proc_monitor() { // Register the cancel signal struct sigaction act; memset(&act, 0, sizeof(act)); - act.sa_handler = quit_pthread; - sigaction(SIGUSR1, &act, NULL); + act.sa_handler = term_thread; + sigaction(TERM_THREAD, &act, NULL); + act.sa_handler = hide_done; + sigaction(HIDE_DONE, &act, NULL); cache_block[0] = '\0'; // Get the mount namespace of init if (read_namespace(1, init_ns, 32)) { LOGE("proc_monitor: Your kernel doesn't support mount namespace :(\n"); - quit_pthread(SIGUSR1); + term_thread(TERM_THREAD); } LOGI("proc_monitor: init ns=%s\n", init_ns); @@ -227,8 +238,10 @@ void proc_monitor() { * The setns system call do not support multithread processes * We have to fork a new process, setns, then do the unmounts */ + ++hide_queue; + int selfpid = getpid(); if (fork_dont_care() == 0) - hide_daemon(pid); + hide_daemon(pid, selfpid); break; }