diff --git a/native/jni/core/bootstages.cpp b/native/jni/core/bootstages.cpp index c04d770be..e0bd27921 100644 --- a/native/jni/core/bootstages.cpp +++ b/native/jni/core/bootstages.cpp @@ -19,12 +19,11 @@ #include #include #include -#include #include #include #include -#include #include +#include using namespace std; @@ -32,7 +31,7 @@ static char buf[PATH_MAX], buf2[PATH_MAX]; static vector module_list; static bool seperate_vendor; -char *system_block, *vendor_block, *magiskloop; +char *system_block, *vendor_block, *data_block; static int bind_mount(const char *from, const char *to); extern void auto_start_magiskhide(); @@ -135,7 +134,7 @@ void node_entry::create_module_tree(const char *module) { struct dirent *entry; auto full_path = get_path(); - snprintf(buf, PATH_MAX, "%s/%s%s", MOUNTPOINT, module, full_path.c_str()); + snprintf(buf, PATH_MAX, "%s/%s%s", MODULEROOT, module, full_path.c_str()); if (!(dir = xopendir(buf))) return; @@ -169,7 +168,7 @@ void node_entry::create_module_tree(const char *module) { node->status = IS_MODULE; } else if (IS_DIR(node)) { // Check if marked as replace - snprintf(buf2, PATH_MAX, "%s/%s%s/.replace", MOUNTPOINT, module, buf); + snprintf(buf2, PATH_MAX, "%s/%s%s/.replace", MODULEROOT, module, buf); if (access(buf2, F_OK) == 0) { // Replace everything, mark as leaf node->status = IS_MODULE; @@ -236,7 +235,7 @@ void node_entry::clone_skeleton() { continue; } else if (child->status & IS_MODULE) { // Mount from module file to dummy file - snprintf(buf2, PATH_MAX, "%s/%s%s/%s", MOUNTPOINT, + snprintf(buf2, PATH_MAX, "%s/%s%s/%s", MODULEROOT, child->module, full_path.c_str(), child->name.c_str()); } else if (child->status & (IS_SKEL | IS_INTER)) { // It's an intermediate folder, recursive clone @@ -262,7 +261,7 @@ void node_entry::magic_mount() { if (status & IS_MODULE) { // Mount module item auto real_path = get_path(); - snprintf(buf, PATH_MAX, "%s/%s%s", MOUNTPOINT, module, real_path.c_str()); + snprintf(buf, PATH_MAX, "%s/%s%s", MODULEROOT, module, real_path.c_str()); bind_mount(buf, real_path.c_str()); } else if (status & IS_SKEL) { // The node is labeled to be cloned with skeleton, lets do it @@ -338,7 +337,7 @@ static void exec_common_script(const char* stage) { static void exec_module_script(const char* stage) { for (const auto &m : module_list) { const auto module = m.c_str(); - snprintf(buf2, PATH_MAX, "%s/%s/%s.sh", MOUNTPOINT, module, stage); + snprintf(buf2, PATH_MAX, "%s/%s/%s.sh", MODULEROOT, module, stage); if (access(buf2, F_OK) == -1) continue; LOGI("%s: exec [%s.sh]\n", module, stage); @@ -418,18 +417,21 @@ static bool magisk_env() { // Remove legacy stuffs unlink("/data/magisk.img"); unlink("/data/magisk_debug.log"); + unlink(SECURE_DIR "/magisk.img"); + unlink(SECURE_DIR "/magisk_merge.img"); - // Symlink for legacy path users + // Legacy support symlink(MAGISKTMP, "/sbin/.core"); + xmkdir(MAGISKTMP "/img", 0755); // Create directories in tmpfs overlay xmkdirs(MIRRDIR "/system", 0755); xmkdir(MIRRDIR "/bin", 0755); xmkdir(BBPATH, 0755); - xmkdir(MOUNTPOINT, 0755); xmkdir(BLOCKDIR, 0755); - // Boot script directories + // /data/adb directories + xmkdir(MODULEROOT, 0755); xmkdir(SECURE_DIR "/post-fs-data.d", 0755); xmkdir(SECURE_DIR "/service.d", 0755); @@ -454,6 +456,9 @@ static bool magisk_env() { xmkdir(MIRRDIR "/vendor", 0755); xmount(vendor_block, MIRRDIR "/vendor", buf2, MS_RDONLY, nullptr); VLOGI("mount", vendor_block, MIRRDIR "/vendor"); + } else if (str_contains(line, " /data ")) { + sscanf(line.c_str(), "%s", buf); + data_block = strdup(buf); } else if (SDK_INT >= 24 && str_contains(line, " /proc ") && !str_contains(line, "hidepid=2")) { // Enforce hidepid @@ -482,16 +487,43 @@ static bool magisk_env() { return true; } +static void upgrade_modules() { + DIR *dir; + struct dirent *entry; + if ((dir = opendir(MODULEUPGRADE))) { + while ((entry = xreaddir(dir))) { + if (entry->d_type == DT_DIR) { + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) + continue; + // Cleanup old module if exists + snprintf(buf, sizeof(buf), "%s/%s", MODULEROOT, entry->d_name); + if (access(buf, F_OK) == 0) + rm_rf(buf); + LOGI("Upgrade / New module: %s\n", entry->d_name); + snprintf(buf2, sizeof(buf2), "%s/%s", MODULEUPGRADE, entry->d_name); + rename(buf2, buf); + } + } + closedir(dir); + rm_rf(MODULEUPGRADE); + } + // Legacy support + bind_mount(MODULEROOT, MAGISKTMP "/img"); + xmkdir(LEGACYCORE, 0755); + symlink(SECURE_DIR "/post-fs-data.d", LEGACYCORE "/post-fs-data.d"); + symlink(SECURE_DIR "/service.d", LEGACYCORE "/service.d"); +} + static void collect_modules() { - chdir(MOUNTPOINT); + chdir(MODULEROOT); + rm_rf("lost+found"); DIR *dir = xopendir("."); struct dirent *entry; while ((entry = xreaddir(dir))) { if (entry->d_type == DT_DIR) { if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0 || - strcmp(entry->d_name, ".core") == 0 || - strcmp(entry->d_name, "lost+found") == 0) + strcmp(entry->d_name, ".core") == 0) continue; chdir(entry->d_name); if (access("remove", F_OK) == 0) { @@ -510,47 +542,6 @@ static void collect_modules() { chdir("/"); } -static bool prepare_img() { - const char *alt_img[] = - { "/cache/magisk.img", "/data/magisk_merge.img", "/data/adb/magisk_merge.img" }; - - for (auto &alt : alt_img) { - if (merge_img(alt, MAINIMG)) { - LOGE("Image merge %s -> " MAINIMG " failed!\n", alt); - return false; - } - } - - if (access(MAINIMG, F_OK) == -1) { - if (create_img(MAINIMG, 64)) - return false; - } - - LOGI("* Mounting " MAINIMG "\n"); - magiskloop = mount_image(MAINIMG, MOUNTPOINT); - if (magiskloop == nullptr) - return false; - - // Migrate legacy boot scripts - struct stat st; - if (lstat(LEGACY_CORE "/post-fs-data.d", &st) == 0 && S_ISDIR(st.st_mode)) { - cp_afc(LEGACY_CORE "/post-fs-data.d", SECURE_DIR "/post-fs-data.d"); - rm_rf(LEGACY_CORE "/post-fs-data.d"); - } - if (lstat(LEGACY_CORE "/service.d", &st) == 0 && S_ISDIR(st.st_mode)) { - cp_afc(LEGACY_CORE "/service.d", SECURE_DIR "/service.d"); - rm_rf(LEGACY_CORE "/service.d"); - } - - // Links for legacy paths - xmkdir(LEGACY_CORE, 0755); - symlink(SECURE_DIR "/post-fs-data.d", LEGACY_CORE "/post-fs-data.d"); - symlink(SECURE_DIR "/service.d", LEGACY_CORE "/service.d"); - - collect_modules(); - return trim_img(MAINIMG, MOUNTPOINT, magiskloop) == 0; -} - static void install_apk(const char *apk) { setfilecon(apk, "u:object_r:" SEPOL_FILE_DOMAIN ":s0"); while (true) { @@ -688,24 +679,20 @@ void post_fs_data(int client) { start_logcat(); - // Run common scripts LOGI("* Running post-fs-data.d scripts\n"); exec_common_script("post-fs-data"); + upgrade_modules(); + // Core only mode if (access(DISABLEFILE, F_OK) == 0) core_only(); - if (!prepare_img()) { - LOGE("* Magisk image mount failed, switch to core-only mode\n"); - free(magiskloop); - magiskloop = nullptr; - creat(DISABLEFILE, 0644); - } - restorecon(); chmod(SECURE_DIR, 0700); + collect_modules(); + // Execute module scripts LOGI("* Running module post-fs-data scripts\n"); exec_module_script("post-fs-data"); @@ -726,17 +713,17 @@ void post_fs_data(int client) { for (const auto &m : module_list) { const auto module = m.c_str(); // Read props - snprintf(buf, PATH_MAX, "%s/%s/system.prop", MOUNTPOINT, module); + snprintf(buf, PATH_MAX, "%s/%s/system.prop", MODULEROOT, module); if (access(buf, F_OK) == 0) { LOGI("%s: loading [system.prop]\n", module); load_prop_file(buf, false); } // Check whether enable auto_mount - snprintf(buf, PATH_MAX, "%s/%s/auto_mount", MOUNTPOINT, module); + snprintf(buf, PATH_MAX, "%s/%s/auto_mount", MODULEROOT, module); if (access(buf, F_OK) == -1) continue; // Double check whether the system folder exists - snprintf(buf, PATH_MAX, "%s/%s/system", MOUNTPOINT, module); + snprintf(buf, PATH_MAX, "%s/%s/system", MODULEROOT, module); if (access(buf, F_OK) == -1) continue; @@ -744,9 +731,9 @@ void post_fs_data(int client) { has_modules = true; LOGI("%s: constructing magic mount structure\n", module); // If /system/vendor exists in module, create a link outside - snprintf(buf, PATH_MAX, "%s/%s/system/vendor", MOUNTPOINT, module); + snprintf(buf, PATH_MAX, "%s/%s/system/vendor", MODULEROOT, module); if (access(buf, F_OK) == 0) { - snprintf(buf2, PATH_MAX, "%s/%s/vendor", MOUNTPOINT, module); + snprintf(buf2, PATH_MAX, "%s/%s/vendor", MODULEROOT, module); unlink(buf2); xsymlink(buf, buf2); } diff --git a/native/jni/include/magisk.h b/native/jni/include/magisk.h index 48fcb45d7..1ff30d2c9 100644 --- a/native/jni/include/magisk.h +++ b/native/jni/include/magisk.h @@ -18,16 +18,18 @@ #define BLOCKDIR MAGISKTMP "/block" #define MIRRDIR MAGISKTMP "/mirror" #define BBPATH MAGISKTMP "/busybox" -#define MOUNTPOINT MAGISKTMP "/img" -#define LEGACY_CORE MOUNTPOINT "/.core" #define SECURE_DIR "/data/adb" -#define MAINIMG SECURE_DIR "/magisk.img" +#define MODULEROOT SECURE_DIR "/modules" +#define MODULEUPGRADE SECURE_DIR "/modules_update" #define DATABIN SECURE_DIR "/magisk" #define MAGISKDB SECURE_DIR "/magisk.db" #define SIMPLEMOUNT SECURE_DIR "/magisk_simple" #define BOOTCOUNT SECURE_DIR "/.boot_count" #define MANAGERAPK DATABIN "/magisk.apk" +// Legacy crap +#define LEGACYCORE MODULEROOT "/.core" + // selinux consts #define SELINUX_PATH "/sys/fs/selinux" #define SELINUX_ENFORCE SELINUX_PATH "/enforce" diff --git a/native/jni/magiskhide/hide_utils.cpp b/native/jni/magiskhide/hide_utils.cpp index c6234e362..c9b16529c 100644 --- a/native/jni/magiskhide/hide_utils.cpp +++ b/native/jni/magiskhide/hide_utils.cpp @@ -233,7 +233,7 @@ int rm_list(int client) { return ret; } -#define LEGACY_LIST MOUNTPOINT "/.core/hidelist" +#define LEGACY_LIST MODULEROOT "/.core/hidelist" static int collect_list(void *, int, char **data, char**) { LOGI("hide_list: [%s]\n", data[0]); diff --git a/native/jni/magiskhide/proc_monitor.cpp b/native/jni/magiskhide/proc_monitor.cpp index c226aae0d..98b29d217 100644 --- a/native/jni/magiskhide/proc_monitor.cpp +++ b/native/jni/magiskhide/proc_monitor.cpp @@ -26,7 +26,7 @@ using namespace std; -extern char *system_block, *vendor_block, *magiskloop; +extern char *system_block, *vendor_block, *data_block; // Workaround for the lack of pthread_cancel static void term_thread(int) { @@ -91,10 +91,10 @@ static void hide_daemon(int pid) { // Re-read mount infos mounts = file_to_vector("mounts"); - // Unmount everything under /system, /vendor, and loop mounts + // Unmount everything under /system, /vendor, and data mounts for (auto &s : mounts) { if ((str_contains(s, " /system/") || str_contains(s, " /vendor/")) && - (str_contains(s, system_block) || str_contains(s, vendor_block) || str_contains(s, magiskloop))) { + (str_contains(s, system_block) || str_contains(s, vendor_block) || str_contains(s, data_block))) { sscanf(s.c_str(), "%*s %4096s", buffer); lazy_unmount(buffer); } diff --git a/native/jni/utils/selinux.cpp b/native/jni/utils/selinux.cpp index 9a38473b5..d695f6fea 100644 --- a/native/jni/utils/selinux.cpp +++ b/native/jni/utils/selinux.cpp @@ -162,7 +162,8 @@ void restorecon() { if (write(fd, ADB_CON, sizeof(ADB_CON)) >= 0) lsetfilecon(SECURE_DIR, ADB_CON); close(fd); - fd = xopen(MOUNTPOINT, O_RDONLY | O_CLOEXEC); + lsetfilecon(MODULEROOT, MAGISK_CON); + fd = xopen(MODULEROOT, O_RDONLY | O_CLOEXEC); restore_syscon(fd); close(fd); fd = xopen(DATABIN, O_RDONLY | O_CLOEXEC); diff --git a/scripts/util_functions.sh b/scripts/util_functions.sh index a60c4f2b5..f107f62a2 100644 --- a/scripts/util_functions.sh +++ b/scripts/util_functions.sh @@ -52,7 +52,8 @@ abort() { resolve_vars() { MAGISKBIN=$NVBASE/magisk - IMG=$NVBASE/magisk.img + POSTFSDATAD=$NVBASE/post-fs-data.d + SERVICED=$NVBASE/service.d } ###################### @@ -351,7 +352,9 @@ find_manager_apk() { set_perm() { chown $2:$3 $1 || return 1 chmod $4 $1 || return 1 - [ -z $5 ] && chcon 'u:object_r:system_file:s0' $1 || chcon $5 $1 || return 1 + CON=$5 + [ -z $CON ] && CON=u:object_r:system_file:s0 + chcon $CON $1 || return 1 } set_perm_recursive() { @@ -370,64 +373,30 @@ mktouch() { } request_size_check() { - reqSizeM=`du -ms $1 | cut -f1` + reqSizeM=`du -ms "$1" | cut -f1` } request_zip_size_check() { reqSizeM=`unzip -l "$1" | tail -n 1 | awk '{ print int(($1 - 1) / 1048576 + 1) }'` } -check_filesystem() { - curSizeM=`wc -c < $1` - curSizeM=$((curSizeM / 1048576)) - local DF=`df -Pk $2 | grep $2` - curUsedM=`echo $DF | awk '{ print int($3 / 1024) }'` - curFreeM=`echo $DF | awk '{ print int($4 / 1024) }'` -} - -mount_snippet() { - MAGISKLOOP=`$MAGISKBIN/magisk imgtool mount $IMG $MOUNTPATH` - is_mounted $MOUNTPATH || abort "! $IMG mount failed..." -} - -mount_magisk_img() { - [ -z $reqSizeM ] && reqSizeM=0 - mkdir -p $MOUNTPATH 2>/dev/null - if [ -f "$IMG" ]; then - ui_print "- Found $IMG" - mount_snippet - check_filesystem $IMG $MOUNTPATH - if [ $reqSizeM -gt $curFreeM ]; then - newSizeM=$(((curSizeM + reqSizeM - curFreeM) / 32 * 32 + 64)) - ui_print "- Resizing $IMG to ${newSizeM}M" - $MAGISKBIN/magisk imgtool umount $MOUNTPATH $MAGISKLOOP - $MAGISKBIN/magisk imgtool resize $IMG $newSizeM >&2 - mount_snippet - fi - ui_print "- Mount $IMG to $MOUNTPATH" - else - newSizeM=$((reqSizeM / 32 * 32 + 64)) - ui_print "- Creating $IMG with size ${newSizeM}M" - $MAGISKBIN/magisk imgtool create $IMG $newSizeM >&2 - mount_snippet - fi -} - -unmount_magisk_img() { - check_filesystem $IMG $MOUNTPATH - newSizeM=$((curUsedM / 32 * 32 + 64)) - $MAGISKBIN/magisk imgtool umount $MOUNTPATH $MAGISKLOOP - if [ $curSizeM -gt $newSizeM ]; then - ui_print "- Shrinking $IMG to ${newSizeM}M" - $MAGISKBIN/magisk imgtool resize $IMG $newSizeM >&2 - fi -} - ################################## # Backwards Compatibile Functions ################################## + get_outfd() { setup_flashable; } +mount_magisk_img() { + $BOOTMODE && MODULE_BASE=modules_update || MODULE_BASE=modules + MODULEPATH=$NVBASE/$MODULE_BASE + mkdir -p $MODULEPATH 2>/dev/null + ln -s $MODULEPATH $MOUNTPATH +} + +unmount_magisk_img() { + rm -f $MODULEPATH 2>/dev/null +} + ####### # main #######