diff --git a/native/jni/core/bootstages.cpp b/native/jni/core/bootstages.cpp index c7181db68..47930f955 100644 --- a/native/jni/core/bootstages.cpp +++ b/native/jni/core/bootstages.cpp @@ -19,8 +19,8 @@ using namespace std; +bool pfs_done = false; static bool no_secure_dir = false; -static bool pfs_done = false; static bool safe_mode = false; /********* diff --git a/native/jni/include/daemon.hpp b/native/jni/include/daemon.hpp index 42510bc9d..f187cc376 100644 --- a/native/jni/include/daemon.hpp +++ b/native/jni/include/daemon.hpp @@ -31,6 +31,7 @@ enum { extern int SDK_INT; extern bool RECOVERY_MODE; +extern bool pfs_done; extern std::vector module_list; #define APP_DATA_DIR (SDK_INT >= 24 ? "/data/user_de" : "/data/user") diff --git a/native/jni/magiskhide/hide_policy.cpp b/native/jni/magiskhide/hide_policy.cpp index 936ebaf1a..be7b6e36d 100644 --- a/native/jni/magiskhide/hide_policy.cpp +++ b/native/jni/magiskhide/hide_policy.cpp @@ -13,51 +13,63 @@ static const char *prop_key[] = { "ro.boot.vbmeta.device_state", "ro.boot.verifiedbootstate", "ro.boot.flash.locked", "ro.boot.veritymode", "ro.boot.warranty_bit", "ro.warranty_bit", "ro.debuggable", "ro.secure", "ro.build.type", "ro.build.tags", "ro.build.selinux", - "ro.vendor.boot.warranty_bit", "ro.vendor.warranty_bit", - "vendor.boot.vbmeta.device_state", "vendor.boot.verifiedbootstate", nullptr }; + "ro.vendor.boot.warranty_bit", "ro.vendor.warranty_bit", nullptr }; - -static const char *prop_value[] = +static const char *prop_val[] = { "locked", "green", "1", "enforcing", "0", "0", "0", "1", "user", "release-keys", "0", - "0", "0", - "locked", "green", nullptr }; + "0", "0", nullptr }; + +static const char *late_prop_key[] = + { "vendor.boot.vbmeta.device_state", "vendor.boot.verifiedbootstate", nullptr }; + +static const char *late_prop_val[] = + { "locked", "green", nullptr }; void hide_sensitive_props() { LOGI("hide_policy: Hiding sensitive props\n"); - // Hide all sensitive props for (int i = 0; prop_key[i]; ++i) { auto value = getprop(prop_key[i]); - if (!value.empty() && value != prop_value[i]) - setprop(prop_key[i], prop_value[i], false); + if (!value.empty() && value != prop_val[i]) + setprop(prop_key[i], prop_val[i], false); } // Hide that we booted from recovery when magisk is in recovery mode auto bootmode = getprop("ro.bootmode"); - if (!bootmode.empty() && bootmode.find("recovery") != string::npos) { + if (!bootmode.empty() && str_contains(bootmode, "recovery")) { setprop("ro.bootmode", "unknown", false); } bootmode = getprop("ro.boot.mode"); - if (!bootmode.empty() && bootmode.find("recovery") != string::npos) { + if (!bootmode.empty() && str_contains(bootmode, "recovery")) { setprop("ro.boot.mode", "unknown", false); } - bootmode = getprop("vendor.boot.mode"); - if (!bootmode.empty() && bootmode.find("recovery") != string::npos) { - setprop("vendor.boot.mode", "unknown", false); - } // Xiaomi cross region flash auto hwc = getprop("ro.boot.hwc"); - if (!hwc.empty() && hwc.find("CN") != string::npos) { + if (!hwc.empty() && str_contains(hwc, "CN")) { setprop("ro.boot.hwc", "GLOBAL", false); } auto hwcountry = getprop("ro.boot.hwcountry"); - if (!hwcountry.empty() && hwcountry.find("China") != string::npos) { + if (!hwcountry.empty() && str_contains(hwcountry, "China")) { setprop("ro.boot.hwcountry", "GLOBAL", false); } } +void hide_late_sensitive_props() { + LOGI("hide_policy: Hiding sensitive props (late)\n"); + + for (int i = 0; late_prop_key[i]; ++i) { + auto value = getprop(late_prop_key[i]); + if (!value.empty() && value != late_prop_val[i]) + setprop(prop_key[i], late_prop_val[i], false); + } + auto bootmode = getprop("vendor.boot.mode"); + if (!bootmode.empty() && str_contains(bootmode, "recovery")) { + setprop("vendor.boot.mode", "unknown", false); + } +} + static inline void lazy_unmount(const char* mountpoint) { if (umount2(mountpoint, MNT_DETACH) != -1) LOGD("hide_policy: Unmounted (%s)\n", mountpoint); diff --git a/native/jni/magiskhide/hide_utils.cpp b/native/jni/magiskhide/hide_utils.cpp index 9b009ee25..fa33e65e7 100644 --- a/native/jni/magiskhide/hide_utils.cpp +++ b/native/jni/magiskhide/hide_utils.cpp @@ -16,15 +16,19 @@ using namespace std; static pthread_t proc_monitor_thread; +static bool hide_state = false; + +// This locks the 2 variables above +static pthread_mutex_t hide_state_lock = PTHREAD_MUTEX_INITIALIZER; // Leave /proc fd opened as we're going to read from it repeatedly static DIR *procfp; -void crawl_procfs(const function &fn) { +void crawl_procfs(const function &fn) { rewinddir(procfp); crawl_procfs(procfp, fn); } -void crawl_procfs(DIR *dir, const function &fn) { +void crawl_procfs(DIR *dir, const function &fn) { struct dirent *dp; int pid; while ((dp = readdir(dir))) { @@ -34,18 +38,20 @@ void crawl_procfs(DIR *dir, const function &fn) { } } -static bool hide_state = false; -static pthread_mutex_t hide_state_lock = PTHREAD_MUTEX_INITIALIZER; - bool hide_enabled() { mutex_guard g(hide_state_lock); return hide_state; } +void set_hide_state(bool state) { + mutex_guard g(hide_state_lock); + hide_state = state; +} + static bool proc_name_match(int pid, const char *name) { char buf[4019]; sprintf(buf, "/proc/%d/cmdline", pid); - if (FILE *f; (f = fopen(buf, "re"))) { + if (FILE *f = fopen(buf, "re")) { fgets(buf, sizeof(buf), f); fclose(f); if (strcmp(buf, name) == 0) @@ -174,7 +180,7 @@ static void init_list(const char *pkg, const char *proc) { #define GMS_PKG "com.google.android.gms" #define MICROG_PKG "org.microg.gms.droidguard" -bool init_list() { +static bool init_list() { LOGD("hide_list: initialize\n"); char *err = db_exec("SELECT * FROM hidelist", [](db_row &row) -> bool { @@ -211,7 +217,7 @@ void ls_list(int client) { close(client); } -static void set_hide_config() { +static void update_hide_config() { char sql[64]; sprintf(sql, "REPLACE INTO settings (key,value) VALUES('%s',%d)", DB_SETTING_KEYS[HIDE_CONFIG], hide_state); @@ -219,80 +225,66 @@ static void set_hide_config() { db_err(err); } -[[noreturn]] static void launch_err(int client, int code = DAEMON_ERROR) { - if (code != HIDE_IS_ENABLED) - hide_state = false; - if (client >= 0) { - write_int(client, code); - close(client); - } - pthread_mutex_unlock(&hide_state_lock); - pthread_exit(nullptr); -} - -void launch_magiskhide(int client) { - pthread_mutex_lock(&hide_state_lock); +int launch_magiskhide() { + mutex_guard g(hide_state_lock); if (SDK_INT < 19) - launch_err(client); + return DAEMON_ERROR; if (hide_state) - launch_err(client, HIDE_IS_ENABLED); + return HIDE_IS_ENABLED; if (access("/proc/1/ns/mnt", F_OK) != 0) - launch_err(client, HIDE_NO_NS); - - hide_state = true; - set_hide_config(); - LOGI("* Starting MagiskHide\n"); + return HIDE_NO_NS; if (procfp == nullptr && (procfp = opendir("/proc")) == nullptr) - launch_err(client); + return DAEMON_ERROR; + + LOGI("* Starting MagiskHide\n"); + + // Initialize the hide list + if (!init_list()) + return DAEMON_ERROR; hide_sensitive_props(); + if (pfs_done) + hide_late_sensitive_props(); // Initialize the mutex lock pthread_mutex_init(&monitor_lock, nullptr); - // Initialize the hide list - if (!init_list()) - launch_err(client); - - // Get thread reference - proc_monitor_thread = pthread_self(); - if (client >= 0) { - write_int(client, DAEMON_SUCCESS); - close(client); - client = -1; - } // Start monitoring - proc_monitor(); + void *(*start)(void*) = [](void*) -> void* { proc_monitor(); return nullptr; }; + if (xpthread_create(&proc_monitor_thread, nullptr, start, nullptr)) + return DAEMON_ERROR; - // proc_monitor should not return - launch_err(client); + hide_state = true; + update_hide_config(); + return DAEMON_SUCCESS; } int stop_magiskhide() { - LOGI("* Stopping MagiskHide\n"); - mutex_guard g(hide_state_lock); - if (hide_state) - pthread_kill(proc_monitor_thread, SIGTERMTHRD); - hide_state = false; - set_hide_config(); + if (hide_state) { + LOGI("* Stopping MagiskHide\n"); + pthread_kill(proc_monitor_thread, SIGTERMTHRD); + } + + hide_state = false; + update_hide_config(); return DAEMON_SUCCESS; } void auto_start_magiskhide() { if (hide_enabled()) { pthread_kill(proc_monitor_thread, SIGZYGOTE); + hide_late_sensitive_props(); } else if (SDK_INT >= 19) { db_settings dbs; get_db_settings(dbs, HIDE_CONFIG); - if (dbs[HIDE_CONFIG]) { - new_daemon_thread([]{ launch_magiskhide(-1); }); - } + if (dbs[HIDE_CONFIG]) + launch_magiskhide(); } } diff --git a/native/jni/magiskhide/magiskhide.cpp b/native/jni/magiskhide/magiskhide.cpp index 2c721b207..83fe0d960 100644 --- a/native/jni/magiskhide/magiskhide.cpp +++ b/native/jni/magiskhide/magiskhide.cpp @@ -54,8 +54,8 @@ void magiskhide_handler(int client) { switch (req) { case LAUNCH_MAGISKHIDE: - launch_magiskhide(client); - return; + res = launch_magiskhide(); + break; case STOP_MAGISKHIDE: res = stop_magiskhide(); break; @@ -67,8 +67,7 @@ void magiskhide_handler(int client) { break; case LS_HIDELIST: ls_list(client); - client = -1; - break; + return; case HIDE_STATUS: res = hide_enabled() ? HIDE_IS_ENABLED : HIDE_NOT_ENABLED; break; diff --git a/native/jni/magiskhide/magiskhide.hpp b/native/jni/magiskhide/magiskhide.hpp index 99fcda9a2..4f1c8c78f 100644 --- a/native/jni/magiskhide/magiskhide.hpp +++ b/native/jni/magiskhide/magiskhide.hpp @@ -16,7 +16,7 @@ #define SIGZYGOTE SIGUSR2 // CLI entries -void launch_magiskhide(int client); +int launch_magiskhide(); int stop_magiskhide(); int add_list(int client); int rm_list(int client); @@ -31,11 +31,13 @@ void update_uid_map(); 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); // Hide policies void hide_daemon(int pid); 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; diff --git a/native/jni/magiskhide/proc_monitor.cpp b/native/jni/magiskhide/proc_monitor.cpp index 8fa67b2e6..2a67b75c8 100644 --- a/native/jni/magiskhide/proc_monitor.cpp +++ b/native/jni/magiskhide/proc_monitor.cpp @@ -95,7 +95,7 @@ static void check_zygote() { crawl_procfs([](int pid) -> bool { char buf[512]; snprintf(buf, sizeof(buf), "/proc/%d/cmdline", pid); - if (FILE *f = fopen(buf, "re"); f) { + if (FILE *f = fopen(buf, "re")) { fgets(buf, sizeof(buf), f); if (strncmp(buf, "zygote", 6) == 0 && parse_ppid(pid) == 1) new_zygote(pid); @@ -167,7 +167,7 @@ static void term_thread(int) { hide_set.clear(); attaches.reset(); // Misc - hide_enabled = false; + set_hide_state(false); pthread_mutex_destroy(&monitor_lock); close(inotify_fd); inotify_fd = -1;