diff --git a/jni/Android.mk b/jni/Android.mk index 86c992578..bfb0c78a3 100644 --- a/jni/Android.mk +++ b/jni/Android.mk @@ -29,6 +29,7 @@ LOCAL_SRC_FILES := \ magiskhide/hide_daemon.c \ magiskhide/proc_monitor.c \ magiskhide/pre_process.c \ + magiskhide/list_manager.c \ magiskpolicy/magiskpolicy.c \ magiskpolicy/rules.c \ magiskpolicy/sepolicy.c \ diff --git a/jni/daemon/daemon.c b/jni/daemon/daemon.c index 5c98c9bba..aaa6d7af3 100644 --- a/jni/daemon/daemon.c +++ b/jni/daemon/daemon.c @@ -35,10 +35,10 @@ static void request_handler(int client) { stop_magiskhide(client); break; case ADD_HIDELIST: - // TODO: Add hidelist + add_hide_list(client); break; case RM_HIDELIST: - // TODO: Remove hidelist + rm_hide_list(client); break; case SUPERUSER: su_daemon_receiver(client); @@ -135,7 +135,7 @@ void start_daemon() { // Start log monitor monitor_logs(); - LOGI("Magisk v" xstr(VERSION) " daemon started\n"); + LOGI("Magisk v" xstr(MAGISK_VERSION) " daemon started\n"); // Unlock all blocks for rw unlock_blocks(); diff --git a/jni/daemon/daemon.h b/jni/daemon/daemon.h index 9a225499a..7b2db07da 100644 --- a/jni/daemon/daemon.h +++ b/jni/daemon/daemon.h @@ -55,6 +55,8 @@ void late_start(int client); void launch_magiskhide(int client); void stop_magiskhide(int client); +void add_hide_list(int client); +void rm_hide_list(int client); /************* * Superuser * diff --git a/jni/magiskhide/hide_daemon.c b/jni/magiskhide/hide_daemon.c index 35d952311..d19e55b9b 100644 --- a/jni/magiskhide/hide_daemon.c +++ b/jni/magiskhide/hide_daemon.c @@ -83,9 +83,8 @@ int hide_daemon() { close(fd); snprintf(buffer, sizeof(buffer), "/proc/%d/mounts", pid); - fp = xfopen(buffer, "r"); vec_init(&mount_list); - file_to_vector(&mount_list, fp); + file_to_vector(buffer, &mount_list); // Find the cache block name if not found yet if (strlen(cache_block) == 0) { @@ -109,10 +108,9 @@ int hide_daemon() { vec_destroy(&mount_list); // Re-read mount infos - fseek(fp, 0, SEEK_SET); + snprintf(buffer, sizeof(buffer), "/proc/%d/mounts", pid); vec_init(&mount_list); - file_to_vector(&mount_list, fp); - fclose(fp); + file_to_vector(buffer, &mount_list); // Unmount loop mounts vec_for_each_r(&mount_list, line) { diff --git a/jni/magiskhide/list_manager.c b/jni/magiskhide/list_manager.c new file mode 100644 index 000000000..9ca209692 --- /dev/null +++ b/jni/magiskhide/list_manager.c @@ -0,0 +1,130 @@ +/* list_manager.c - Hide list management + */ + +#include +#include +#include + +#include "magisk.h" +#include "utils.h" +#include "daemon.h" +#include "magiskhide.h" + +int add_list(char *proc) { + if (!hideEnabled) + return 1; + + char *line; + struct vector *new_list, *temp = hide_list; + new_list = xmalloc(sizeof(*new_list)); + if (new_list == NULL) + return 1; + vec_init(new_list); + + vec_for_each(hide_list, line) { + // They should be unique + if (strcmp(line, proc) == 0) { + free(proc); + vec_destroy(new_list); + free(new_list); + return 2; + } + vec_push_back(new_list, line); + } + + vec_push_back(new_list, proc); + LOGI("hide_list add: [%s]\n", proc); + ps_filter_proc_name(proc, kill_proc); + + // Critical region + pthread_mutex_lock(&lock); + hide_list = new_list; + pthread_mutex_unlock(&lock); + + // Free old list + vec_destroy(temp); + free(temp); + if (vector_to_file(HIDELIST, hide_list)) + return 1; + return 0; +} + +int rm_list(char *proc) { + if (!hideEnabled) + return 1; + + char *line; + struct vector *new_list, *temp; + temp = new_list = xmalloc(sizeof(*new_list)); + if (new_list == NULL) + return 1; + vec_init(new_list); + + vec_for_each(hide_list, line) { + if (strcmp(line, proc) == 0) { + free(proc); + proc = line; + temp = hide_list; + continue; + } + vec_push_back(new_list, line); + } + + if (temp == hide_list) { + LOGI("hide_list rm: [%s]\n", proc); + ps_filter_proc_name(proc, kill_proc); + // Critical region + pthread_mutex_lock(&lock); + hide_list = new_list; + pthread_mutex_unlock(&lock); + if (vector_to_file(HIDELIST, hide_list)) + return 1; + } + + free(proc); + vec_destroy(temp); + free(temp); + return 0; +} + +int init_list() { + LOGD("hide_list: initialize...\n"); + if ((hide_list = xmalloc(sizeof(*hide_list))) == NULL) + return 1; + vec_init(hide_list); + + // Might return 1 if first time + file_to_vector(HIDELIST, hide_list); + + char *line; + vec_for_each(hide_list, line) { + LOGI("hide_list: [%s]\n", line); + ps_filter_proc_name(line, kill_proc); + } + return 0; +} + +int destroy_list() { + char *line; + vec_for_each(hide_list, line) { + ps_filter_proc_name(line, kill_proc); + } + vec_deep_destroy(hide_list); + free(hide_list); + hide_list = NULL; + return 0; +} + +void add_hide_list(int client) { + char *proc = read_string(client); + // ack + write_int(client, add_list(proc)); + close(client); +} + +void rm_hide_list(int client) { + char *proc = read_string(client); + // ack + write_int(client, rm_list(proc)); + close(client); +} diff --git a/jni/magiskhide/magiskhide.c b/jni/magiskhide/magiskhide.c index 27d287893..74bda234f 100644 --- a/jni/magiskhide/magiskhide.c +++ b/jni/magiskhide/magiskhide.c @@ -16,12 +16,14 @@ #include "utils.h" #include "magiskhide.h" #include "daemon.h" +#include "resetprop.h" int sv[2], hide_pid = -1; -struct vector *hide_list, *new_list; +struct vector *hide_list = NULL; -int isEnabled = 0; +int hideEnabled = 0; static pthread_t proc_monitor_thread; +pthread_mutex_t lock; void kill_proc(int pid) { kill(pid, SIGTERM); @@ -41,7 +43,7 @@ static void usage(char *arg0) { } void launch_magiskhide(int client) { - if (isEnabled) + if (hideEnabled) goto success; /* * The setns system call do not support multithread processes @@ -50,6 +52,9 @@ void launch_magiskhide(int client) { LOGI("* Starting MagiskHide\n"); + hideEnabled = 1; + setprop("persist.magisk.hide", "1"); + hide_sensitive_props(); if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sv) == -1) @@ -62,31 +67,23 @@ void launch_magiskhide(int client) { close(sv[1]); // Initialize the hide list - hide_list = new_list = xmalloc(sizeof(*hide_list)); - if (hide_list == NULL) + if (init_list()) 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; - vec_for_each(hide_list, line) { - LOGI("hide_list: [%s]\n", line); - ps_filter_proc_name(line, kill_proc); - } + + // Add SafetyNet by default + add_list(strdup("com.google.android.gms.unstable")); // Start a new thread to monitor processes + pthread_mutex_init(&lock, NULL); if (xpthread_create(&proc_monitor_thread, NULL, proc_monitor, NULL)) goto error; - isEnabled = 1; success: write_int(client, 0); close(client); return; error: + hideEnabled = 0; write_int(client, 1); close(client); if (hide_pid != -1) { @@ -101,7 +98,7 @@ error: } void stop_magiskhide(int client) { - if (!isEnabled) + if (!hideEnabled) return; LOGI("* Stopping MagiskHide\n"); @@ -109,7 +106,8 @@ void stop_magiskhide(int client) { pthread_kill(proc_monitor_thread, SIGUSR1); pthread_join(proc_monitor_thread, NULL); - isEnabled = 0; + hideEnabled = 0; + setprop("persist.magisk.hide", "0"); write_int(client, 0); close(client); } diff --git a/jni/magiskhide/magiskhide.h b/jni/magiskhide/magiskhide.h index e955e34c0..187a7ed56 100644 --- a/jni/magiskhide/magiskhide.h +++ b/jni/magiskhide/magiskhide.h @@ -1,6 +1,8 @@ #ifndef MAGISK_HIDE_H #define MAGISK_HIDE_H +#include + #define HIDELIST "/magisk/.core/magiskhide/hidelist" #define DUMMYPATH "/dev/magisk/dummy" #define ENFORCE_FILE "/sys/fs/selinux/enforce" @@ -20,7 +22,14 @@ void manage_selinux(); void hide_sensitive_props(); void relink_sbin(); -extern int sv[2], hide_pid, isEnabled; -extern struct vector *hide_list, *new_list; +// List managements +int add_list(char *proc); +int rm_list(char *proc); +int init_list(); +int destroy_list(); + +extern int sv[2], hide_pid, hideEnabled; +extern struct vector *hide_list; +extern pthread_mutex_t lock; #endif diff --git a/jni/magiskhide/proc_monitor.c b/jni/magiskhide/proc_monitor.c index a857b2564..cb1ca3c32 100644 --- a/jni/magiskhide/proc_monitor.c +++ b/jni/magiskhide/proc_monitor.c @@ -30,18 +30,8 @@ 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) { 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); - free(hide_list); - if (new_list != hide_list) { - vec_deep_destroy(new_list); - free(new_list); - } - hide_list = new_list = NULL; - isEnabled = 0; + destroy_list(); + hideEnabled = 0; // Kill the logging if possible if (log_pid) { kill(log_pid, SIGTERM); @@ -54,6 +44,7 @@ static void quit_pthread(int sig) { write(sv[0], &kill, sizeof(kill)); close(sv[0]); waitpid(hide_pid, NULL, 0); + pthread_mutex_destroy(&lock); LOGD("proc_monitor: terminating...\n"); pthread_exit(NULL); } @@ -109,7 +100,6 @@ void *proc_monitor(void *args) { while(fdgets(buffer, sizeof(buffer), log_fd)) { int ret, comma = 0; char *pos = buffer, *line, processName[256]; - struct vector *temp = NULL; while(1) { pos = strchr(pos, ','); @@ -127,14 +117,10 @@ void *proc_monitor(void *args) { if(ret != 2) continue; - // Should be thread safe - if (hide_list != new_list) { - temp = hide_list; - hide_list = new_list; - } - ret = 0; + // Critical region + pthread_mutex_lock(&lock); vec_for_each(hide_list, line) { if (strcmp(processName, line) == 0) { read_namespace(pid, buffer, 32); @@ -166,10 +152,8 @@ void *proc_monitor(void *args) { break; } } - if (temp) { - vec_deep_destroy(temp); - free(temp); - } + pthread_mutex_unlock(&lock); + if (ret) { // Wait hide process to kill itself waitpid(hide_pid, NULL, 0); diff --git a/jni/utils/misc.c b/jni/utils/misc.c index 31aeee958..09b5f05fa 100644 --- a/jni/utils/misc.c +++ b/jni/utils/misc.c @@ -57,11 +57,15 @@ int check_data() { } /* All the string should be freed manually!! */ -void file_to_vector(struct vector *v, FILE *fp) { +int file_to_vector(const char* filename, struct vector *v) { char *line = NULL; size_t len = 0; ssize_t read; + FILE *fp = xfopen(filename, "r"); + if (fp == NULL) + return 1; + while ((read = getline(&line, &len, fp)) != -1) { // Remove end newline if (line[read - 1] == '\n') @@ -69,6 +73,20 @@ void file_to_vector(struct vector *v, FILE *fp) { vec_push_back(v, line); line = NULL; } + fclose(fp); + return 0; +} + +int vector_to_file(const char *filename, struct vector *v) { + FILE *fp = xfopen(filename, "w"); + if (fp == NULL) + return 1; + char *line; + vec_for_each(v, line) { + fprintf(fp, "%s\n", line); + } + fclose(fp); + return 0; } /* Check if the string only contains digits */ diff --git a/jni/utils/utils.h b/jni/utils/utils.h index 37f12fcf8..5008099d5 100644 --- a/jni/utils/utils.h +++ b/jni/utils/utils.h @@ -63,7 +63,8 @@ unsigned get_shell_uid(); unsigned get_system_uid(); unsigned get_radio_uid(); int check_data(); -void file_to_vector(struct vector *v, FILE *fp); +int file_to_vector(const char* filename, struct vector *v); +int vector_to_file(const char* filename, struct vector *v); int isNum(const char *s); ssize_t fdgets(char *buf, size_t size, int fd); void ps(void (*func)(int));