diff --git a/native/src/init/lib.rs b/native/src/init/lib.rs index c3c338c16..04672c8e5 100644 --- a/native/src/init/lib.rs +++ b/native/src/init/lib.rs @@ -86,7 +86,6 @@ pub mod ffi { // Two stage init fn redirect_second_stage(self: &MagiskInit); - fn first_stage(self: &MagiskInit); // SELinux unsafe fn patch_sepolicy(self: &MagiskInit, in_: *const c_char, out: *const c_char); diff --git a/native/src/init/twostage.cpp b/native/src/init/twostage.cpp index 810a1073b..b4b6626bb 100644 --- a/native/src/init/twostage.cpp +++ b/native/src/init/twostage.cpp @@ -8,43 +8,6 @@ using namespace std; -void MagiskInit::first_stage() const noexcept { - LOGI("First Stage Init\n"); - prepare_data(); - - if (struct stat st{}; fstatat(-1, "/sdcard", &st, AT_SYMLINK_NOFOLLOW) != 0 && - fstatat(-1, "/first_stage_ramdisk/sdcard", &st, AT_SYMLINK_NOFOLLOW) != 0) { - if (config.force_normal_boot) { - xmkdirs("/first_stage_ramdisk/storage/self", 0755); - xsymlink("/system/system/bin/init", "/first_stage_ramdisk/storage/self/primary"); - LOGD("Symlink /first_stage_ramdisk/storage/self/primary -> /system/system/bin/init\n"); - close(xopen("/first_stage_ramdisk/sdcard", O_RDONLY | O_CREAT | O_CLOEXEC, 0)); - } else { - xmkdirs("/storage/self", 0755); - xsymlink("/system/system/bin/init", "/storage/self/primary"); - LOGD("Symlink /storage/self/primary -> /system/system/bin/init\n"); - } - xrename("/init", "/sdcard"); - // Try to keep magiskinit in rootfs for samsung RKP - if (mount("/sdcard", "/sdcard", nullptr, MS_BIND, nullptr) == 0) { - LOGD("Bind mount /sdcard -> /sdcard\n"); - } else { - // rootfs before 3.12 - xmount(REDIR_PATH, "/sdcard", nullptr, MS_BIND, nullptr); - LOGD("Bind mount " REDIR_PATH " -> /sdcard\n"); - } - restore_ramdisk_init(); - } else { - restore_ramdisk_init(); - // fallback to hexpatch if /sdcard exists - auto init = mmap_data("/init", true); - // Redirect original init to magiskinit - for (size_t off : init.patch(INIT_PATH, REDIR_PATH)) { - LOGD("Patch @ %08zX [" INIT_PATH "] -> [" REDIR_PATH "]\n", off); - } - } -} - void MagiskInit::redirect_second_stage() const noexcept { // Patch init binary int src = xopen("/init", O_RDONLY); diff --git a/native/src/init/twostage.rs b/native/src/init/twostage.rs index 5d98eec4d..a366f673a 100644 --- a/native/src/init/twostage.rs +++ b/native/src/init/twostage.rs @@ -1,26 +1,135 @@ use crate::ffi::MagiskInit; -use base::{cstr, info, raw_cstr, FsPath, ResultExt, libc::{statfs, umount2, MNT_DETACH, TMPFS_MAGIC}}; +use base::libc::{mount, MS_BIND}; +use base::{ + cstr, debug, info, + libc::{ + fstatat, stat, statfs, umount2, AT_SYMLINK_NOFOLLOW, MNT_DETACH, O_CLOEXEC, O_CREAT, + O_RDONLY, TMPFS_MAGIC, + }, + raw_cstr, FsPath, MappedFile, MutBytesExt, ResultExt, +}; use std::ffi::c_long; +use std::ptr::null; impl MagiskInit { + pub(crate) fn first_stage(&self) { + info!("First Stage Init"); + self.prepare_data(); + + if unsafe { + let mut st: stat = unsafe { std::mem::zeroed() }; + fstatat( + -1, + raw_cstr!("/sdcard"), + std::ptr::from_mut(&mut st), + AT_SYMLINK_NOFOLLOW, + ) != 0 + && fstatat( + -1, + raw_cstr!("/first_stage_ramdisk/sdcard"), + std::ptr::from_mut(&mut st), + AT_SYMLINK_NOFOLLOW, + ) != 0 + } { + if self.config.force_normal_boot { + FsPath::from(cstr!("/first_stage_ramdisk/storage/self")) + .mkdirs(0o755) + .log() + .ok(); + FsPath::from(cstr!("/system/system/bin/init")) + .symlink_to(FsPath::from(cstr!( + "/first_stage_ramdisk/storage/self/primary" + ))) + .log() + .ok(); + debug!( + "Symlink /first_stage_ramdisk/storage/self/primary -> /system/system/bin/init" + ); + FsPath::from(cstr!("/first_stage_ramdisk/sdcard")) + .create(O_RDONLY | O_CREAT | O_CLOEXEC, 0) + .log() + .ok(); + } else { + FsPath::from(cstr!("/storage/self")) + .mkdirs(0o755) + .log() + .ok(); + FsPath::from(cstr!("/system/system/bin/init")) + .symlink_to(FsPath::from(cstr!("/storage/self/primary"))) + .log() + .ok(); + debug!("Symlink /storage/self/primary -> /system/system/bin/init"); + } + FsPath::from(cstr!("/init")) + .rename_to(FsPath::from(cstr!("/sdcard"))) + .log() + .ok(); + // Try to keep magiskinit in rootfs for samsung RKP + if unsafe { + mount( + raw_cstr!("/sdcard"), + raw_cstr!("/sdcard"), + null(), + MS_BIND, + null(), + ) + } == 0 + { + debug!("Bind mount /sdcard -> /sdcard"); + } else { + // rootfs before 3.12 + unsafe { + mount( + raw_cstr!("/data/magiskinit"), + raw_cstr!("/sdcard"), + null(), + MS_BIND, + null(), + ) + }; + debug!("Bind mount /data/magiskinit -> /sdcard"); + } + self.restore_ramdisk_init(); + } else { + self.restore_ramdisk_init(); + + // fallback to hexpatch if /sdcard exists + if let Ok(mut map) = MappedFile::open_rw(cstr!("/init")) { + let from = "/system/bin/init"; + let to = "/data/magiskinit"; + + // Redirect original init to magiskinit + let v = map.patch(from.as_bytes(), to.as_bytes()); + for off in &v { + debug!("Patch @ {:#010X} [{}] -> [{}]", off, from, to); + } + } else { + debug!("Failed to open /init for hexpatch"); + } + } + } + pub(crate) fn second_stage(&mut self) { info!("Second Stage Init"); unsafe { umount2(raw_cstr!("/init"), MNT_DETACH); umount2(raw_cstr!("/system/bin/init"), MNT_DETACH); // just in case FsPath::from(cstr!("/data/init")).remove().ok(); - + // Make sure init dmesg logs won't get messed up *self.argv = raw_cstr!("/system/bin/init") as *mut _; // Some weird devices like meizu, uses 2SI but still have legacy rootfs let mut sfs: statfs = std::mem::zeroed(); statfs(raw_cstr!("/"), std::ptr::from_mut(&mut sfs)); - if sfs.f_type == 0x858458f6 || sfs.f_type as c_long == TMPFS_MAGIC { + if sfs.f_type == 0x858458f6 || sfs.f_type as c_long == TMPFS_MAGIC { // We are still on rootfs, so make sure we will execute the init of the 2nd stage let init_path = FsPath::from(cstr!("/init")); init_path.remove().ok(); - FsPath::from(cstr!("/system/bin/init")).symlink_to(init_path).log().ok(); + FsPath::from(cstr!("/system/bin/init")) + .symlink_to(init_path) + .log() + .ok(); self.patch_rw_root(); } else { self.patch_ro_root();