From a5d7c41d209527fe7b45a2ef7d031add9b6fad24 Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Fri, 8 May 2020 00:45:11 -0700 Subject: [PATCH] Support Safe Mode detection When detecting device is booting as Safe Mode, disable all modules and MagiskHide and skip all operations. The only thing that'll be available in this state is root (Magisk Manager will also be disabled by system). Since the next normal boot will also have all modules disabled, this can be used to rescue a device in the case when a rogue module causes bootloop and no custom recovery is available (or recoveries without the ability to decrypt data). --- build.py | 2 +- native/jni/core/bootstages.cpp | 41 +++++++++++++--------------- native/jni/core/daemon.cpp | 3 +- native/jni/core/module.cpp | 11 +++----- native/jni/include/daemon.hpp | 8 ++++-- native/jni/include/magisk.hpp | 1 - native/jni/magiskhide/hide_utils.cpp | 5 ++-- 7 files changed, 35 insertions(+), 36 deletions(-) diff --git a/build.py b/build.py index 139271184..304cdd32a 100755 --- a/build.py +++ b/build.py @@ -299,7 +299,7 @@ def build_binary(args): header('* Building binaries: ' + ' '.join(args.target)) - os.utime(op.join('native', 'jni', 'include', 'flags.h')) + # os.utime(op.join('native', 'jni', 'include', 'flags.h')) # Basic flags global base_flags diff --git a/native/jni/core/bootstages.cpp b/native/jni/core/bootstages.cpp index 9ae198a00..794dc2a59 100644 --- a/native/jni/core/bootstages.cpp +++ b/native/jni/core/bootstages.cpp @@ -21,6 +21,7 @@ using namespace std; static bool no_secure_dir = false; static bool pfs_done = false; +static bool safe_mode = false; /********* * Setup * @@ -224,12 +225,6 @@ static void dump_logs() { pthread_exit(nullptr); } -[[noreturn]] static void core_only() { - pfs_done = true; - auto_start_magiskhide(); - unblock_boot_process(); -} - void post_fs_data(int client) { // ack write_int(client, 0); @@ -262,16 +257,21 @@ void post_fs_data(int client) { unblock_boot_process(); } - LOGI("* Running post-fs-data.d scripts\n"); - exec_common_script("post-fs-data"); + if (getprop("persist.sys.safemode", true) == "1") { + safe_mode = true; + // Disable all modules and magiskhide so next boot will be clean + foreach_modules("disable"); + stop_magiskhide(); + } else { + LOGI("* Running post-fs-data.d scripts\n"); + exec_common_script("post-fs-data"); + handle_modules(); + auto_start_magiskhide(); + } - // Core only mode - if (access(DISABLEFILE, F_OK) == 0) - core_only(); - - handle_modules(); - - core_only(); + // We still want to do magic mount because root itself might need it + magic_mount(); + unblock_boot_process(); } void late_start(int client) { @@ -290,7 +290,7 @@ void late_start(int client) { reboot(); } - if (!pfs_done) + if (!pfs_done || safe_mode) return; auto_start_magiskhide(); @@ -298,11 +298,8 @@ void late_start(int client) { LOGI("* Running service.d scripts\n"); exec_common_script("service"); - // Core only mode - if (access(DISABLEFILE, F_OK) != 0) { - LOGI("* Running module service scripts\n"); - exec_module_script("service", module_list); - } + LOGI("* Running module service scripts\n"); + exec_module_script("service", module_list); // All boot stage done, cleanup module_list.clear(); @@ -315,7 +312,7 @@ void boot_complete(int client) { write_int(client, 0); close(client); - if (!pfs_done) + if (!pfs_done || safe_mode) return; auto_start_magiskhide(); diff --git a/native/jni/core/daemon.cpp b/native/jni/core/daemon.cpp index 920cd010b..828c4bf9f 100644 --- a/native/jni/core/daemon.cpp +++ b/native/jni/core/daemon.cpp @@ -96,9 +96,10 @@ static void *request_handler(void *args) { exec_sql(client); break; case REMOVE_MODULES: - remove_modules(); + foreach_modules("remove"); write_int(client, 0); close(client); + reboot(); break; case GET_PATH: write_string(client, MAGISKTMP.data()); diff --git a/native/jni/core/module.cpp b/native/jni/core/module.cpp index 36f734dcc..91c74ed42 100644 --- a/native/jni/core/module.cpp +++ b/native/jni/core/module.cpp @@ -542,7 +542,7 @@ static void inject_magisk_bins(root_node *system) { delete bin->extract(init_applet[i]); } -static void mount_modules() { +void magic_mount() { node_entry::mirror_dir = MAGISKTMP + "/" MIRRDIR; node_entry::module_mnt = MAGISKTMP + "/" MODULEMNT "/"; @@ -683,12 +683,10 @@ void handle_modules() { // Recollect modules (module scripts could remove itself) module_list.clear(); collect_modules(); - - mount_modules(); } -void remove_modules() { - LOGI("* Remove all modules and reboot\n"); +void foreach_modules(const char *name) { + LOGI("* Add %s to all modules\n", name); auto dir = open_dir(MODULEROOT); if (!dir) return; @@ -700,9 +698,8 @@ void remove_modules() { continue; int modfd = xopenat(dfd, entry->d_name, O_RDONLY | O_CLOEXEC); - close(xopenat(modfd, "remove", O_RDONLY | O_CREAT | O_CLOEXEC, 0)); + close(xopenat(modfd, name, O_RDONLY | O_CREAT | O_CLOEXEC, 0)); close(modfd); } } - reboot(); } diff --git a/native/jni/include/daemon.hpp b/native/jni/include/daemon.hpp index a34c9e025..42510bc9d 100644 --- a/native/jni/include/daemon.hpp +++ b/native/jni/include/daemon.hpp @@ -40,15 +40,19 @@ void late_start(int client); void boot_complete(int client); void magiskhide_handler(int client); void su_daemon_handler(int client, struct ucred *credential); -void remove_modules(); +void foreach_modules(const char *name); // Misc int connect_daemon(bool create = false); -void auto_start_magiskhide(); void unlock_blocks(); void handle_modules(); +void magic_mount(); void reboot(); +// MagiskHide +void auto_start_magiskhide(); +int stop_magiskhide(); + // Scripting void exec_script(const char *script); void exec_common_script(const char *stage); diff --git a/native/jni/include/magisk.hpp b/native/jni/include/magisk.hpp index 2e03851fc..72afdbd35 100644 --- a/native/jni/include/magisk.hpp +++ b/native/jni/include/magisk.hpp @@ -7,7 +7,6 @@ #define JAVA_PACKAGE_NAME "com.topjohnwu.magisk" #define LOGFILE "/cache/magisk.log" #define UNBLOCKFILE "/dev/.magisk_unblock" -#define DISABLEFILE "/cache/.disable_magisk" #define SECURE_DIR "/data/adb" #define MODULEROOT SECURE_DIR "/modules" #define MODULEUPGRADE SECURE_DIR "/modules_update" diff --git a/native/jni/magiskhide/hide_utils.cpp b/native/jni/magiskhide/hide_utils.cpp index 3a804b379..16f3349f6 100644 --- a/native/jni/magiskhide/hide_utils.cpp +++ b/native/jni/magiskhide/hide_utils.cpp @@ -10,7 +10,6 @@ #include #include #include -#include #include "magiskhide.hpp" @@ -267,9 +266,11 @@ void launch_magiskhide(int client) { int stop_magiskhide() { LOGI("* Stopping MagiskHide\n"); + if (hide_enabled) + pthread_kill(proc_monitor_thread, SIGTERMTHRD); + hide_enabled = false; set_hide_config(); - pthread_kill(proc_monitor_thread, SIGTERMTHRD); return DAEMON_SUCCESS; }