Prevent race condition on /magisk symlink

This commit is contained in:
topjohnwu 2017-11-09 03:05:01 +08:00
parent 2db60e0a6b
commit 72b5985398
3 changed files with 25 additions and 9 deletions

View File

@ -100,7 +100,7 @@ void stop_magiskhide(int client) {
setprop(MAGISKHIDE_PROP, "0"); setprop(MAGISKHIDE_PROP, "0");
// Remove without actually removing persist props // Remove without actually removing persist props
deleteprop2(MAGISKHIDE_PROP, 0); deleteprop2(MAGISKHIDE_PROP, 0);
pthread_kill(proc_monitor_thread, SIGUSR1); pthread_kill(proc_monitor_thread, TERM_THREAD);
write_int(client, DAEMON_SUCCESS); write_int(client, DAEMON_SUCCESS);
close(client); close(client);

View File

@ -3,6 +3,9 @@
#include <pthread.h> #include <pthread.h>
#define TERM_THREAD SIGUSR1
#define HIDE_DONE SIGUSR2
// Kill process // Kill process
void kill_proc(int pid); void kill_proc(int pid);

View File

@ -20,10 +20,10 @@
#include "magiskhide.h" #include "magiskhide.h"
static char init_ns[32], zygote_ns[2][32], cache_block[256]; 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 // 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"); LOGD("proc_monitor: running cleanup\n");
destroy_list(); destroy_list();
hideEnabled = 0; hideEnabled = 0;
@ -38,6 +38,15 @@ static void quit_pthread(int sig) {
pthread_exit(NULL); 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) { static int read_namespace(const int pid, char* target, const size_t size) {
char path[32]; char path[32];
snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid); 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); 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); LOGD("hide_daemon: start unmount for pid=[%d]\n", pid);
char *line, buffer[PATH_MAX]; char *line, buffer[PATH_MAX];
@ -135,7 +144,7 @@ exit:
vec_destroy(&mount_list); vec_destroy(&mount_list);
// Wait a while and link it back // Wait a while and link it back
sleep(10); sleep(10);
xsymlink(MOUNTPOINT, FAKEPOINT); kill(ppid, HIDE_DONE);
_exit(0); _exit(0);
} }
@ -143,15 +152,17 @@ void proc_monitor() {
// Register the cancel signal // Register the cancel signal
struct sigaction act; struct sigaction act;
memset(&act, 0, sizeof(act)); memset(&act, 0, sizeof(act));
act.sa_handler = quit_pthread; act.sa_handler = term_thread;
sigaction(SIGUSR1, &act, NULL); sigaction(TERM_THREAD, &act, NULL);
act.sa_handler = hide_done;
sigaction(HIDE_DONE, &act, NULL);
cache_block[0] = '\0'; cache_block[0] = '\0';
// Get the mount namespace of init // Get the mount namespace of init
if (read_namespace(1, init_ns, 32)) { if (read_namespace(1, init_ns, 32)) {
LOGE("proc_monitor: Your kernel doesn't support mount namespace :(\n"); 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); 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 * The setns system call do not support multithread processes
* We have to fork a new process, setns, then do the unmounts * We have to fork a new process, setns, then do the unmounts
*/ */
++hide_queue;
int selfpid = getpid();
if (fork_dont_care() == 0) if (fork_dont_care() == 0)
hide_daemon(pid); hide_daemon(pid, selfpid);
break; break;
} }