From 5c7f69acaa022963b3a65f5fce6c09706a11d66b Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Sun, 16 Jun 2019 12:45:32 -0700 Subject: [PATCH] Separate SAR and legacy implementation --- native/jni/init/early_mount.cpp | 76 +++++++++++------- native/jni/init/init.cpp | 135 ++++++++++++++++---------------- native/jni/init/init.h | 32 ++++++-- native/jni/init/rootfs.cpp | 4 +- 4 files changed, 140 insertions(+), 107 deletions(-) diff --git a/native/jni/init/early_mount.cpp b/native/jni/init/early_mount.cpp index c4b4a572c..efc659a31 100644 --- a/native/jni/init/early_mount.cpp +++ b/native/jni/init/early_mount.cpp @@ -5,6 +5,7 @@ #include #include +#include #include "init.h" @@ -73,7 +74,7 @@ static void setup_block(const char *partname, char *block_dev) { } } -bool MagiskInit::read_dt_fstab(const char *name, char *partname, char *fstype) { +bool BaseInit::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); @@ -106,38 +107,57 @@ if (!is_lnk("/" #name) && read_dt_fstab(#name, partname, fstype)) { \ mnt_##name = true; \ } -void MagiskInit::early_mount() { +void LegacyInit::early_mount() { char partname[32]; char fstype[32]; char block_dev[64]; - if (cmd->system_as_root) { - LOGD("Early mount system_root\n"); - sprintf(partname, "system%s", cmd->slot); - setup_block(partname, block_dev); - xmkdir("/system_root", 0755); - if (xmount(block_dev, "/system_root", "ext4", MS_RDONLY, nullptr)) - xmount(block_dev, "/system_root", "erofs", MS_RDONLY, nullptr); - xmkdir("/system", 0755); - xmount("/system_root/system", "/system", nullptr, MS_BIND, nullptr); - - // Android Q - if (is_lnk("/system_root/init")) - load_sepol = true; - - // System-as-root with monolithic sepolicy - if (access("/system_root/sepolicy", F_OK) == 0) - cp_afc("/system_root/sepolicy", "/sepolicy"); - - // Copy if these partitions are symlinks - link_root("/vendor"); - link_root("/product"); - link_root("/odm"); - } else { - mount_root(system); - } - + mount_root(system); mount_root(vendor); mount_root(product); mount_root(odm); } + +void SARInit::early_mount() { + char partname[32]; + char fstype[32]; + char block_dev[64]; + + LOGD("Early mount system_root\n"); + sprintf(partname, "system%s", cmd->slot); + setup_block(partname, block_dev); + xmkdir("/system_root", 0755); + if (xmount(block_dev, "/system_root", "ext4", MS_RDONLY, nullptr)) + xmount(block_dev, "/system_root", "erofs", MS_RDONLY, nullptr); + xmkdir("/system", 0755); + xmount("/system_root/system", "/system", nullptr, MS_BIND, nullptr); + + // Android Q + if (is_lnk("/system_root/init")) + load_sepol = true; + + // System-as-root with monolithic sepolicy + if (access("/system_root/sepolicy", F_OK) == 0) + cp_afc("/system_root/sepolicy", "/sepolicy"); + + link_root("/vendor"); + link_root("/product"); + link_root("/odm"); + mount_root(vendor); + mount_root(product); + mount_root(odm); +} + +#define umount_root(name) \ +if (mnt_##name) \ + umount("/" #name); + +void BaseInit::cleanup() { + umount(SELINUX_MNT); + umount("/sys"); + umount("/proc"); + umount_root(system); + umount_root(vendor); + umount_root(product); + umount_root(odm); +} diff --git a/native/jni/init/init.cpp b/native/jni/init/init.cpp index 2df588336..5855231a9 100644 --- a/native/jni/init/init.cpp +++ b/native/jni/init/init.cpp @@ -6,13 +6,11 @@ #include #include #include -#include #include #include #include #include -#include #include #include #include @@ -48,12 +46,10 @@ static void setup_klog() { #define setup_klog(...) #endif -static int test_main(int argc, char *argv[]); - constexpr const char *init_applet[] = - { "magiskpolicy", "supolicy", "init_test", nullptr }; + { "magiskpolicy", "supolicy", nullptr }; constexpr int (*init_applet_main[])(int, char *[]) = - { magiskpolicy_main, magiskpolicy_main, test_main, nullptr }; + { magiskpolicy_main, magiskpolicy_main, nullptr }; static bool unxz(int fd, const uint8_t *buf, size_t size) { uint8_t out[8192]; @@ -117,50 +113,27 @@ static int dump_manager(const char *path, mode_t mode) { return 0; } -void MagiskInit::preset() { - root = open("/", O_RDONLY | O_CLOEXEC); - - if (cmd->system_as_root) { - // Clear rootfs - LOGD("Cleaning rootfs\n"); - frm_rf(root, { "overlay", "proc", "sys" }); - } else { - decompress_ramdisk(); - - // Revert original init binary - rename("/.backup/init", "/init"); - rm_rf("/.backup"); - - // Do not go further if device is booting into recovery - if (access("/sbin/recovery", F_OK) == 0) { - LOGD("Ramdisk is recovery, abort\n"); - re_exec_init(); - } - } -} - -#define umount_root(name) \ -if (mnt_##name) \ - umount("/" #name); - -void MagiskInit::cleanup() { - umount(SELINUX_MNT); - umount("/sys"); - umount("/proc"); - umount_root(system); - umount_root(vendor); - umount_root(product); - umount_root(odm); -} - -void MagiskInit::re_exec_init() { +void BaseInit::re_exec_init() { LOGD("Re-exec /init\n"); cleanup(); execv("/init", argv); exit(1); } -void MagiskInit::start() { +void LegacyInit::preset() { + LOGD("Reverting /init\n"); + root = open("/", O_RDONLY | O_CLOEXEC); + rename("/.backup/init", "/init"); + rm_rf("/.backup"); +} + +void SARInit::preset() { + LOGD("Cleaning rootfs\n"); + root = open("/", O_RDONLY | O_CLOEXEC); + frm_rf(root, { "overlay", "proc", "sys" }); +} + +void BaseInit::start() { // Prevent file descriptor confusion mknod("/null", S_IFCHR | 0666, makedev(1, 3)); int null = open("/null", O_RDWR | O_CLOEXEC); @@ -180,27 +153,27 @@ void MagiskInit::start() { re_exec_init(); } -void MagiskInit::test() { - cmdline_logging(); - log_cb.ex = nop_ex; +class RecoveryInit : public BaseInit { +public: + RecoveryInit(char *argv[], cmdline *cmd) : BaseInit(argv, cmd) {}; + void start() override { + LOGD("Ramdisk is recovery, abort\n"); + rename("/.backup/init", "/init"); + rm_rf("/.backup"); + re_exec_init(); + } +}; - chdir(dirname(argv[0])); - chroot("."); - chdir("/"); - - preset(); - early_mount(); - setup_rootfs(); - cleanup(); -} - -static int test_main(int, char *argv[]) { - cmdline cmd{}; - load_kernel_info(&cmd); - MagiskInit init(argv, &cmd); - init.test(); - return 0; -} +class TestInit : public SARInit { +public: + TestInit(char *argv[], cmdline *cmd) : SARInit(argv, cmd) {}; + void start() override { + preset(); + early_mount(); + setup_rootfs(); + cleanup(); + } +}; int main(int argc, char *argv[]) { umask(0); @@ -217,16 +190,40 @@ int main(int argc, char *argv[]) { return dump_manager(argv[3], 0644); } - if (getpid() != 1) - return 1; +#ifdef MAGISK_DEBUG + bool run_test = getenv("INIT_TEST") != nullptr; +#else + constexpr bool run_test = false; +#endif - setup_klog(); + if (run_test) { + chdir(dirname(argv[0])); + chroot("."); + chdir("/"); + cmdline_logging(); + log_cb.ex = nop_ex; + } else { + if (getpid() != 1) + return 1; + setup_klog(); + } cmdline cmd{}; load_kernel_info(&cmd); - MagiskInit init(argv, &cmd); + unique_ptr init; + if (run_test) { + init = make_unique(argv, &cmd); + } else if (cmd.system_as_root) { + init = make_unique(argv, &cmd); + } else { + decompress_ramdisk(); + if (access("/sbin/recovery", F_OK) == 0) + init = make_unique(argv, &cmd); + else + init = make_unique(argv, &cmd); + } // Run the main routine - init.start(); + init->start(); } diff --git a/native/jni/init/init.h b/native/jni/init/init.h index 5920c0f92..67ea375ba 100644 --- a/native/jni/init/init.h +++ b/native/jni/init/init.h @@ -11,21 +11,21 @@ struct raw_data { size_t sz; }; -class MagiskInit { -private: +class BaseInit { +protected: cmdline *cmd; raw_data self{}; raw_data config{}; - int root = -1; char **argv; + int root = -1; bool load_sepol = false; bool mnt_system = false; bool mnt_vendor = false; bool mnt_product = false; bool mnt_odm = false; - void preset(); - void early_mount(); + virtual void preset() {}; + virtual void early_mount() {} void setup_rootfs(); bool read_dt_fstab(const char *name, char *partname, char *fstype); bool patch_sepolicy(); @@ -33,9 +33,25 @@ private: void re_exec_init(); public: - explicit MagiskInit(char *argv[], cmdline *cmd) : cmd(cmd), argv(argv) {} - void start(); - void test(); + BaseInit(char *argv[], cmdline *cmd) : cmd(cmd), argv(argv) {} + virtual ~BaseInit() = default; + virtual void start(); +}; + +class LegacyInit : public BaseInit { +protected: + void preset() override; + void early_mount() override; +public: + LegacyInit(char *argv[], cmdline *cmd) : BaseInit(argv, cmd) {}; +}; + +class SARInit : public BaseInit { +protected: + void preset() override; + void early_mount() override; +public: + SARInit(char *argv[], cmdline *cmd) : BaseInit(argv, cmd) {}; }; static inline bool is_lnk(const char *name) { diff --git a/native/jni/init/rootfs.cpp b/native/jni/init/rootfs.cpp index 20783b5dc..9010ebed2 100644 --- a/native/jni/init/rootfs.cpp +++ b/native/jni/init/rootfs.cpp @@ -37,7 +37,7 @@ constexpr const char wrapper[] = "exec /sbin/magisk.bin \"$0\" \"$@\"\n" ; -void MagiskInit::setup_rootfs() { +void BaseInit::setup_rootfs() { bool patch_init = patch_sepolicy(); if (cmd->system_as_root) { @@ -173,7 +173,7 @@ void MagiskInit::setup_rootfs() { close(sbin); } -bool MagiskInit::patch_sepolicy() { +bool BaseInit::patch_sepolicy() { bool patch_init = false; if (access(SPLIT_PLAT_CIL, R_OK) == 0) {