Magisk/jni/magiskhide/proc_monitor.c

167 lines
3.8 KiB
C
Raw Normal View History

2017-04-05 22:12:29 +00:00
/* proc_monitor.c - Monitor am_proc_start events
*
* We monitor the logcat am_proc_start events, pause it,
* and send the target PID to hide daemon ASAP
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/wait.h>
2017-04-05 22:12:29 +00:00
#include "magisk.h"
#include "utils.h"
2016-12-30 18:44:24 +00:00
#include "magiskhide.h"
2017-04-06 23:50:02 +00:00
static int zygote_num = 0;
static char init_ns[32], zygote_ns[2][32];
2017-04-18 11:32:50 +00:00
static int log_pid = 0, log_fd;
2017-04-06 23:50:02 +00:00
2017-04-05 22:12:29 +00:00
static void read_namespace(const int pid, char* target, const size_t size) {
char path[32];
snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
2017-04-17 08:36:49 +00:00
xreadlink(path, target, size);
2017-04-05 22:12:29 +00:00
}
2017-01-01 10:54:13 +00:00
2017-04-05 22:12:29 +00:00
// Workaround for the lack of pthread_cancel
static void quit_pthread(int sig) {
LOGD("proc_monitor: running cleanup\n");
2017-04-20 14:45:56 +00:00
destroy_list();
hideEnabled = 0;
2017-04-18 11:32:50 +00:00
// Kill the logging if possible
if (log_pid) {
kill(log_pid, SIGTERM);
waitpid(log_pid, NULL, 0);
close(log_fd);
log_pid = 0;
}
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);
2017-04-21 16:54:08 +00:00
pthread_mutex_destroy(&hide_lock);
LOGD("proc_monitor: terminating...\n");
pthread_exit(NULL);
2017-04-05 22:12:29 +00:00
}
2017-01-01 10:54:13 +00:00
2017-04-06 23:50:02 +00:00
static void store_zygote_ns(int pid) {
2017-04-18 11:32:50 +00:00
if (zygote_num == 2) return;
2017-04-06 23:50:02 +00:00
do {
usleep(500);
read_namespace(pid, zygote_ns[zygote_num], 32);
} while (strcmp(zygote_ns[zygote_num], init_ns) == 0);
++zygote_num;
}
static void proc_monitor_err() {
LOGD("proc_monitor: error occured, stopping magiskhide services\n");
quit_pthread(SIGUSR1);
}
2017-04-21 16:54:08 +00:00
void proc_monitor() {
2017-04-05 22:12:29 +00:00
// Register the cancel signal
signal(SIGUSR1, quit_pthread);
// The error handler should only exit the thread, not the whole process
err_handler = proc_monitor_err;
2017-04-06 23:50:02 +00:00
int pid;
char buffer[512];
2017-04-05 22:12:29 +00:00
// Get the mount namespace of init
read_namespace(1, init_ns, 32);
LOGI("proc_monitor: init ns=%s\n", init_ns);
// Get the mount namespace of zygote
2017-04-17 08:36:49 +00:00
while(!zygote_num) {
// Check zygote every 2 secs
sleep(2);
ps_filter_proc_name("zygote", store_zygote_ns);
}
2017-04-05 22:12:29 +00:00
switch(zygote_num) {
case 1:
LOGI("proc_monitor: zygote ns=%s\n", zygote_ns[0]);
break;
case 2:
LOGI("proc_monitor: zygote (1) ns=%s (2) ns=%s\n", zygote_ns[0], zygote_ns[1]);
break;
}
2017-04-18 11:32:50 +00:00
// Monitor am_proc_start
system("logcat -b events -c");
char *const command[] = { "logcat", "-b", "events", "-v", "raw", "-s", "am_proc_start", NULL };
log_pid = run_command(&log_fd, "/system/bin/logcat", command);
2016-12-30 18:44:24 +00:00
2017-04-18 11:32:50 +00:00
while(fdgets(buffer, sizeof(buffer), log_fd)) {
2017-04-05 22:12:29 +00:00
int ret, comma = 0;
char *pos = buffer, *line, processName[256];
2016-12-30 18:44:24 +00:00
while(1) {
pos = strchr(pos, ',');
if(pos == NULL)
break;
pos[0] = ' ';
2017-04-05 22:12:29 +00:00
++comma;
2016-12-30 18:44:24 +00:00
}
2017-04-05 22:12:29 +00:00
if (comma == 6)
ret = sscanf(buffer, "[%*d %d %*d %*d %256s", &pid, processName);
2017-04-05 22:12:29 +00:00
else
ret = sscanf(buffer, "[%*d %d %*d %256s", &pid, processName);
2016-12-30 18:44:24 +00:00
if(ret != 2)
continue;
ret = 0;
2017-04-20 14:45:56 +00:00
// Critical region
2017-04-21 16:54:08 +00:00
pthread_mutex_lock(&hide_lock);
2017-04-05 22:12:29 +00:00
vec_for_each(hide_list, line) {
if (strcmp(processName, line) == 0) {
read_namespace(pid, buffer, 32);
2017-01-01 10:54:13 +00:00
while(1) {
2017-04-05 22:12:29 +00:00
ret = 1;
for (int i = 0; i < zygote_num; ++i) {
2017-01-01 10:54:13 +00:00
if (strcmp(buffer, zygote_ns[i]) == 0) {
2017-04-17 08:36:49 +00:00
usleep(50);
2017-04-05 22:12:29 +00:00
ret = 0;
2017-01-01 10:54:13 +00:00
break;
}
}
2017-04-05 22:12:29 +00:00
if (ret) break;
2017-01-01 10:54:13 +00:00
}
ret = 0;
2017-01-01 10:54:13 +00:00
// Send pause signal ASAP
if (kill(pid, SIGSTOP) == -1) continue;
2017-04-21 17:40:07 +00:00
LOGI("proc_monitor: %s (PID=%d ns=%s)\n", processName, pid, buffer);
2017-01-01 10:54:13 +00:00
// Unmount start
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);
2017-01-01 10:54:13 +00:00
break;
2016-12-30 18:44:24 +00:00
}
}
2017-04-21 16:54:08 +00:00
pthread_mutex_unlock(&hide_lock);
2017-04-20 14:45:56 +00:00
if (ret) {
// Wait hide process to kill itself
waitpid(hide_pid, NULL, 0);
quit_pthread(SIGUSR1);
}
2016-12-30 18:44:24 +00:00
}
2017-04-05 22:12:29 +00:00
// Should never be here
2017-04-18 11:32:50 +00:00
quit_pthread(SIGUSR1);
}