Move MagiskInit::first_stage to rust

This commit is contained in:
LoveSy 2025-01-31 13:25:53 +08:00 committed by John Wu
parent dc9d5a4cac
commit e0489eeffd
3 changed files with 113 additions and 42 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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();