Commit 8893cbd6 authored by topjohnwu's avatar topjohnwu

Modularize MagiskInit

parent f0240b1f
...@@ -53,19 +53,10 @@ ...@@ -53,19 +53,10 @@
#define DEFAULT_DT_DIR "/proc/device-tree/firmware/android" #define DEFAULT_DT_DIR "/proc/device-tree/firmware/android"
int (*init_applet_main[]) (int, char *[]) = { magiskpolicy_main, magiskpolicy_main, nullptr }; int (*init_applet_main[])(int, char *[]) = { magiskpolicy_main, magiskpolicy_main, nullptr };
static bool mnt_system = false;
static bool mnt_vendor = false;
static bool mnt_product = false;
static bool mnt_odm = false;
static bool kirin = false;
static void *self, *config;
static size_t self_sz, config_sz;
struct cmdline { struct cmdline {
bool early_boot; bool system_as_root;
char slot[3]; char slot[3];
char dt_dir[128]; char dt_dir[128];
}; };
...@@ -78,7 +69,102 @@ struct device { ...@@ -78,7 +69,102 @@ struct device {
char path[64]; char path[64];
}; };
static void parse_cmdline(const std::function<void (std::string_view, const char *)> &fn) { struct raw_data {
void *buf;
size_t sz;
};
static bool unxz(int fd, const uint8_t *buf, size_t size) {
uint8_t out[8192];
xz_crc32_init();
struct xz_dec *dec = xz_dec_init(XZ_DYNALLOC, 1 << 26);
struct xz_buf b = {
.in = buf,
.in_pos = 0,
.in_size = size,
.out = out,
.out_pos = 0,
.out_size = sizeof(out)
};
enum xz_ret ret;
do {
ret = xz_dec_run(dec, &b);
if (ret != XZ_OK && ret != XZ_STREAM_END)
return false;
write(fd, out, b.out_pos);
b.out_pos = 0;
} while (b.in_pos != size);
return true;
}
static void decompress_ramdisk() {
constexpr char tmp[] = "tmp.cpio";
constexpr char ramdisk_xz[] = "ramdisk.cpio.xz";
if (access(ramdisk_xz, F_OK))
return;
uint8_t *buf;
size_t sz;
mmap_ro(ramdisk_xz, buf, sz);
int fd = open(tmp, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC);
unxz(fd, buf, sz);
munmap(buf, sz);
close(fd);
cpio_mmap cpio(tmp);
cpio.extract();
unlink(tmp);
unlink(ramdisk_xz);
}
static int dump_magisk(const char *path, mode_t mode) {
int fd = open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, mode);
if (fd < 0)
return 1;
if (!unxz(fd, magisk_xz, sizeof(magisk_xz)))
return 1;
close(fd);
return 0;
}
static int dump_manager(const char *path, mode_t mode) {
int fd = open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, mode);
if (fd < 0)
return 1;
if (!unxz(fd, manager_xz, sizeof(manager_xz)))
return 1;
close(fd);
return 0;
}
class MagiskInit {
private:
cmdline cmd{};
raw_data init{};
raw_data config{};
int root = -1;
bool mnt_system = false;
bool mnt_vendor = false;
bool mnt_product = false;
bool mnt_odm = false;
bool kirin = false;
char **argv;
void load_kernel_info();
void preset();
void early_mount();
void setup_rootfs();
bool read_dt_fstab(const char *mnt_point, char *partname, char *partfs);
bool patch_sepolicy();
void cleanup();
public:
explicit MagiskInit(char *argv[]) : argv(argv) {}
void setup_overlay();
void re_exec_init();
void start();
void test();
};
static inline void parse_cmdline(const std::function<void (std::string_view, const char *)> &fn) {
char cmdline[4096]; char cmdline[4096];
int fd = open("/proc/cmdline", O_RDONLY | O_CLOEXEC); int fd = open("/proc/cmdline", O_RDONLY | O_CLOEXEC);
cmdline[read(fd, cmdline, sizeof(cmdline))] = '\0'; cmdline[read(fd, cmdline, sizeof(cmdline))] = '\0';
...@@ -106,7 +192,13 @@ static void parse_cmdline(const std::function<void (std::string_view, const char ...@@ -106,7 +192,13 @@ static void parse_cmdline(const std::function<void (std::string_view, const char
} }
} }
static void parse_cmdline(struct cmdline *cmd) { void MagiskInit::load_kernel_info() {
// Communicate with kernel using procfs and sysfs
mkdir("/proc", 0755);
xmount("proc", "/proc", "proc", 0, nullptr);
mkdir("/sys", 0755);
xmount("sysfs", "/sys", "sysfs", 0, nullptr);
char cmdline[4096]; char cmdline[4096];
int fd = open("/proc/cmdline", O_RDONLY | O_CLOEXEC); int fd = open("/proc/cmdline", O_RDONLY | O_CLOEXEC);
cmdline[read(fd, cmdline, sizeof(cmdline))] = '\0'; cmdline[read(fd, cmdline, sizeof(cmdline))] = '\0';
...@@ -117,14 +209,14 @@ static void parse_cmdline(struct cmdline *cmd) { ...@@ -117,14 +209,14 @@ static void parse_cmdline(struct cmdline *cmd) {
parse_cmdline([&](auto key, auto value) -> void { parse_cmdline([&](auto key, auto value) -> void {
LOGD("cmdline: [%s]=[%s]\n", key.data(), value); LOGD("cmdline: [%s]=[%s]\n", key.data(), value);
if (key == "androidboot.slot_suffix") { if (key == "androidboot.slot_suffix") {
strcpy(cmd->slot, value); strcpy(cmd.slot, value);
} else if (key == "androidboot.slot") { } else if (key == "androidboot.slot") {
cmd->slot[0] = '_'; cmd.slot[0] = '_';
strcpy(cmd->slot + 1, value); strcpy(cmd.slot + 1, value);
} else if (key == "skip_initramfs") { } else if (key == "skip_initramfs") {
skip_initramfs = true; skip_initramfs = true;
} else if (key == "androidboot.android_dt_dir") { } else if (key == "androidboot.android_dt_dir") {
strcpy(cmd->dt_dir, value); strcpy(cmd.dt_dir, value);
} else if (key == "enter_recovery") { } else if (key == "enter_recovery") {
enter_recovery = value[0] == '1'; enter_recovery = value[0] == '1';
} else if (key == "androidboot.hardware") { } else if (key == "androidboot.hardware") {
...@@ -138,19 +230,40 @@ static void parse_cmdline(struct cmdline *cmd) { ...@@ -138,19 +230,40 @@ static void parse_cmdline(struct cmdline *cmd) {
fprintf(f, "RECOVERYMODE=true\n"); fprintf(f, "RECOVERYMODE=true\n");
fclose(f); fclose(f);
} }
cmd->early_boot = true; cmd.system_as_root = true;
} }
cmd.system_as_root |= skip_initramfs;
if (cmd.dt_dir[0] == '\0')
strcpy(cmd.dt_dir, DEFAULT_DT_DIR);
cmd->early_boot |= skip_initramfs; LOGD("system_as_root[%d] slot[%s] dt_dir[%s]\n", cmd.system_as_root, cmd.slot, cmd.dt_dir);
}
if (cmd->dt_dir[0] == '\0') void MagiskInit::preset() {
strcpy(cmd->dt_dir, DEFAULT_DT_DIR); root = open("/", O_RDONLY | O_CLOEXEC);
LOGD("cmdline: early_boot[%d] slot[%s] dt_dir[%s]\n", cmd->early_boot, cmd->slot, cmd->dt_dir); if (cmd.system_as_root) {
// Clear rootfs
const char *excl[] = { "overlay", "proc", "sys", nullptr };
excl_list = excl;
frm_rf(root);
excl_list = nullptr;
} 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)
re_exec_init();
}
} }
static void parse_device(struct device *dev, const char *uevent) { static inline void parse_device(struct device *dev, const char *uevent) {
dev->partname[0] = '\0'; dev->partname[0] = '\0';
FILE *fp = xfopen(uevent, "r"); FILE *fp = xfopen(uevent, "r");
char buf[64]; char buf[64];
...@@ -205,31 +318,112 @@ static inline bool is_lnk(const char *name) { ...@@ -205,31 +318,112 @@ static inline bool is_lnk(const char *name) {
return S_ISLNK(st.st_mode); return S_ISLNK(st.st_mode);
} }
static bool read_fstab_dt(const struct cmdline *cmd, const char *mnt_point, char *partname, char *partfs) { #define link_root(part) \
char buf[128]; if (is_lnk("/system_root" part)) \
struct stat st; cp_afc("/system_root" part, part)
sprintf(buf, "/%s", mnt_point);
if (is_lnk(buf)) #define mount_root(part) \
return false; if (!is_lnk("/" #part) && read_dt_fstab(#part, partname, fstype)) { \
int fd; setup_block(&dev, partname); \
sprintf(buf, "%s/fstab/%s/dev", cmd->dt_dir, mnt_point); xmkdir("/" #part, 0755); \
if ((fd = xopen(buf, O_RDONLY | O_CLOEXEC)) >= 0) { xmount(dev.path, "/" #part, fstype, MS_RDONLY, nullptr); \
read(fd, buf, sizeof(buf)); mnt_##part = true; \
close(fd); }
char *name = rtrim(strrchr(buf, '/') + 1);
sprintf(partname, "%s%s", name, strend(name, cmd->slot) ? cmd->slot : ""); void MagiskInit::early_mount() {
sprintf(buf, "%s/fstab/%s/type", cmd->dt_dir, mnt_point); struct device dev;
if ((fd = xopen(buf, O_RDONLY | O_CLOEXEC)) >= 0) { char partname[32];
lstat(buf, &st); char fstype[32];
read(fd, partfs, st.st_size);
close(fd); if (cmd.system_as_root) {
return true; sprintf(partname, "system%s", cmd.slot);
setup_block(&dev, partname);
xmkdir("/system_root", 0755);
xmount(dev.path, "/system_root", "ext4", MS_RDONLY, nullptr);
xmkdir("/system", 0755);
xmount("/system_root/system", "/system", nullptr, MS_BIND, nullptr);
// Copy if these partitions are symlinks
link_root("/vendor");
link_root("/product");
link_root("/odm");
} else {
mount_root(system);
}
mount_root(vendor);
mount_root(product);
mount_root(odm);
}
void MagiskInit::setup_rootfs() {
bool patch_init = patch_sepolicy();
if (cmd.system_as_root) {
// Clone rootfs except /system
int system_root = open("/system_root", O_RDONLY | O_CLOEXEC);
const char *excl[] = { "system", nullptr };
excl_list = excl;
clone_dir(system_root, root);
close(system_root);
excl_list = nullptr;
}
if (patch_init) {
constexpr char SYSTEM_INIT[] = "/system/bin/init";
// If init is symlink, copy it to rootfs so we can patch
struct stat st;
lstat("/init", &st);
if (S_ISLNK(st.st_mode))
cp_afc(SYSTEM_INIT, "/init");
char *addr;
size_t size;
mmap_rw("/init", addr, size);
for (char *p = addr; p < addr + size; ++p) {
if (memcmp(p, SPLIT_PLAT_CIL, sizeof(SPLIT_PLAT_CIL)) == 0) {
// Force init to load /sepolicy
memset(p, 'x', sizeof(SPLIT_PLAT_CIL) - 1);
p += sizeof(SPLIT_PLAT_CIL) - 1;
} else if (memcmp(p, SYSTEM_INIT, sizeof(SYSTEM_INIT)) == 0) {
// Force execute /init instead of /system/bin/init
strcpy(p, "/init");
p += sizeof(SYSTEM_INIT) - 1;
}
} }
munmap(addr, size);
} }
return false;
// Handle ramdisk overlays
int fd = open("/overlay", O_RDONLY | O_CLOEXEC);
if (fd >= 0) {
mv_dir(fd, root);
close(fd);
rmdir("/overlay");
}
// Patch init.rc
FILE *rc = xfopen("/init.rc", "ae");
char pfd_svc[8], ls_svc[8];
gen_rand_str(pfd_svc, sizeof(pfd_svc));
do {
gen_rand_str(ls_svc, sizeof(ls_svc));
} while (strcmp(pfd_svc, ls_svc) == 0);
fprintf(rc, magiskrc, pfd_svc, pfd_svc, ls_svc);
fclose(rc);
// Don't let init run in init yet
lsetfilecon("/init", "u:object_r:rootfs:s0");
// Create hardlink mirror of /sbin to /root
mkdir("/root", 0750);
clone_attr("/sbin", "/root");
int rootdir = xopen("/root", O_RDONLY | O_CLOEXEC);
int sbin = xopen("/sbin", O_RDONLY | O_CLOEXEC);
link_dir(sbin, rootdir);
} }
static bool patch_sepolicy() { bool MagiskInit::patch_sepolicy() {
bool patch_init = false; bool patch_init = false;
if (access(SPLIT_PLAT_CIL, R_OK) == 0) if (access(SPLIT_PLAT_CIL, R_OK) == 0)
...@@ -265,68 +459,40 @@ static bool patch_sepolicy() { ...@@ -265,68 +459,40 @@ static bool patch_sepolicy() {
return patch_init; return patch_init;
} }
static bool unxz(int fd, const uint8_t *buf, size_t size) { bool MagiskInit::read_dt_fstab(const char *mnt_point, char *partname, char *partfs) {
uint8_t out[8192]; char path[128];
xz_crc32_init(); int fd;
struct xz_dec *dec = xz_dec_init(XZ_DYNALLOC, 1 << 26); sprintf(path, "%s/fstab/%s/dev", cmd.dt_dir, mnt_point);
struct xz_buf b = { if ((fd = xopen(path, O_RDONLY | O_CLOEXEC)) >= 0) {
.in = buf, read(fd, path, sizeof(path));
.in_pos = 0, close(fd);
.in_size = size, char *name = rtrim(strrchr(path, '/') + 1);
.out = out, sprintf(partname, "%s%s", name, strend(name, cmd.slot) ? cmd.slot : "");
.out_pos = 0, sprintf(path, "%s/fstab/%s/type", cmd.dt_dir, mnt_point);
.out_size = sizeof(out) if ((fd = xopen(path, O_RDONLY | O_CLOEXEC)) >= 0) {
}; read(fd, partfs, 32);
enum xz_ret ret; close(fd);
do { return true;
ret = xz_dec_run(dec, &b); }
if (ret != XZ_OK && ret != XZ_STREAM_END) }
return false; return false;
write(fd, out, b.out_pos);
b.out_pos = 0;
} while (b.in_pos != size);
return true;
}
static void decompress_ramdisk() {
constexpr char tmp[] = "tmp.cpio";
constexpr char ramdisk_xz[] = "ramdisk.cpio.xz";
if (access(ramdisk_xz, F_OK))
return;
uint8_t *buf;
size_t sz;
mmap_ro(ramdisk_xz, buf, sz);
int fd = open(tmp, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC);
unxz(fd, buf, sz);
munmap(buf, sz);
close(fd);
cpio_mmap cpio(tmp);
cpio.extract();
unlink(tmp);
unlink(ramdisk_xz);
} }
static int dump_magisk(const char *path, mode_t mode) { #define umount_part(part) \
int fd = open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, mode); if (mnt_##part) \
if (fd < 0) umount("/" #part);
return 1;
if (!unxz(fd, magisk_xz, sizeof(magisk_xz)))
return 1;
close(fd);
return 0;
}
static int dump_manager(const char *path, mode_t mode) { void MagiskInit::cleanup() {
int fd = open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, mode); umount(SELINUX_MNT);
if (fd < 0) umount("/sys");
return 1; umount("/proc");
if (!unxz(fd, manager_xz, sizeof(manager_xz))) umount_part(system);
return 1; umount_part(vendor);
close(fd); umount_part(product);
return 0; umount_part(odm);
} }
static void patch_socket_name(const char *path) { static inline void patch_socket_name(const char *path) {
uint8_t *buf; uint8_t *buf;
char name[sizeof(MAIN_SOCKET)]; char name[sizeof(MAIN_SOCKET)];
size_t size; size_t size;
...@@ -346,19 +512,8 @@ static void patch_socket_name(const char *path) { ...@@ -346,19 +512,8 @@ static void patch_socket_name(const char *path) {
munmap(buf, size); munmap(buf, size);
} }
static void setup_init_rc() { void MagiskInit::setup_overlay() {
FILE *rc = xfopen("/init.rc", "ae"); char path[128];
char pfd_svc[8], ls_svc[8];
gen_rand_str(pfd_svc, sizeof(pfd_svc));
do {
gen_rand_str(ls_svc, sizeof(ls_svc));
} while (strcmp(pfd_svc, ls_svc) == 0);
fprintf(rc, magiskrc, pfd_svc, pfd_svc, ls_svc);
fclose(rc);
}
static void setup_overlay() {
char buf[128];
int fd; int fd;
// Wait for early-init start // Wait for early-init start
...@@ -375,10 +530,10 @@ static void setup_overlay() { ...@@ -375,10 +530,10 @@ static void setup_overlay() {
// Dump binaries // Dump binaries
mkdir(MAGISKTMP, 0755); mkdir(MAGISKTMP, 0755);
fd = xopen(MAGISKTMP "/config", O_WRONLY | O_CREAT, 0000); fd = xopen(MAGISKTMP "/config", O_WRONLY | O_CREAT, 0000);
write(fd, config, config_sz); write(fd, config.buf, config.sz);
close(fd); close(fd);
fd = xopen("/sbin/magiskinit", O_WRONLY | O_CREAT, 0755); fd = xopen("/sbin/magiskinit", O_WRONLY | O_CREAT, 0755);
write(fd, self, self_sz); write(fd, init.buf, init.sz);
close(fd); close(fd);
dump_magisk("/sbin/magisk", 0755); dump_magisk("/sbin/magisk", 0755);
patch_socket_name("/sbin/magisk"); patch_socket_name("/sbin/magisk");
...@@ -387,23 +542,23 @@ static void setup_overlay() { ...@@ -387,23 +542,23 @@ static void setup_overlay() {
// Create applet symlinks // Create applet symlinks
for (int i = 0; applet_names[i]; ++i) { for (int i = 0; applet_names[i]; ++i) {
sprintf(buf, "/sbin/%s", applet_names[i]); sprintf(path, "/sbin/%s", applet_names[i]);
xsymlink("/sbin/magisk", buf); xsymlink("/sbin/magisk", path);
} }
for (int i = 0; init_applet[i]; ++i) { for (int i = 0; init_applet[i]; ++i) {
sprintf(buf, "/sbin/%s", init_applet[i]); sprintf(path, "/sbin/%s", init_applet[i]);
xsymlink("/sbin/magiskinit", buf); xsymlink("/sbin/magiskinit", path);
} }
// Create symlinks pointing back to /root // Create symlinks pointing back to /root
DIR *dir; DIR *dir = xopendir("/root");
struct dirent *entry; struct dirent *entry;
dir = xopendir("/root");
fd = xopen("/sbin", O_RDONLY); fd = xopen("/sbin", O_RDONLY);
while((entry = xreaddir(dir))) { while((entry = xreaddir(dir))) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) continue; if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
snprintf(buf, PATH_MAX, "/root/%s", entry->d_name); continue;
xsymlinkat(buf, fd, entry->d_name); snprintf(path, PATH_MAX, "/root/%s", entry->d_name);
xsymlinkat(path, fd, entry->d_name);
} }
closedir(dir); closedir(dir);
close(fd); close(fd);
...@@ -412,40 +567,13 @@ static void setup_overlay() { ...@@ -412,40 +567,13 @@ static void setup_overlay() {
exit(0); exit(0);
} }
[[noreturn]] static void exec_init(char *argv[]) { void MagiskInit::re_exec_init() {
// Clean up cleanup();
umount(SELINUX_MNT);
umount("/sys");
umount("/proc");
if (mnt_system)
umount("/system");
if (mnt_vendor)
umount("/vendor");
if (mnt_product)
umount("/product");
if (mnt_odm)
umount("/odm");
execv("/init", argv); execv("/init", argv);
exit(1); exit(1);
} }
int main(int argc, char *argv[]) { void MagiskInit::start() {
umask(0);
no_logging();
for (int i = 0; init_applet[i]; ++i) {
if (strcmp(basename(argv[0]), init_applet[i]) == 0)
return (*init_applet_main[i])(argc, argv);
}
if (argc > 1 && strcmp(argv[1], "-x") == 0) {
if (strcmp(argv[2], "magisk") == 0)
return dump_magisk(argv[3], 0755);
else if (strcmp(argv[2], "manager") == 0)
return dump_manager(argv[3], 0644);
}
// Prevent file descriptor confusion // Prevent file descriptor confusion
mknod("/null", S_IFCHR | 0666, makedev(1, 3)); mknod("/null", S_IFCHR | 0666, makedev(1, 3));
int null = open("/null", O_RDWR | O_CLOEXEC); int null = open("/null", O_RDWR | O_CLOEXEC);
...@@ -456,155 +584,49 @@ int main(int argc, char *argv[]) { ...@@ -456,155 +584,49 @@ int main(int argc, char *argv[]) {
if (null > STDERR_FILENO) if (null > STDERR_FILENO)
close(null); close(null);
// Communicate with kernel using procfs and sysfs full_read("/init", &init.buf, &init.sz);
mkdir("/proc", 0755); full_read("/.backup/.magisk", &config.buf, &config.sz);
xmount("proc", "/proc", "proc", 0, nullptr);
mkdir("/sys", 0755);
xmount("sysfs", "/sys", "sysfs", 0, nullptr);
struct cmdline cmd{};
parse_cmdline(&cmd);
// Backup stuffs
full_read("/init", &self, &self_sz);
full_read("/.backup/.magisk", &config, &config_sz);
/*************
* Initialize
*************/
int root, sbin;
root = open("/", O_RDONLY | O_CLOEXEC);
if (cmd.early_boot) { load_kernel_info();
// Clear rootfs preset();
const char *excl[] = { "overlay", "proc", "sys", nullptr }; early_mount();
excl_list = excl; setup_rootfs();
frm_rf(root); }
excl_list = nullptr;
} 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)
exec_init(argv);
}
/**************
* Early Mount
**************/
struct device dev;
char partname[32];
char partfs[32];
if (cmd.early_boot) {
sprintf(partname, "system%s", cmd.slot);
setup_block(&dev, partname);
xmkdir("/system_root", 0755);
xmount(dev.path, "/system_root", "ext4", MS_RDONLY, nullptr);
xmkdir("/system", 0755);
xmount("/system_root/system", "/system", nullptr, MS_BIND, nullptr);
// Copy if these partitions are symlinks
if (is_lnk("/system_root/vendor"))
cp_afc("/system_root/vendor", "/vendor");
if (is_lnk("/system_root/product"))
cp_afc("/system_root/product", "/product");
if (is_lnk("/system_root/odm"))
cp_afc("/system_root/odm", "/odm");
} else if (read_fstab_dt(&cmd, "system", partname, partfs)) {
setup_block(&dev, partname);
xmount(dev.path, "/system", partfs, MS_RDONLY, nullptr);
mnt_system = true;
}
if (read_fstab_dt(&cmd, "vendor", partname, partfs)) {
setup_block(&dev, partname);
xmkdir("/vendor", 0755);
xmount(dev.path, "/vendor", partfs, MS_RDONLY, nullptr);
mnt_vendor = true;
}
if (read_fstab_dt(&cmd, "product", partname, partfs)) {
setup_block(&dev, partname);
xmkdir("/product", 0755);
xmount(dev.path, "/product", partfs, MS_RDONLY, nullptr);
mnt_product = true;
}
if (read_fstab_dt(&cmd, "odm", partname, partfs)) {
setup_block(&dev, partname);
xmkdir("/odm", 0755);
xmount(dev.path, "/odm", partfs, MS_RDONLY, nullptr);
mnt_odm = true;
}
/*************** void MagiskInit::test() {
* Setup Rootfs cmdline_logging();
***************/ log_cb.ex = nop_ex;
bool patch_init = patch_sepolicy(); chdir(argv[1]);
chroot(".");
chdir("/");
if (cmd.early_boot) { load_kernel_info();
// Clone rootfs except /system preset();
int system_root = open("/system_root", O_RDONLY | O_CLOEXEC); early_mount();
const char *excl[] = { "system", nullptr }; setup_rootfs();
excl_list = excl; cleanup();
clone_dir(system_root, root); }
close(system_root);
excl_list = nullptr;
}
if (patch_init) { int main(int argc, char *argv[]) {
constexpr char SYSTEM_INIT[] = "/system/bin/init"; umask(0);
// If init is symlink, copy it to rootfs so we can patch
struct stat st;
lstat("/init", &st);
if (S_ISLNK(st.st_mode))
cp_afc(SYSTEM_INIT, "/init");
char *addr; for (int i = 0; init_applet[i]; ++i) {
size_t size; if (strcmp(basename(argv[0]), init_applet[i]) == 0)
mmap_rw("/init", addr, size); return (*init_applet_main[i])(argc, argv);
for (char *p = addr; p < addr + size; ++p) {
if (memcmp(p, SPLIT_PLAT_CIL, sizeof(SPLIT_PLAT_CIL)) == 0) {
// Force init to load /sepolicy
memset(p, 'x', sizeof(SPLIT_PLAT_CIL) - 1);
p += sizeof(SPLIT_PLAT_CIL) - 1;
} else if (memcmp(p, SYSTEM_INIT, sizeof(SYSTEM_INIT)) == 0) {
// Force execute /init instead of /system/bin/init
strcpy(p, "/init");
p += sizeof(SYSTEM_INIT) - 1;
}
}
munmap(addr, size);
} }
// Handle ramdisk overlays if (argc > 1 && strcmp(argv[1], "-x") == 0) {
int fd = open("/overlay", O_RDONLY | O_CLOEXEC); if (strcmp(argv[2], "magisk") == 0)
if (fd >= 0) { return dump_magisk(argv[3], 0755);
mv_dir(fd, root); else if (strcmp(argv[2], "manager") == 0)
close(fd); return dump_manager(argv[3], 0644);
rmdir("/overlay");
} }
setup_init_rc(); MagiskInit init(argv);
// Don't let init run in init yet // Run the main routine
lsetfilecon("/init", "u:object_r:rootfs:s0"); init.start();
// Create hardlink mirror of /sbin to /root
mkdir("/root", 0750);
clone_attr("/sbin", "/root");
root = xopen("/root", O_RDONLY | O_CLOEXEC);
sbin = xopen("/sbin", O_RDONLY | O_CLOEXEC);
link_dir(sbin, root);
// Close all file descriptors // Close all file descriptors
for (int i = 0; i < 30; ++i) for (int i = 0; i < 30; ++i)
...@@ -612,7 +634,7 @@ int main(int argc, char *argv[]) { ...@@ -612,7 +634,7 @@ int main(int argc, char *argv[]) {
// Launch daemon to setup overlay // Launch daemon to setup overlay
if (fork_dont_care() == 0) if (fork_dont_care() == 0)
setup_overlay(); init.setup_overlay();
exec_init(argv); init.re_exec_init();
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment