From b36e6d987dcc7d79727c3ca64df463877f7f827e Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Sun, 10 Jan 2021 17:11:00 -0800 Subject: [PATCH] Reorganize MagiskHide code Prepare for zygote injection hiding --- native/jni/magiskhide/hide_utils.cpp | 59 +++++++++++++++++------- native/jni/magiskhide/magiskhide.hpp | 7 ++- native/jni/magiskhide/proc_monitor.cpp | 62 ++++++-------------------- native/jni/utils/misc.cpp | 19 +++++--- native/jni/utils/misc.hpp | 1 + 5 files changed, 72 insertions(+), 76 deletions(-) diff --git a/native/jni/magiskhide/hide_utils.cpp b/native/jni/magiskhide/hide_utils.cpp index fccf7f224..be1107d46 100644 --- a/native/jni/magiskhide/hide_utils.cpp +++ b/native/jni/magiskhide/hide_utils.cpp @@ -15,11 +15,43 @@ using namespace std; -static pthread_t proc_monitor_thread; +static pthread_t monitor_thread; static bool hide_state = false; +static set> hide_set; /* set of pair */ +map> uid_proc_map; /* uid -> list of process */ -// This locks the 2 variables above -static pthread_mutex_t hide_state_lock = PTHREAD_MUTEX_INITIALIZER; +// Locks the variables above +pthread_mutex_t hide_state_lock = PTHREAD_MUTEX_INITIALIZER; + +void update_uid_map() { + mutex_guard lock(hide_state_lock); + uid_proc_map.clear(); + string data_path(APP_DATA_DIR); + size_t len = data_path.length(); + auto dir = open_dir(APP_DATA_DIR); + bool first_iter = true; + for (dirent *entry; (entry = xreaddir(dir.get()));) { + data_path.resize(len); + data_path += '/'; + data_path += entry->d_name; // multiuser user id + data_path += '/'; + size_t user_len = data_path.length(); + struct stat st; + for (auto &hide : hide_set) { + if (hide.first == ISOLATED_MAGIC) { + if (!first_iter) continue; + // Setup isolated processes + uid_proc_map[-1].emplace_back(hide.second); + } + data_path.resize(user_len); + data_path += hide.first; + if (stat(data_path.data(), &st)) + continue; + uid_proc_map[st.st_uid].emplace_back(hide.second); + } + first_iter = false; + } +} // Leave /proc fd opened as we're going to read from it repeatedly static DIR *procfp; @@ -43,11 +75,6 @@ bool hide_enabled() { return hide_state; } -void set_hide_state(bool state) { - mutex_guard g(hide_state_lock); - hide_state = state; -} - template static bool proc_name_match(int pid, const char *name) { char buf[4019]; @@ -124,7 +151,7 @@ static int add_list(const char *pkg, const char *proc) { { // Critical region - mutex_guard lock(monitor_lock); + mutex_guard lock(hide_state_lock); add_hide_set(pkg, proc); } @@ -146,7 +173,7 @@ static int rm_list(const char *pkg, const char *proc) { bool remove = false; { // Critical region - mutex_guard lock(monitor_lock); + mutex_guard lock(hide_state_lock); for (auto it = hide_set.begin(); it != hide_set.end();) { if (it->first == pkg && (proc[0] == '\0' || it->second == proc)) { remove = true; @@ -256,9 +283,6 @@ int launch_magiskhide() { LOGI("* Starting MagiskHide\n"); - // Initialize the mutex lock - pthread_mutex_init(&monitor_lock, nullptr); - // Initialize the hide list if (!init_list()) return DAEMON_ERROR; @@ -268,8 +292,7 @@ int launch_magiskhide() { hide_late_sensitive_props(); // Start monitoring - void *(*start)(void*) = [](void*) -> void* { proc_monitor(); }; - if (xpthread_create(&proc_monitor_thread, nullptr, start, nullptr)) + if (new_daemon_thread(&proc_monitor)) return DAEMON_ERROR; hide_state = true; @@ -282,7 +305,9 @@ int stop_magiskhide() { if (hide_state) { LOGI("* Stopping MagiskHide\n"); - pthread_kill(proc_monitor_thread, SIGTERMTHRD); + uid_proc_map.clear(); + hide_set.clear(); + pthread_kill(monitor_thread, SIGTERMTHRD); } hide_state = false; @@ -292,7 +317,7 @@ int stop_magiskhide() { void auto_start_magiskhide() { if (hide_enabled()) { - pthread_kill(proc_monitor_thread, SIGALRM); + pthread_kill(monitor_thread, SIGALRM); hide_late_sensitive_props(); } else if (SDK_INT >= 19) { db_settings dbs; diff --git a/native/jni/magiskhide/magiskhide.hpp b/native/jni/magiskhide/magiskhide.hpp index 1769d4976..c49f49f51 100644 --- a/native/jni/magiskhide/magiskhide.hpp +++ b/native/jni/magiskhide/magiskhide.hpp @@ -25,13 +25,12 @@ void ls_list(int client); // Process monitoring [[noreturn]] void proc_monitor(); -void update_uid_map(); // Utility functions void crawl_procfs(const std::function &fn); void crawl_procfs(DIR *dir, const std::function &fn); bool hide_enabled(); -void set_hide_state(bool state); +void update_uid_map(); // Hide policies void hide_daemon(int pid); @@ -39,8 +38,8 @@ void hide_unmount(int pid = getpid()); void hide_sensitive_props(); void hide_late_sensitive_props(); -extern pthread_mutex_t monitor_lock; -extern std::set> hide_set; +extern pthread_mutex_t hide_state_lock; +extern std::map> uid_proc_map; enum { LAUNCH_MAGISKHIDE, diff --git a/native/jni/magiskhide/proc_monitor.cpp b/native/jni/magiskhide/proc_monitor.cpp index e4ec37cec..eb45a46a2 100644 --- a/native/jni/magiskhide/proc_monitor.cpp +++ b/native/jni/magiskhide/proc_monitor.cpp @@ -18,18 +18,11 @@ using namespace std; static int inotify_fd = -1; -static void term_thread(int sig = SIGTERMTHRD); static void new_zygote(int pid); -/********************** - * All data structures - **********************/ - -set> hide_set; /* set of pair */ -static map zygote_map; /* zygote pid -> mnt ns */ -static map> uid_proc_map; /* uid -> list of process */ - -pthread_mutex_t monitor_lock; +/****************** + * Data structures + ******************/ #define PID_MAX 32768 struct pid_set { @@ -41,7 +34,10 @@ private: }; // true if pid is monitored -pid_set attaches; +static pid_set attaches; + +// zygote pid -> mnt ns +static map zygote_map; /******** * Utils @@ -69,36 +65,6 @@ static int parse_ppid(int pid) { return ppid; } -void update_uid_map() { - mutex_guard lock(monitor_lock); - uid_proc_map.clear(); - string data_path(APP_DATA_DIR); - size_t len = data_path.length(); - auto dir = open_dir(APP_DATA_DIR); - bool first_iter = true; - for (dirent *entry; (entry = xreaddir(dir.get()));) { - data_path.resize(len); - data_path += '/'; - data_path += entry->d_name; // multiuser user id - data_path += '/'; - size_t user_len = data_path.length(); - struct stat st; - for (auto &hide : hide_set) { - if (hide.first == ISOLATED_MAGIC) { - if (!first_iter) continue; - // Setup isolated processes - uid_proc_map[-1].emplace_back(hide.second); - } - data_path.resize(user_len); - data_path += hide.first; - if (stat(data_path.data(), &st)) - continue; - uid_proc_map[st.st_uid].emplace_back(hide.second); - } - first_iter = false; - } -} - static bool is_zygote_done() { #ifdef __LP64__ return zygote_map.size() >= 2; @@ -132,7 +98,7 @@ static void check_zygote() { static void setup_inotify() { inotify_fd = xinotify_init1(IN_CLOEXEC); if (inotify_fd < 0) - term_thread(); + return; // Setup inotify asynchronous I/O fcntl(inotify_fd, F_SETFL, O_ASYNC); @@ -160,8 +126,8 @@ static void setup_inotify() { ************************/ static void inotify_event(int) { - /* Make sure we can actually read stuffs - * or else the whole thread will be blocked.*/ + // Make sure we can actually read stuffs + // or else the whole thread will be blocked. struct pollfd pfd = { .fd = inotify_fd, .events = POLLIN, @@ -180,13 +146,8 @@ static void inotify_event(int) { // Workaround for the lack of pthread_cancel static void term_thread(int) { LOGD("proc_monitor: cleaning up\n"); - uid_proc_map.clear(); zygote_map.clear(); - hide_set.clear(); attaches.reset(); - // Misc - set_hide_state(false); - pthread_mutex_destroy(&monitor_lock); close(inotify_fd); inotify_fd = -1; LOGD("proc_monitor: terminate\n"); @@ -240,6 +201,9 @@ static bool check_pid(int pid) { return false; int uid = st.st_uid; + + // Start accessing uid_proc_map + mutex_guard lock(hide_state_lock); auto it = uid_proc_map.end(); if (uid % 100000 > 90000) { diff --git a/native/jni/utils/misc.cpp b/native/jni/utils/misc.cpp index 87aa54693..4cbafcdbf 100644 --- a/native/jni/utils/misc.cpp +++ b/native/jni/utils/misc.cpp @@ -121,15 +121,22 @@ int new_daemon_thread(thread_entry entry, void *arg) { return xpthread_create(&thread, &attr, entry, arg); } -static void *proxy_routine(void *fp) { - auto fn = reinterpret_cast*>(fp); - (*fn)(); - delete fn; - return nullptr; +int new_daemon_thread(void(*entry)()) { + thread_entry proxy = [](void *entry) -> void * { + reinterpret_cast(entry)(); + return nullptr; + }; + return new_daemon_thread(proxy, (void *) entry); } int new_daemon_thread(std::function &&entry) { - return new_daemon_thread(proxy_routine, new std::function(std::move(entry))); + thread_entry proxy = [](void *fp) -> void * { + auto fn = reinterpret_cast*>(fp); + (*fn)(); + delete fn; + return nullptr; + }; + return new_daemon_thread(proxy, new std::function(std::move(entry))); } static char *argv0; diff --git a/native/jni/utils/misc.hpp b/native/jni/utils/misc.hpp index 441f87f91..f3a1a89e5 100644 --- a/native/jni/utils/misc.hpp +++ b/native/jni/utils/misc.hpp @@ -60,6 +60,7 @@ static inline int parse_int(std::string_view s) { return parse_int(s.data()); } using thread_entry = void *(*)(void *); int new_daemon_thread(thread_entry entry, void *arg = nullptr); +int new_daemon_thread(void(*entry)()); int new_daemon_thread(std::function &&entry); static inline bool str_contains(std::string_view s, std::string_view ss) {