diff --git a/native/jni/core/bootstages.cpp b/native/jni/core/bootstages.cpp index 3cb6f9306..3a3c5a9fb 100644 --- a/native/jni/core/bootstages.cpp +++ b/native/jni/core/bootstages.cpp @@ -560,6 +560,9 @@ void post_fs_data(int client) { write_int(client, 0); close(client); + if (getenv("REMOUNT_ROOT")) + xmount(nullptr, "/", nullptr, MS_REMOUNT | MS_RDONLY, nullptr); + if (!check_data()) unblock_boot_process(); diff --git a/native/jni/init/early_mount.cpp b/native/jni/init/early_mount.cpp index efc659a31..30c501675 100644 --- a/native/jni/init/early_mount.cpp +++ b/native/jni/init/early_mount.cpp @@ -74,7 +74,7 @@ static void setup_block(const char *partname, char *block_dev) { } } -bool BaseInit::read_dt_fstab(const char *name, char *partname, char *fstype) { +bool MagiskInit::read_dt_fstab(const char *name, char *partname, char *fstype) { char path[128]; int fd; sprintf(path, "%s/fstab/%s/dev", cmd->dt_dir, name); @@ -152,10 +152,9 @@ void SARInit::early_mount() { if (mnt_##name) \ umount("/" #name); -void BaseInit::cleanup() { +void MagiskInit::cleanup() { + BaseInit::cleanup(); umount(SELINUX_MNT); - umount("/sys"); - umount("/proc"); umount_root(system); umount_root(vendor); umount_root(product); diff --git a/native/jni/init/init.cpp b/native/jni/init/init.cpp index 5855231a9..acad2f4e1 100644 --- a/native/jni/init/init.cpp +++ b/native/jni/init/init.cpp @@ -26,13 +26,17 @@ using namespace std; +constexpr const char *init_applet[] = + { "magiskpolicy", "supolicy", "magisk", nullptr }; +constexpr int (*init_applet_main[])(int, char *[]) = + { magiskpolicy_main, magiskpolicy_main, magisk_proxy_main, nullptr }; + #ifdef MAGISK_DEBUG static FILE *kmsg; static int vprintk(const char *fmt, va_list ap) { fprintf(kmsg, "magiskinit: "); return vfprintf(kmsg, fmt, ap); } - static void setup_klog() { mknod("/kmsg", S_IFCHR | 0666, makedev(1, 11)); int fd = xopen("/kmsg", O_WRONLY | O_CLOEXEC); @@ -46,11 +50,6 @@ static void setup_klog() { #define setup_klog(...) #endif -constexpr const char *init_applet[] = - { "magiskpolicy", "supolicy", nullptr }; -constexpr int (*init_applet_main[])(int, char *[]) = - { magiskpolicy_main, magiskpolicy_main, nullptr }; - static bool unxz(int fd, const uint8_t *buf, size_t size) { uint8_t out[8192]; xz_crc32_init(); @@ -113,6 +112,11 @@ static int dump_manager(const char *path, mode_t mode) { return 0; } +void BaseInit::cleanup() { + umount("/sys"); + umount("/proc"); +} + void BaseInit::re_exec_init() { LOGD("Re-exec /init\n"); cleanup(); @@ -121,19 +125,22 @@ void BaseInit::re_exec_init() { } void LegacyInit::preset() { + full_read("/init", &self.buf, &self.sz); + LOGD("Reverting /init\n"); root = open("/", O_RDONLY | O_CLOEXEC); rename("/.backup/init", "/init"); - rm_rf("/.backup"); } void SARInit::preset() { + full_read("/init", &self.buf, &self.sz); + LOGD("Cleaning rootfs\n"); root = open("/", O_RDONLY | O_CLOEXEC); frm_rf(root, { "overlay", "proc", "sys" }); } -void BaseInit::start() { +void MagiskInit::start() { // Prevent file descriptor confusion mknod("/null", S_IFCHR | 0666, makedev(1, 3)); int null = open("/null", O_RDWR | O_CLOEXEC); @@ -144,9 +151,6 @@ void BaseInit::start() { if (null > STDERR_FILENO) close(null); - full_read("/init", &self.buf, &self.sz); - full_read("/.backup/.magisk", &config.buf, &config.sz); - preset(); early_mount(); setup_rootfs(); diff --git a/native/jni/init/init.h b/native/jni/init/init.h index 67ea375ba..2302a3112 100644 --- a/native/jni/init/init.h +++ b/native/jni/init/init.h @@ -14,9 +14,18 @@ struct raw_data { class BaseInit { protected: cmdline *cmd; - raw_data self{}; - raw_data config{}; char **argv; + void re_exec_init(); + virtual void cleanup(); +public: + BaseInit(char *argv[], cmdline *cmd) : cmd(cmd), argv(argv) {} + virtual ~BaseInit() = default; + virtual void start() = 0; +}; + +class MagiskInit : public BaseInit { +protected: + raw_data self{}; int root = -1; bool load_sepol = false; bool mnt_system = false; @@ -24,34 +33,31 @@ protected: bool mnt_product = false; bool mnt_odm = false; - virtual void preset() {}; - virtual void early_mount() {} + virtual void preset() = 0; + virtual void early_mount() = 0; void setup_rootfs(); bool read_dt_fstab(const char *name, char *partname, char *fstype); bool patch_sepolicy(); - void cleanup(); - void re_exec_init(); - + void cleanup() override; public: - BaseInit(char *argv[], cmdline *cmd) : cmd(cmd), argv(argv) {} - virtual ~BaseInit() = default; - virtual void start(); + MagiskInit(char *argv[], cmdline *cmd) : BaseInit(argv, cmd) {}; + void start() override; }; -class LegacyInit : public BaseInit { +class LegacyInit : public MagiskInit { protected: void preset() override; void early_mount() override; public: - LegacyInit(char *argv[], cmdline *cmd) : BaseInit(argv, cmd) {}; + LegacyInit(char *argv[], cmdline *cmd) : MagiskInit(argv, cmd) {}; }; -class SARInit : public BaseInit { +class SARInit : public MagiskInit { protected: void preset() override; void early_mount() override; public: - SARInit(char *argv[], cmdline *cmd) : BaseInit(argv, cmd) {}; + SARInit(char *argv[], cmdline *cmd) : MagiskInit(argv, cmd) {}; }; static inline bool is_lnk(const char *name) { @@ -63,3 +69,4 @@ static inline bool is_lnk(const char *name) { void load_kernel_info(cmdline *cmd); int dump_magisk(const char *path, mode_t mode); +int magisk_proxy_main(int argc, char *argv[]); diff --git a/native/jni/init/rootfs.cpp b/native/jni/init/rootfs.cpp index 9010ebed2..5d24e7d64 100644 --- a/native/jni/init/rootfs.cpp +++ b/native/jni/init/rootfs.cpp @@ -1,11 +1,13 @@ #include #include +#include #include #include #include #include "init.h" +#include "flags.h" #include "magiskrc.h" #ifdef USE_64BIT @@ -37,7 +39,7 @@ constexpr const char wrapper[] = "exec /sbin/magisk.bin \"$0\" \"$@\"\n" ; -void BaseInit::setup_rootfs() { +void MagiskInit::setup_rootfs() { bool patch_init = patch_sepolicy(); if (cmd->system_as_root) { @@ -125,55 +127,13 @@ void BaseInit::setup_rootfs() { link_dir(sbin, rootdir); close(sbin); - LOGD("Mount /sbin tmpfs overlay\n"); - xmount("tmpfs", "/sbin", "tmpfs", 0, "mode=755"); - sbin = xopen("/sbin", O_RDONLY | O_CLOEXEC); - - char path[64]; - - // Create symlinks pointing back to /root - DIR *dir = xfdopendir(rootdir); - struct dirent *entry; - while((entry = xreaddir(dir))) { - if (entry->d_name == "."sv || entry->d_name == ".."sv) - continue; - sprintf(path, "/root/%s", entry->d_name); - xsymlinkat(path, sbin, entry->d_name); - } - - // Dump binaries - mkdir(MAGISKTMP, 0755); - fd = xopen(MAGISKTMP "/config", O_WRONLY | O_CREAT, 0000); - write(fd, config.buf, config.sz); - close(fd); - fd = xopen("/sbin/magiskinit", O_WRONLY | O_CREAT, 0755); + // Dump magiskinit as magisk + fd = xopen("/sbin/magisk", O_WRONLY | O_CREAT, 0755); write(fd, self.buf, self.sz); close(fd); - if (access("/system/apex", F_OK) == 0) { - LOGD("APEX detected, use wrapper\n"); - dump_magisk("/sbin/magisk.bin", 0755); - patch_socket_name("/sbin/magisk.bin"); - fd = xopen("/sbin/magisk", O_WRONLY | O_CREAT, 0755); - write(fd, wrapper, sizeof(wrapper) - 1); - close(fd); - } else { - dump_magisk("/sbin/magisk", 0755); - patch_socket_name("/sbin/magisk"); - } - - // Create applet symlinks - for (int i = 0; applet_names[i]; ++i) { - sprintf(path, "/sbin/%s", applet_names[i]); - xsymlink("/sbin/magisk", path); - } - xsymlink("/sbin/magiskinit", "/sbin/magiskpolicy"); - xsymlink("/sbin/magiskinit", "/sbin/supolicy"); - - close(rootdir); - close(sbin); } -bool BaseInit::patch_sepolicy() { +bool MagiskInit::patch_sepolicy() { bool patch_init = false; if (access(SPLIT_PLAT_CIL, R_OK) == 0) { @@ -214,3 +174,86 @@ bool BaseInit::patch_sepolicy() { return patch_init; } + +#ifdef MAGISK_DEBUG +static FILE *kmsg; +static int vprintk(const char *fmt, va_list ap) { + fprintf(kmsg, "magiskinit: "); + return vfprintf(kmsg, fmt, ap); +} +static void setup_klog() { + int fd = xopen("/proc/kmsg", O_WRONLY | O_CLOEXEC); + kmsg = fdopen(fd, "w"); + setbuf(kmsg, nullptr); + log_cb.d = log_cb.i = log_cb.w = log_cb.e = vprintk; + log_cb.ex = nop_ex; +} +#else +#define setup_klog(...) +#endif + +int magisk_proxy_main(int argc, char *argv[]) { + setup_klog(); + + raw_data config; + raw_data self; + + full_read("/sbin/magisk", &self.buf, &self.sz); + full_read("/.backup/.magisk", &config.buf, &config.sz); + + xmount(nullptr, "/", nullptr, MS_REMOUNT, nullptr); + + unlink("/sbin/magisk"); + rm_rf("/.backup"); + + LOGD("Mount /sbin tmpfs overlay\n"); + xmount("tmpfs", "/sbin", "tmpfs", 0, "mode=755"); + int sbin = xopen("/sbin", O_RDONLY | O_CLOEXEC); + + char path[64]; + + // Create symlinks pointing back to /root + { + unique_ptr dir(xopendir("/root"), &closedir); + struct dirent *entry; + while((entry = xreaddir(dir.get()))) { + if (entry->d_name == "."sv || entry->d_name == ".."sv) + continue; + sprintf(path, "/root/%s", entry->d_name); + xsymlinkat(path, sbin, entry->d_name); + } + } + + // Dump binaries + mkdir(MAGISKTMP, 0755); + int fd = xopen(MAGISKTMP "/config", O_WRONLY | O_CREAT, 0000); + write(fd, config.buf, config.sz); + close(fd); + fd = xopen("/sbin/magiskinit", O_WRONLY | O_CREAT, 0755); + write(fd, self.buf, self.sz); + close(fd); + if (access("/system/apex", F_OK) == 0) { + LOGD("APEX detected, use wrapper\n"); + dump_magisk("/sbin/magisk.bin", 0755); + patch_socket_name("/sbin/magisk.bin"); + fd = xopen("/sbin/magisk", O_WRONLY | O_CREAT, 0755); + write(fd, wrapper, sizeof(wrapper) - 1); + close(fd); + } else { + dump_magisk("/sbin/magisk", 0755); + patch_socket_name("/sbin/magisk"); + } + + // Create applet symlinks + for (int i = 0; applet_names[i]; ++i) { + sprintf(path, "/sbin/%s", applet_names[i]); + xsymlink("/sbin/magisk", path); + } + xsymlink("/sbin/magiskinit", "/sbin/magiskpolicy"); + xsymlink("/sbin/magiskinit", "/sbin/supolicy"); + + setenv("REMOUNT_ROOT", "1", 1); + execv("/sbin/magisk", argv); + + return 1; +}