From 3f83919e09ec994114cc8ac9103a6cc33b599f9a Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Mon, 11 Jun 2018 02:26:18 +0800 Subject: [PATCH] Fix bootloops when flashing Magisk after data wipe on FBE devices --- native/jni/core/bootstages.c | 86 ++++++++++++++++++++++------------- native/jni/core/daemon.c | 3 +- native/jni/include/daemon.h | 2 +- native/jni/include/magiskrc.h | 5 +- scripts/flash_script.sh | 11 +++-- 5 files changed, 67 insertions(+), 40 deletions(-) diff --git a/native/jni/core/bootstages.c b/native/jni/core/bootstages.c index 1bce7cbce..7b52a5469 100644 --- a/native/jni/core/bootstages.c +++ b/native/jni/core/bootstages.c @@ -471,46 +471,31 @@ static const char wrapper[] = void startup() { if (!check_data()) - return; + unblock_boot_process(); - // uninstaller or core-only mode - if (access(UNINSTALLER, F_OK) == 0 || access(DISABLEFILE, F_OK) == 0) - goto initialize; + if (access(SECURE_DIR, F_OK) != 0) { + /* If the folder is not automatically created by the system, + * do NOT proceed further. Manual creation of the folder + * will cause bootloops on FBE devices. */ + LOGE(SECURE_DIR" is not present, abort..."); + unblock_boot_process(); + } - // Allocate buffer - buf = xmalloc(PATH_MAX); - buf2 = xmalloc(PATH_MAX); + // No uninstaller or core-only mode + if (access(UNINSTALLER, F_OK) != 0 && access(DISABLEFILE, F_OK) != 0) { + // Allocate buffer + buf = xmalloc(PATH_MAX); + buf2 = xmalloc(PATH_MAX); - simple_mount("/system"); - simple_mount("/vendor"); + simple_mount("/system"); + simple_mount("/vendor"); + } -initialize: LOGI("** Initializing Magisk\n"); // Unlock all blocks for rw unlock_blocks(); - // Magisk binaries - char *bin_path = NULL; - if (access("/cache/data_bin", F_OK) == 0) - bin_path = "/cache/data_bin"; - else if (access("/data/data/com.topjohnwu.magisk/install", F_OK) == 0) - bin_path = "/data/data/com.topjohnwu.magisk/install"; - else if (access("/data/user_de/0/com.topjohnwu.magisk/install", F_OK) == 0) - bin_path = "/data/user_de/0/com.topjohnwu.magisk/install"; - if (bin_path) { - rm_rf(DATABIN); - cp_afc(bin_path, DATABIN); - rm_rf(bin_path); - } - - // Migration - rm_rf("/data/magisk"); - unlink("/data/magisk.img"); - unlink("/data/magisk_debug.log"); - xmkdir("/data/adb", 0700); - chmod("/data/adb", 0700); - LOGI("* Creating /sbin overlay"); DIR *dir; struct dirent *entry; @@ -579,6 +564,27 @@ initialize: close(sbin); close(root); + // Alternative binaries paths + char *alt_bin[] = { "/cache/data_bin", "/data/magisk", + "/data/data/com.topjohnwu.magisk/install", + "/data/user_de/0/com.topjohnwu.magisk/install", NULL }; + char *bin_path = NULL; + for (int i = 0; alt_bin[i]; ++i) { + if (access(alt_bin[i], F_OK) == 0) { + bin_path = alt_bin[i]; + break; + } + } + if (bin_path) { + rm_rf(DATABIN); + cp_afc(bin_path, DATABIN); + rm_rf(bin_path); + } + + // Remove legacy stuffs + unlink("/data/magisk.img"); + unlink("/data/magisk_debug.log"); + // Create directories in tmpfs overlay xmkdirs(MIRRDIR "/system", 0755); xmkdir(MIRRDIR "/bin", 0755); @@ -650,6 +656,9 @@ void post_fs_data(int client) { write_int(client, 0); close(client); + // If post-fs-data mode is started, it means startup succeeded + setup_done = 1; + // Start the debug log start_debug_full_log(); @@ -669,6 +678,7 @@ void post_fs_data(int client) { goto core_only; // Mounting fails, we can only do core only stuffs restorecon(); + chmod(SECURE_DIR, 0700); // Run common scripts LOGI("* Running post-fs-data.d scripts\n"); @@ -765,12 +775,24 @@ void late_start(int client) { write_int(client, 0); close(client); + if (access(SECURE_DIR, F_OK) != 0) { + // It's safe to create the folder at this point if the system didn't create it + xmkdir(SECURE_DIR, 0700); + } + + if (!setup_done) { + // The setup failed for some reason, reboot and try again + exec_command_sync("/system/bin/reboot", NULL); + return; + } + // Allocate buffer if (buf == NULL) buf = xmalloc(PATH_MAX); if (buf2 == NULL) buf2 = xmalloc(PATH_MAX); // Wait till the full patch is done - waitpid(full_patch_pid, NULL, 0); + if (full_patch_pid > 0) + waitpid(full_patch_pid, NULL, 0); // Run scripts after full patch, most reliable way to run scripts LOGI("* Running service.d scripts\n"); diff --git a/native/jni/core/daemon.c b/native/jni/core/daemon.c index 9b7cf7cc3..c273ce6bb 100644 --- a/native/jni/core/daemon.c +++ b/native/jni/core/daemon.c @@ -21,8 +21,9 @@ #include "resetprop.h" #include "magiskpolicy.h" +int setup_done = 0; int seperate_vendor = 0; -int full_patch_pid; +int full_patch_pid = -1; static void *request_handler(void *args) { int client = *((int *) args); diff --git a/native/jni/include/daemon.h b/native/jni/include/daemon.h index 164a66faf..6b145354c 100644 --- a/native/jni/include/daemon.h +++ b/native/jni/include/daemon.h @@ -8,7 +8,7 @@ #include #include -extern int is_daemon_init; +extern int setup_done; extern int seperate_vendor; extern int full_patch_pid; diff --git a/native/jni/include/magiskrc.h b/native/jni/include/magiskrc.h index 31bbec9f2..6066d0f97 100644 --- a/native/jni/include/magiskrc.h +++ b/native/jni/include/magiskrc.h @@ -1,3 +1,4 @@ +#include "magisk.h" #include "magiskpolicy.h" const char magiskrc[] = @@ -10,9 +11,9 @@ const char magiskrc[] = "on post-fs-data\n" " load_persist_props\n" -" rm /dev/.magisk.unblock\n" +" rm "UNBLOCKFILE"\n" " start magisk_startup\n" -" wait /dev/.magisk.unblock 10\n" +" wait "UNBLOCKFILE" 10\n" " rm /dev/.magisk.unblock\n" "\n" diff --git a/scripts/flash_script.sh b/scripts/flash_script.sh index 37b85e960..20d56be1e 100644 --- a/scripts/flash_script.sh +++ b/scripts/flash_script.sh @@ -81,15 +81,18 @@ remove_system_su ui_print "- Constructing environment" -# Check if we can actually access the data (DE storage) DATA=false +DATA_DE=false if grep ' /data ' /proc/mounts | grep -vq 'tmpfs'; then - [ ! -d /data/adb ] && mkdir /data/adb - touch /data/adb/.write_test && rm /data/adb/.write_test && DATA=true + # Test if data is writable + touch /data/.rw && rm /data/.rw && DATA=true + # Test if DE storage is writable + $DATA && [ -d /data/adb ] && touch /data/adb/.rw && rm /data/adb/.rw && DATA_DE=true fi if $DATA; then - MAGISKBIN=/data/adb/magisk + MAGISKBIN=/data/magisk + $DATA_DE && MAGISKBIN=/data/adb/magisk run_migrations else MAGISKBIN=/cache/data_bin