Magisk/jni/magiskhide/hide_daemon.c

137 lines
3.0 KiB
C
Raw Normal View History

2017-04-05 22:12:29 +00:00
/* hide_daemon.c - MagiskHide daemon
*
* A dedicated process to join the target namespace,
* and hide all traces in that particular namespace
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
2017-04-06 23:50:02 +00:00
#include <signal.h>
2017-04-05 22:12:29 +00:00
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mount.h>
#include "magisk.h"
#include "utils.h"
#include "magiskhide.h"
2017-04-17 08:36:49 +00:00
static int pid;
2017-04-05 22:12:29 +00:00
static void lazy_unmount(const char* mountpoint) {
if (umount2(mountpoint, MNT_DETACH) != -1)
LOGI("hide_daemon: Unmounted (%s)\n", mountpoint);
else
LOGI("hide_daemon: Unmount Failed (%s)\n", mountpoint);
}
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() {
2017-04-05 22:12:29 +00:00
// Fork to a new process
hide_pid = fork();
switch(hide_pid) {
2017-04-05 22:12:29 +00:00
case -1:
PLOGE("fork");
return 1;
2017-04-05 22:12:29 +00:00
case 0:
break;
default:
return 0;
2017-04-05 22:12:29 +00:00
}
close(sv[0]);
2017-04-07 23:37:43 +00:00
// Set the process name
2017-04-05 22:12:29 +00:00
strcpy(argv0, "magiskhide_daemon");
// When an error occurs, report its failure to main process
err_handler = hide_daemon_err;
2017-04-05 22:12:29 +00:00
int fd;
2017-04-05 22:12:29 +00:00
FILE *fp;
2017-04-14 19:23:09 +00:00
char buffer[4096], cache_block[256], *line;
2017-04-05 22:12:29 +00:00
struct vector mount_list;
cache_block[0] = '\0';
while(1) {
xxread(sv[1], &pid, sizeof(pid));
2017-04-05 22:12:29 +00:00
// Termination called
if(pid == -1) {
LOGD("hide_daemon: received termination request\n");
_exit(0);
}
2017-04-05 22:12:29 +00:00
2017-04-17 08:36:49 +00:00
manage_selinux();
relink_sbin();
2017-04-14 19:23:09 +00:00
snprintf(buffer, sizeof(buffer), "/proc/%d/ns/mnt", pid);
if(access(buffer, F_OK) == -1) continue; // Maybe process died..
2017-04-05 22:12:29 +00:00
2017-04-14 19:23:09 +00:00
fd = xopen(buffer, O_RDONLY);
2017-04-05 22:12:29 +00:00
// Switch to its namespace
xsetns(fd, 0);
close(fd);
2017-04-14 19:23:09 +00:00
snprintf(buffer, sizeof(buffer), "/proc/%d/mounts", pid);
fp = xfopen(buffer, "r");
2017-04-05 22:12:29 +00:00
vec_init(&mount_list);
file_to_vector(&mount_list, fp);
// Find the cache block name if not found yet
if (strlen(cache_block) == 0) {
vec_for_each(&mount_list, line) {
if (strstr(line, " /cache ")) {
sscanf(line, "%256s", cache_block);
break;
}
}
}
2017-04-05 22:12:29 +00:00
// 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")
|| (strstr(line, cache_block) && strstr(line, "/system/")) ) {
2017-04-14 19:23:09 +00:00
sscanf(line, "%*s %512s", buffer);
lazy_unmount(buffer);
2017-04-05 22:12:29 +00:00
}
free(line);
}
vec_destroy(&mount_list);
// Re-read mount infos
fseek(fp, 0, SEEK_SET);
vec_init(&mount_list);
file_to_vector(&mount_list, fp);
fclose(fp);
// Unmount loop mounts
vec_for_each_r(&mount_list, line) {
if (strstr(line, "/dev/block/loop") && !strstr(line, DUMMYPATH)) {
2017-04-14 19:23:09 +00:00
sscanf(line, "%*s %512s", buffer);
lazy_unmount(buffer);
2017-04-05 22:12:29 +00:00
}
free(line);
}
vec_destroy(&mount_list);
// All done, send resume signal
kill(pid, SIGCONT);
// Tell main process all is well
pid = 0;
xwrite(sv[1], &pid, sizeof(pid));
2017-04-05 22:12:29 +00:00
}
// Should never go here
}