Boot MagiskInit as actual system-as-root

WIP, no customization. DO NOT USE YET!
This commit is contained in:
topjohnwu 2019-06-23 15:14:47 -07:00
parent 28cd6a75e7
commit 9ec8bc2166
5 changed files with 93 additions and 29 deletions

View File

@ -106,7 +106,7 @@ LOCAL_C_INCLUDES := \
LOCAL_SRC_FILES := \ LOCAL_SRC_FILES := \
init/init.cpp \ init/init.cpp \
init/early_mount.cpp \ init/early_mount.cpp \
init/rootfs.cpp \ init/rootdir.cpp \
init/getinfo.cpp \ init/getinfo.cpp \
magiskpolicy/api.cpp \ magiskpolicy/api.cpp \
magiskpolicy/magiskpolicy.cpp \ magiskpolicy/magiskpolicy.cpp \

View File

@ -53,17 +53,20 @@ static void collect_devices() {
closedir(dir); 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()) if (dev_list.empty())
collect_devices(); collect_devices();
for (;;) { for (;;) {
for (auto &dev : dev_list) { for (auto &dev : dev_list) {
if (strcasecmp(dev.partname, partname) == 0) { 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", 0755);
xmkdir("/dev/block", 0755); if (block_dev) {
mknod(block_dev, S_IFBLK | 0600, makedev(dev.major, dev.minor)); 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; return;
} }
} }
@ -148,6 +151,36 @@ void SARCompatInit::early_mount() {
mount_root(odm); mount_root(odm);
} }
static void switch_root(const string &path) {
LOGD("Switch root to %s\n", path.data());
vector<string> 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) \ #define umount_root(name) \
if (mnt_##name) \ if (mnt_##name) \
umount("/" #name); umount("/" #name);

View File

@ -132,6 +132,14 @@ void LegacyInit::preset() {
rename("/.backup/init", "/init"); 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() { void SARCompatInit::preset() {
full_read("/init", &self.buf, &self.sz); full_read("/init", &self.buf, &self.sz);
@ -140,23 +148,19 @@ void SARCompatInit::preset() {
frm_rf(root, { "overlay", "proc", "sys" }); frm_rf(root, { "overlay", "proc", "sys" });
} }
void MagiskInit::start() { void RootFSInit::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);
preset(); preset();
early_mount(); early_mount();
setup_rootfs(); setup_rootfs();
re_exec_init(); re_exec_init();
} }
void SARInit::start() {
preset();
early_mount();
re_exec_init();
}
class RecoveryInit : public BaseInit { class RecoveryInit : public BaseInit {
public: public:
RecoveryInit(char *argv[], cmdline *cmd) : BaseInit(argv, cmd) {}; RecoveryInit(char *argv[], cmdline *cmd) : BaseInit(argv, cmd) {};
@ -168,13 +172,12 @@ public:
} }
}; };
class TestInit : public SARCompatInit { class TestInit : public SARInit {
public: public:
TestInit(char *argv[], cmdline *cmd) : SARCompatInit(argv, cmd) {}; TestInit(char *argv[], cmdline *cmd) : SARInit(argv, cmd) {};
void start() override { void start() override {
preset(); preset();
early_mount(); early_mount();
setup_rootfs();
cleanup(); cleanup();
} }
}; };
@ -210,6 +213,16 @@ int main(int argc, char *argv[]) {
if (getpid() != 1) if (getpid() != 1)
return 1; return 1;
setup_klog(); 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{}; cmdline cmd{};
@ -219,7 +232,10 @@ int main(int argc, char *argv[]) {
if (run_test) { if (run_test) {
init = make_unique<TestInit>(argv, &cmd); init = make_unique<TestInit>(argv, &cmd);
} else if (cmd.system_as_root) { } else if (cmd.system_as_root) {
init = make_unique<SARCompatInit>(argv, &cmd); if (access("/overlay", F_OK) == 0) /* Compatible mode */
init = make_unique<SARCompatInit>(argv, &cmd);
else
init = make_unique<SARInit>(argv, &cmd);
} else { } else {
decompress_ramdisk(); decompress_ramdisk();
if (access("/sbin/recovery", F_OK) == 0) if (access("/sbin/recovery", F_OK) == 0)

View File

@ -35,29 +35,44 @@ protected:
virtual void preset() = 0; virtual void preset() = 0;
virtual void early_mount() = 0; virtual void early_mount() = 0;
void setup_rootfs();
bool read_dt_fstab(const char *name, char *partname, char *fstype); bool read_dt_fstab(const char *name, char *partname, char *fstype);
bool patch_sepolicy(); bool patch_sepolicy();
void cleanup() override; void cleanup() override;
public: public:
MagiskInit(char *argv[], cmdline *cmd) : BaseInit(argv, cmd) {}; 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; void start() override;
}; };
class LegacyInit : public MagiskInit { class RootFSInit : public MagiskInit {
protected: protected:
void preset() override; void setup_rootfs();
void early_mount() override;
public: 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: protected:
void preset() override; void preset() override;
void early_mount() override; void early_mount() override;
public: 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) { static inline bool is_lnk(const char *name) {

View File

@ -39,7 +39,7 @@ constexpr const char wrapper[] =
"exec /sbin/magisk.bin \"$0\" \"$@\"\n" "exec /sbin/magisk.bin \"$0\" \"$@\"\n"
; ;
void MagiskInit::setup_rootfs() { void RootFSInit::setup_rootfs() {
bool patch_init = patch_sepolicy(); bool patch_init = patch_sepolicy();
if (cmd->system_as_root) { if (cmd->system_as_root) {