mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-10-16 09:52:31 +00:00
Integrate MagiskHide into Magisk Daemon
This commit is contained in:
@@ -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
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user