Integrate MagiskHide into Magisk Daemon

This commit is contained in:
topjohnwu
2017-04-09 07:25:10 +08:00
parent 054a1e5ea4
commit 144ff5e716
12 changed files with 297 additions and 75 deletions

View File

@@ -18,7 +18,7 @@
#include "utils.h"
#include "magiskhide.h"
static int isMocked = 0;
static int isMocked = 0, pid;
static void manage_selinux() {
if (isMocked) return;
@@ -43,23 +43,36 @@ static void lazy_unmount(const char* mountpoint) {
LOGI("hide_daemon: Unmount Failed (%s)\n", mountpoint);
}
void hide_daemon() {
static void hide_daemon_err() {
LOGD("hide_daemon: error occured, stopping magiskhide services\n");
// Resume process if possible
kill(pid, SIGCONT);
int err = 1;
write(sv[1], &err, sizeof(err));
_exit(-1);
}
int hide_daemon() {
// Fork to a new process
switch(fork()) {
hide_pid = fork();
switch(hide_pid) {
case -1:
PLOGE("fork");
return 1;
case 0:
break;
default:
return;
return 0;
}
close(pipefd[1]);
close(sv[0]);
// Set the process name
strcpy(argv0, "magiskhide_daemon");
// When an error occurs, report its failure to main process
err_handler = hide_daemon_err;
int pid, fd;
int fd;
FILE *fp;
char cache_block[256], *line;
struct vector mount_list;
@@ -67,9 +80,12 @@ void hide_daemon() {
cache_block[0] = '\0';
while(1) {
xxread(pipefd[0], &pid, sizeof(pid));
xxread(sv[1], &pid, sizeof(pid));
// Termination called
if(pid == -1) exit(0);
if(pid == -1) {
LOGD("hide_daemon: received termination request\n");
_exit(0);
}
snprintf(magiskbuf, BUF_SIZE, "/proc/%d/ns/mnt", pid);
if(access(magiskbuf, F_OK) == -1) continue; // Maybe process died..
@@ -95,7 +111,7 @@ void hide_daemon() {
}
}
}
// First unmount the dummy skeletons, cache mounts, and /sbin links
vec_for_each_r(&mount_list, line) {
if (strstr(line, "tmpfs /system") || strstr(line, "tmpfs /vendor") || strstr(line, "tmpfs /sbin")
@@ -125,6 +141,10 @@ void hide_daemon() {
// All done, send resume signal
kill(pid, SIGCONT);
// Tell main process all is well
pid = 0;
xwrite(sv[1], &pid, sizeof(pid));
}
// Should never go here

View File

@@ -8,38 +8,67 @@
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/types.h>
#include "magisk.h"
#include "utils.h"
#include "magiskhide.h"
#include "daemon.h"
int pipefd[2];
int sv[2], hide_pid;
struct vector *hide_list, *new_list;
int isEnabled = 0;
static pthread_t proc_monitor_thread;
static void kill_proc(int pid) {
void kill_proc(int pid) {
kill(pid, SIGTERM);
}
void launch_magiskhide() {
static void usage(char *arg0) {
fprintf(stderr,
"%s [--options [arguments...] ]\n\n"
"Options:\n"
" --enable: Start the magiskhide daemon\n"
" --disable: Stop the magiskhide daemon\n"
" --add <process name>: Add <process name> to the list\n"
" --rm <process name>: Remove <process name> from the list\n"
" --ls: Print out the current hide list\n"
, arg0);
exit(1);
}
void launch_magiskhide(int client) {
if (isEnabled) {
write_int(client, 0);
return;
}
/*
* The setns system call do not support multithread processes
* We have to fork a new process, and communicate with pipe
*/
xpipe(pipefd);
LOGI("* Starting MagiskHide\n");
if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sv) == -1)
goto error;
// Launch the hide daemon
hide_daemon();
if (hide_daemon())
goto error;
close(pipefd[0]);
close(sv[1]);
// Initialize the hide list
hide_list = new_list = malloc(sizeof(*hide_list));
hide_list = new_list = xmalloc(sizeof(*hide_list));
if (hide_list == NULL)
goto error;
vec_init(hide_list);
FILE *fp = xfopen(HIDELIST, "r");
if (fp == NULL)
goto error;
file_to_vector(hide_list, fp);
fclose(fp);
char *line;
@@ -49,20 +78,66 @@ void launch_magiskhide() {
}
// Start a new thread to monitor processes
pthread_create(&proc_monitor_thread, NULL, proc_monitor, NULL);
pthread_join(proc_monitor_thread, NULL);
if (xpthread_create(&proc_monitor_thread, NULL, proc_monitor, NULL))
goto error;
isEnabled = 1;
write_int(client, 0);
return;
error:
write_int(client, 1);
return;
}
void stop_magiskhide() {
void stop_magiskhide(int client) {
if (!isEnabled)
return;
LOGI("* Stopping MagiskHide\n");
int kill = -1;
// Terminate hide daemon
xwrite(pipefd[1], &kill, sizeof(kill));
write(sv[0], &kill, sizeof(kill));
close(sv[0]);
waitpid(hide_pid, NULL, 0);
// Stop process monitor
pthread_kill(proc_monitor_thread, SIGUSR1);
pthread_join(proc_monitor_thread, NULL);
isEnabled = 0;
write_int(client, 0);
}
int magiskhide_main(int argc, char *argv[]) {
launch_magiskhide();
return 0;
if (argc < 2) {
usage(argv[0]);
}
client_request req;
if (strcmp(argv[1], "--enable") == 0) {
req = LAUNCH_MAGISKHIDE;
} else if (strcmp(argv[1], "--disable") == 0) {
req = STOP_MAGISKHIDE;
} else if (strcmp(argv[1], "--add") == 0 && argc > 2) {
req = ADD_HIDELIST;
} else if (strcmp(argv[1], "--rm") == 0 && argc > 2) {
req = RM_HIDELIST;
} else if (strcmp(argv[1], "--ls") == 0) {
FILE *fp = xfopen(HIDELIST, "r");
while (fgets(magiskbuf, BUF_SIZE, fp)) {
printf("%s", magiskbuf);
}
fclose(fp);
return 0;
}
int fd = connect_daemon();
write_int(fd, req);
if (req == ADD_HIDELIST || req == RM_HIDELIST) {
write_string(fd, argv[2]);
}
int code = read_int(fd);
close(fd);
if (code) {
fprintf(stderr, "Error occured in MagiskHide daemon\n");
}
return code;
}

View File

@@ -6,13 +6,16 @@
#define ENFORCE_FILE "/sys/fs/selinux/enforce"
#define POLICY_FILE "/sys/fs/selinux/policy"
// Kill process
void kill_proc(int pid);
// Hide daemon
void hide_daemon();
int hide_daemon();
// Process monitor
void *proc_monitor(void *args);
extern int pipefd[2];
extern int sv[2], hide_pid, isEnabled;
extern struct vector *hide_list, *new_list;
#endif

View File

@@ -11,15 +11,12 @@
#include <signal.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "magisk.h"
#include "utils.h"
#include "magiskhide.h"
/* WTF... the macro in the NDK pthread.h is broken.... */
#define pthread_cleanup_push_fix(routine, arg) \
pthread_cleanup_push(routine, arg) } while(0);
static int zygote_num = 0;
static char init_ns[32], zygote_ns[2][32];
@@ -32,15 +29,21 @@ static void read_namespace(const int pid, char* target, const size_t size) {
// Workaround for the lack of pthread_cancel
static void quit_pthread(int sig) {
pthread_exit(NULL);
}
static void cleanup_handler(void *arg) {
LOGD("proc_monitor: running cleanup\n");
char *line;
vec_for_each(hide_list, line) {
ps_filter_proc_name(line, kill_proc);
}
vec_deep_destroy(hide_list);
vec_deep_destroy(new_list);
free(hide_list);
free(new_list);
if (new_list != hide_list) {
vec_deep_destroy(new_list);
free(new_list);
}
hide_list = new_list = NULL;
isEnabled = 0;
LOGD("proc_monitor: terminating...\n");
pthread_exit(NULL);
}
static void store_zygote_ns(int pid) {
@@ -51,10 +54,21 @@ static void store_zygote_ns(int pid) {
++zygote_num;
}
static void proc_monitor_err() {
LOGD("proc_monitor: error occured, stopping magiskhide services\n");
int kill = -1;
// If process monitor dies, kill hide daemon too
write(sv[0], &kill, sizeof(kill));
close(sv[0]);
waitpid(hide_pid, NULL, 0);
quit_pthread(SIGUSR1);
}
void *proc_monitor(void *args) {
// Register the cancel signal
signal(SIGUSR1, quit_pthread);
pthread_cleanup_push_fix(cleanup_handler, NULL);
// The error handler should only exit the thread, not the whole process
err_handler = proc_monitor_err;
int pid;
char buffer[512];
@@ -106,6 +120,8 @@ void *proc_monitor(void *args) {
hide_list = new_list;
}
ret = 0;
vec_for_each(hide_list, line) {
if (strcmp(processName, line) == 0) {
read_namespace(pid, buffer, 32);
@@ -121,13 +137,19 @@ void *proc_monitor(void *args) {
if (ret) break;
}
ret = 0;
// Send pause signal ASAP
if (kill(pid, SIGSTOP) == -1) continue;
LOGI("proc_monitor: %s(PID=%d ns=%s)\n", processName, pid, buffer);
// Unmount start
xwrite(pipefd[1], &pid, sizeof(pid));
xwrite(sv[0], &pid, sizeof(pid));
// Get the hide daemon return code
xxread(sv[0], &ret, sizeof(ret));
LOGD("proc_monitor: hide daemon response code: %d\n", ret);
break;
}
}
@@ -135,10 +157,15 @@ void *proc_monitor(void *args) {
vec_deep_destroy(temp);
free(temp);
}
if (ret) {
// Wait hide process to kill itself
waitpid(hide_pid, NULL, 0);
quit_pthread(SIGUSR1);
}
}
// Should never be here
pclose(p);
quit_pthread(SIGUSR1);
pthread_exit(NULL);
return NULL;
}