diff --git a/native/jni/Android.mk b/native/jni/Android.mk index e33324e2b..20bc676ab 100644 --- a/native/jni/Android.mk +++ b/native/jni/Android.mk @@ -106,7 +106,7 @@ LOCAL_C_INCLUDES := \ LOCAL_SRC_FILES := \ init/init.cpp \ init/early_mount.cpp \ - init/rootfs.cpp \ + init/rootdir.cpp \ init/getinfo.cpp \ magiskpolicy/api.cpp \ magiskpolicy/magiskpolicy.cpp \ diff --git a/native/jni/init/early_mount.cpp b/native/jni/init/early_mount.cpp index 3682da96b..c9b47e44e 100644 --- a/native/jni/init/early_mount.cpp +++ b/native/jni/init/early_mount.cpp @@ -53,17 +53,20 @@ static void collect_devices() { closedir(dir); } -static void setup_block(const char *partname, char *block_dev) { +static void setup_block(const char *partname, char *block_dev = nullptr) { if (dev_list.empty()) collect_devices(); for (;;) { for (auto &dev : dev_list) { if (strcasecmp(dev.partname, partname) == 0) { - sprintf(block_dev, "/dev/block/%s", dev.devname); - LOGD("Found %s: [%s] (%d, %d)\n", dev.partname, dev.devname, dev.major, dev.minor); xmkdir("/dev", 0755); - xmkdir("/dev/block", 0755); - mknod(block_dev, S_IFBLK | 0600, makedev(dev.major, dev.minor)); + if (block_dev) { + sprintf(block_dev, "/dev/block/%s", dev.devname); + xmkdir("/dev/block", 0755); + } + LOGD("Found %s: [%s] (%d, %d)\n", dev.partname, dev.devname, dev.major, dev.minor); + mknod(block_dev ? block_dev : "/dev/root", S_IFBLK | 0600, + makedev(dev.major, dev.minor)); return; } } @@ -148,6 +151,36 @@ void SARCompatInit::early_mount() { mount_root(odm); } +static void switch_root(const string &path) { + LOGD("Switch root to %s\n", path.data()); + vector mounts; + parse_mnt("/proc/mounts", [&](mntent *me) { + if (me->mnt_dir != "/"sv && me->mnt_dir != path) + mounts.emplace_back(me->mnt_dir); + return true; + }); + for (auto &dir : mounts) { + auto new_path = path + dir; + mkdir(new_path.data(), 0755); + xmount(dir.data(), new_path.c_str(), nullptr, MS_MOVE, nullptr); + } + chdir(path.data()); + xmount(path.data(), "/", nullptr, MS_MOVE, nullptr); + chroot("."); +} + +void SARInit::early_mount() { + char partname[32]; + + LOGD("Early mount system_root\n"); + sprintf(partname, "system%s", cmd->slot); + setup_block(partname); + xmkdir("/system_root", 0755); + if (xmount("/dev/root", "/system_root", "ext4", MS_RDONLY, nullptr)) + xmount("/dev/root", "/system_root", "erofs", MS_RDONLY, nullptr); + switch_root("/system_root"); +} + #define umount_root(name) \ if (mnt_##name) \ umount("/" #name); diff --git a/native/jni/init/init.cpp b/native/jni/init/init.cpp index c86b8ff9b..06c84fe71 100644 --- a/native/jni/init/init.cpp +++ b/native/jni/init/init.cpp @@ -132,6 +132,14 @@ void LegacyInit::preset() { rename("/.backup/init", "/init"); } +void SARInit::preset() { + full_read("/init", &self.buf, &self.sz); + + LOGD("Cleaning rootfs\n"); + root = open("/", O_RDONLY | O_CLOEXEC); + frm_rf(root, { "proc", "sys" }); +} + void SARCompatInit::preset() { full_read("/init", &self.buf, &self.sz); @@ -140,23 +148,19 @@ void SARCompatInit::preset() { frm_rf(root, { "overlay", "proc", "sys" }); } -void MagiskInit::start() { - // Prevent file descriptor confusion - mknod("/null", S_IFCHR | 0666, makedev(1, 3)); - int null = open("/null", O_RDWR | O_CLOEXEC); - unlink("/null"); - xdup3(null, STDIN_FILENO, O_CLOEXEC); - xdup3(null, STDOUT_FILENO, O_CLOEXEC); - xdup3(null, STDERR_FILENO, O_CLOEXEC); - if (null > STDERR_FILENO) - close(null); - +void RootFSInit::start() { preset(); early_mount(); setup_rootfs(); re_exec_init(); } +void SARInit::start() { + preset(); + early_mount(); + re_exec_init(); +} + class RecoveryInit : public BaseInit { public: RecoveryInit(char *argv[], cmdline *cmd) : BaseInit(argv, cmd) {}; @@ -168,13 +172,12 @@ public: } }; -class TestInit : public SARCompatInit { +class TestInit : public SARInit { public: - TestInit(char *argv[], cmdline *cmd) : SARCompatInit(argv, cmd) {}; + TestInit(char *argv[], cmdline *cmd) : SARInit(argv, cmd) {}; void start() override { preset(); early_mount(); - setup_rootfs(); cleanup(); } }; @@ -210,6 +213,16 @@ int main(int argc, char *argv[]) { if (getpid() != 1) return 1; setup_klog(); + + // Prevent file descriptor confusion + mknod("/null", S_IFCHR | 0666, makedev(1, 3)); + int null = open("/null", O_RDWR | O_CLOEXEC); + unlink("/null"); + xdup3(null, STDIN_FILENO, O_CLOEXEC); + xdup3(null, STDOUT_FILENO, O_CLOEXEC); + xdup3(null, STDERR_FILENO, O_CLOEXEC); + if (null > STDERR_FILENO) + close(null); } cmdline cmd{}; @@ -219,7 +232,10 @@ int main(int argc, char *argv[]) { if (run_test) { init = make_unique(argv, &cmd); } else if (cmd.system_as_root) { - init = make_unique(argv, &cmd); + if (access("/overlay", F_OK) == 0) /* Compatible mode */ + init = make_unique(argv, &cmd); + else + init = make_unique(argv, &cmd); } else { decompress_ramdisk(); if (access("/sbin/recovery", F_OK) == 0) diff --git a/native/jni/init/init.h b/native/jni/init/init.h index 3fa6e9490..8041f8b39 100644 --- a/native/jni/init/init.h +++ b/native/jni/init/init.h @@ -35,29 +35,44 @@ protected: 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() override; public: MagiskInit(char *argv[], cmdline *cmd) : BaseInit(argv, cmd) {}; +}; + +class SARInit : public MagiskInit { +protected: + void preset() override; + void early_mount() override; +public: + SARInit(char *argv[], cmdline *cmd) : MagiskInit(argv, cmd) {}; void start() override; }; -class LegacyInit : public MagiskInit { +class RootFSInit : public MagiskInit { protected: - void preset() override; - void early_mount() override; + void setup_rootfs(); public: - LegacyInit(char *argv[], cmdline *cmd) : MagiskInit(argv, cmd) {}; + RootFSInit(char *argv[], cmdline *cmd) : MagiskInit(argv, cmd) {}; + void start() override; }; -class SARCompatInit : public MagiskInit { +class LegacyInit : public RootFSInit { protected: void preset() override; void early_mount() override; public: - SARCompatInit(char *argv[], cmdline *cmd) : MagiskInit(argv, cmd) {}; + LegacyInit(char *argv[], cmdline *cmd) : RootFSInit(argv, cmd) {}; +}; + +class SARCompatInit : public RootFSInit { +protected: + void preset() override; + void early_mount() override; +public: + SARCompatInit(char *argv[], cmdline *cmd) : RootFSInit(argv, cmd) {}; }; static inline bool is_lnk(const char *name) { diff --git a/native/jni/init/rootfs.cpp b/native/jni/init/rootdir.cpp similarity index 99% rename from native/jni/init/rootfs.cpp rename to native/jni/init/rootdir.cpp index 5d24e7d64..70a670075 100644 --- a/native/jni/init/rootfs.cpp +++ b/native/jni/init/rootdir.cpp @@ -39,7 +39,7 @@ constexpr const char wrapper[] = "exec /sbin/magisk.bin \"$0\" \"$@\"\n" ; -void MagiskInit::setup_rootfs() { +void RootFSInit::setup_rootfs() { bool patch_init = patch_sepolicy(); if (cmd->system_as_root) {