2018-11-01 17:23:12 +00:00
|
|
|
/* proc_monitor.cpp - Monitor am_proc_start events and unmount
|
2017-08-01 07:34:16 +00:00
|
|
|
*
|
2017-07-10 15:39:33 +00:00
|
|
|
* We monitor the logcat am_proc_start events. When a target starts up,
|
|
|
|
* we pause it ASAP, and fork a new process to join its mount namespace
|
|
|
|
* and do all the unmounting/mocking
|
2017-04-05 22:12:29 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
2018-07-13 14:14:32 +00:00
|
|
|
#include <fcntl.h>
|
2017-04-05 22:12:29 +00:00
|
|
|
#include <signal.h>
|
|
|
|
#include <pthread.h>
|
|
|
|
#include <sys/types.h>
|
2017-04-08 23:25:10 +00:00
|
|
|
#include <sys/wait.h>
|
2017-07-10 15:39:33 +00:00
|
|
|
#include <sys/mount.h>
|
2019-01-20 04:59:37 +00:00
|
|
|
#include <vector>
|
|
|
|
#include <string>
|
2017-04-05 22:12:29 +00:00
|
|
|
|
2019-02-10 06:05:19 +00:00
|
|
|
#include <magisk.h>
|
|
|
|
#include <utils.h>
|
|
|
|
#include <logcat.h>
|
|
|
|
|
2016-12-30 18:44:24 +00:00
|
|
|
#include "magiskhide.h"
|
|
|
|
|
2019-01-20 04:59:37 +00:00
|
|
|
using namespace std;
|
|
|
|
|
2018-11-13 06:53:48 +00:00
|
|
|
extern char *system_block, *vendor_block, *magiskloop;
|
2017-04-06 23:50:02 +00:00
|
|
|
|
2017-04-05 22:12:29 +00:00
|
|
|
// Workaround for the lack of pthread_cancel
|
2018-11-01 17:23:12 +00:00
|
|
|
static void term_thread(int) {
|
2017-04-08 23:25:10 +00:00
|
|
|
LOGD("proc_monitor: running cleanup\n");
|
2019-02-10 06:05:19 +00:00
|
|
|
stop_logging(HIDE_EVENT);
|
2019-01-20 04:59:37 +00:00
|
|
|
hide_list.clear();
|
2018-11-16 05:37:41 +00:00
|
|
|
hide_enabled = false;
|
2018-11-01 17:23:12 +00:00
|
|
|
pthread_mutex_destroy(&list_lock);
|
|
|
|
LOGD("proc_monitor: terminating\n");
|
2018-11-07 07:10:38 +00:00
|
|
|
pthread_exit(nullptr);
|
2017-04-05 22:12:29 +00:00
|
|
|
}
|
2017-01-01 10:54:13 +00:00
|
|
|
|
2018-07-11 15:41:38 +00:00
|
|
|
static int read_ns(const int pid, struct stat *st) {
|
2017-07-02 17:02:11 +00:00
|
|
|
char path[32];
|
2018-06-19 17:20:49 +00:00
|
|
|
sprintf(path, "/proc/%d/ns/mnt", pid);
|
2018-07-11 15:41:38 +00:00
|
|
|
return stat(path, st);
|
2017-07-02 17:02:11 +00:00
|
|
|
}
|
|
|
|
|
2018-11-23 19:32:33 +00:00
|
|
|
static inline void lazy_unmount(const char* mountpoint) {
|
2018-01-11 16:23:38 +00:00
|
|
|
if (umount2(mountpoint, MNT_DETACH) != -1)
|
2017-07-10 15:39:33 +00:00
|
|
|
LOGD("hide_daemon: Unmounted (%s)\n", mountpoint);
|
|
|
|
}
|
|
|
|
|
2018-06-19 17:20:49 +00:00
|
|
|
static int parse_ppid(int pid) {
|
2018-11-23 19:32:33 +00:00
|
|
|
char path[32];
|
|
|
|
int ppid;
|
2018-06-19 17:20:49 +00:00
|
|
|
sprintf(path, "/proc/%d/stat", pid);
|
2018-11-24 20:53:15 +00:00
|
|
|
FILE *stat = fopen(path, "re");
|
2018-11-23 19:32:33 +00:00
|
|
|
if (stat == nullptr)
|
2018-11-13 07:11:02 +00:00
|
|
|
return -1;
|
2018-06-19 17:20:49 +00:00
|
|
|
/* PID COMM STATE PPID ..... */
|
2018-11-23 19:32:33 +00:00
|
|
|
fscanf(stat, "%*d %*s %*c %d", &ppid);
|
2018-11-24 02:15:44 +00:00
|
|
|
fclose(stat);
|
2018-06-19 17:20:49 +00:00
|
|
|
return ppid;
|
|
|
|
}
|
|
|
|
|
2018-04-29 07:10:35 +00:00
|
|
|
static void hide_daemon(int pid) {
|
2018-11-23 20:47:49 +00:00
|
|
|
LOGD("hide_daemon: handling pid=[%d]\n", pid);
|
2017-07-10 15:39:33 +00:00
|
|
|
|
2018-11-23 19:32:33 +00:00
|
|
|
char buffer[4096];
|
2019-01-20 04:59:37 +00:00
|
|
|
vector<string> mounts;
|
2017-07-10 15:39:33 +00:00
|
|
|
|
|
|
|
manage_selinux();
|
2017-07-18 04:26:23 +00:00
|
|
|
clean_magisk_props();
|
2017-07-10 15:39:33 +00:00
|
|
|
|
|
|
|
if (switch_mnt_ns(pid))
|
2017-10-08 21:05:52 +00:00
|
|
|
goto exit;
|
2017-07-10 15:39:33 +00:00
|
|
|
|
2018-11-13 07:07:02 +00:00
|
|
|
snprintf(buffer, sizeof(buffer), "/proc/%d", pid);
|
|
|
|
chdir(buffer);
|
2017-07-10 15:39:33 +00:00
|
|
|
|
2019-01-20 04:59:37 +00:00
|
|
|
mounts = file_to_vector("mounts");
|
2018-06-16 21:16:52 +00:00
|
|
|
// Unmount dummy skeletons and /sbin links
|
2018-11-01 17:23:12 +00:00
|
|
|
for (auto &s : mounts) {
|
2019-01-20 04:59:37 +00:00
|
|
|
if (str_contains(s, "tmpfs /system/") || str_contains(s, "tmpfs /vendor/") ||
|
|
|
|
str_contains(s, "tmpfs /sbin")) {
|
|
|
|
sscanf(s.c_str(), "%*s %4096s", buffer);
|
2017-07-10 15:39:33 +00:00
|
|
|
lazy_unmount(buffer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Re-read mount infos
|
2019-01-20 04:59:37 +00:00
|
|
|
mounts = file_to_vector("mounts");
|
2017-07-10 15:39:33 +00:00
|
|
|
|
2018-06-16 21:16:52 +00:00
|
|
|
// Unmount everything under /system, /vendor, and loop mounts
|
2018-11-01 17:23:12 +00:00
|
|
|
for (auto &s : mounts) {
|
2019-01-20 04:59:37 +00:00
|
|
|
if ((str_contains(s, " /system/") || str_contains(s, " /vendor/")) &&
|
|
|
|
(str_contains(s, system_block) || str_contains(s, vendor_block) || str_contains(s, magiskloop))) {
|
|
|
|
sscanf(s.c_str(), "%*s %4096s", buffer);
|
2017-07-10 15:39:33 +00:00
|
|
|
lazy_unmount(buffer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-08 21:05:52 +00:00
|
|
|
exit:
|
|
|
|
// Send resume signal
|
|
|
|
kill(pid, SIGCONT);
|
|
|
|
_exit(0);
|
2017-07-10 15:39:33 +00:00
|
|
|
}
|
|
|
|
|
2017-04-21 16:54:08 +00:00
|
|
|
void proc_monitor() {
|
2017-11-14 21:15:58 +00:00
|
|
|
// Unblock user signals
|
|
|
|
sigset_t block_set;
|
|
|
|
sigemptyset(&block_set);
|
|
|
|
sigaddset(&block_set, TERM_THREAD);
|
2019-01-20 04:59:37 +00:00
|
|
|
pthread_sigmask(SIG_UNBLOCK, &block_set, nullptr);
|
2017-11-14 21:15:58 +00:00
|
|
|
|
2017-04-05 22:12:29 +00:00
|
|
|
// Register the cancel signal
|
2019-01-20 04:59:37 +00:00
|
|
|
struct sigaction act{};
|
2017-11-08 19:05:01 +00:00
|
|
|
act.sa_handler = term_thread;
|
2019-01-20 04:59:37 +00:00
|
|
|
sigaction(TERM_THREAD, &act, nullptr);
|
2017-05-07 19:11:14 +00:00
|
|
|
|
2018-06-19 17:20:49 +00:00
|
|
|
if (access("/proc/1/ns/mnt", F_OK) != 0) {
|
2017-07-10 15:39:33 +00:00
|
|
|
LOGE("proc_monitor: Your kernel doesn't support mount namespace :(\n");
|
2017-11-08 19:05:01 +00:00
|
|
|
term_thread(TERM_THREAD);
|
2017-07-10 15:39:33 +00:00
|
|
|
}
|
2017-03-25 10:21:48 +00:00
|
|
|
|
2019-02-10 06:05:19 +00:00
|
|
|
auto &queue = start_logging(HIDE_EVENT);
|
|
|
|
while (true) {
|
2018-11-23 20:47:49 +00:00
|
|
|
char *log;
|
|
|
|
int pid, ppid;
|
2018-10-12 04:50:47 +00:00
|
|
|
struct stat ns, pns;
|
|
|
|
|
2019-02-10 06:05:19 +00:00
|
|
|
string line = queue.take();
|
|
|
|
if ((log = strchr(&line[0], '[')) == nullptr)
|
2018-11-23 20:47:49 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
// Extract pid
|
|
|
|
if (sscanf(log, "[%*d,%d", &pid) != 1)
|
|
|
|
continue;
|
2017-12-18 10:17:37 +00:00
|
|
|
|
2018-11-23 20:47:49 +00:00
|
|
|
// Extract last token (component name)
|
|
|
|
const char *tok, *cpnt = "";
|
|
|
|
while ((tok = strtok_r(nullptr, ",[]\n", &log)))
|
|
|
|
cpnt = tok;
|
|
|
|
if (cpnt[0] == '\0')
|
2018-10-12 04:50:47 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
// Make sure our target is alive
|
2018-11-23 19:32:33 +00:00
|
|
|
if ((ppid = parse_ppid(pid)) < 0 || read_ns(ppid, &pns))
|
2018-10-12 04:50:47 +00:00
|
|
|
continue;
|
|
|
|
|
2018-11-01 17:23:12 +00:00
|
|
|
bool hide = false;
|
|
|
|
pthread_mutex_lock(&list_lock);
|
|
|
|
for (auto &s : hide_list) {
|
2019-01-20 04:59:37 +00:00
|
|
|
if (strncmp(cpnt, s.c_str(), s.size() - 1) == 0) {
|
2018-11-01 17:23:12 +00:00
|
|
|
hide = true;
|
2018-10-12 04:50:47 +00:00
|
|
|
break;
|
2018-07-03 17:52:23 +00:00
|
|
|
}
|
2018-10-12 04:50:47 +00:00
|
|
|
}
|
2018-11-01 17:23:12 +00:00
|
|
|
pthread_mutex_unlock(&list_lock);
|
2018-11-13 07:11:02 +00:00
|
|
|
|
2018-11-23 19:32:33 +00:00
|
|
|
if (!hide)
|
2018-10-12 04:50:47 +00:00
|
|
|
continue;
|
|
|
|
|
2018-11-23 19:32:33 +00:00
|
|
|
while (read_ns(pid, &ns) == 0 && ns.st_dev == pns.st_dev && ns.st_ino == pns.st_ino)
|
|
|
|
usleep(500);
|
2018-10-12 04:50:47 +00:00
|
|
|
|
|
|
|
// Send pause signal ASAP
|
|
|
|
if (kill(pid, SIGSTOP) == -1)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The setns system call do not support multithread processes
|
|
|
|
* We have to fork a new process, setns, then do the unmounts
|
|
|
|
*/
|
2018-11-23 20:47:49 +00:00
|
|
|
LOGI("proc_monitor: %s PID=[%d] ns=[%llu]\n", cpnt, pid, ns.st_ino);
|
2018-10-12 04:50:47 +00:00
|
|
|
if (fork_dont_care() == 0)
|
|
|
|
hide_daemon(pid);
|
2017-06-02 20:31:01 +00:00
|
|
|
}
|
2017-03-24 19:45:12 +00:00
|
|
|
}
|