mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-04-29 22:14:27 +02:00
Move all MagiskInit entrypoints into init.rs
This commit is contained in:
parent
e0a356b319
commit
50af14f2a3
@ -1,10 +1,12 @@
|
|||||||
use crate::ffi::backup_init;
|
use crate::ffi::backup_init;
|
||||||
|
use crate::mount::is_rootfs;
|
||||||
|
use crate::twostage::hexpatch_init_for_second_stage;
|
||||||
use crate::{
|
use crate::{
|
||||||
ffi::{BootConfig, MagiskInit, magisk_proxy_main},
|
ffi::{BootConfig, MagiskInit, magisk_proxy_main},
|
||||||
logging::setup_klog,
|
logging::setup_klog,
|
||||||
};
|
};
|
||||||
use base::{
|
use base::{
|
||||||
FsPath, LibcReturn, LoggedResult, ResultExt, debug, info,
|
FsPath, LibcReturn, LoggedResult, ResultExt, info,
|
||||||
libc::{basename, getpid, mount, umask},
|
libc::{basename, getpid, mount, umask},
|
||||||
path, raw_cstr,
|
path, raw_cstr,
|
||||||
};
|
};
|
||||||
@ -35,32 +37,71 @@ impl MagiskInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn legacy_system_as_root(&mut self) {
|
fn first_stage(&self) {
|
||||||
info!("Legacy SAR Init");
|
info!("First Stage Init");
|
||||||
self.prepare_data();
|
self.prepare_data();
|
||||||
let is_two_stage = self.mount_system_root();
|
|
||||||
if is_two_stage {
|
if !path!("/sdcard").exists() && !path!("/first_stage_ramdisk/sdcard").exists() {
|
||||||
self.patch_init_for_second_stage();
|
self.hijack_init_with_switch_root();
|
||||||
|
self.restore_ramdisk_init();
|
||||||
|
} else {
|
||||||
|
self.restore_ramdisk_init();
|
||||||
|
// Fallback to hexpatch if /sdcard exists
|
||||||
|
hexpatch_init_for_second_stage(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn second_stage(&mut self) {
|
||||||
|
info!("Second Stage Init");
|
||||||
|
|
||||||
|
path!("/init").unmount().ok();
|
||||||
|
path!("/system/bin/init").unmount().ok(); // just in case
|
||||||
|
path!("/data/init").remove().ok();
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
// 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
|
||||||
|
if is_rootfs() {
|
||||||
|
// We are still on rootfs, so make sure we will execute the init of the 2nd stage
|
||||||
|
let init_path = path!("/init");
|
||||||
|
init_path.remove().ok();
|
||||||
|
init_path
|
||||||
|
.create_symlink_to(path!("/system/bin/init"))
|
||||||
|
.log_ok();
|
||||||
|
self.patch_rw_root();
|
||||||
} else {
|
} else {
|
||||||
self.patch_ro_root();
|
self.patch_ro_root();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn rootfs(&mut self) {
|
fn legacy_system_as_root(&mut self) {
|
||||||
|
info!("Legacy SAR Init");
|
||||||
|
self.prepare_data();
|
||||||
|
let is_two_stage = self.mount_system_root();
|
||||||
|
if is_two_stage {
|
||||||
|
hexpatch_init_for_second_stage(false);
|
||||||
|
} else {
|
||||||
|
self.patch_ro_root();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rootfs(&mut self) {
|
||||||
info!("RootFS Init");
|
info!("RootFS Init");
|
||||||
self.prepare_data();
|
self.prepare_data();
|
||||||
debug!("Restoring /init\n");
|
self.restore_ramdisk_init();
|
||||||
path!("/.backup/init").rename_to(path!("/init")).log_ok();
|
|
||||||
self.patch_rw_root();
|
self.patch_rw_root();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn recovery(&self) {
|
fn recovery(&self) {
|
||||||
info!("Ramdisk is recovery, abort");
|
info!("Ramdisk is recovery, abort");
|
||||||
self.restore_ramdisk_init();
|
self.restore_ramdisk_init();
|
||||||
path!("/.backup").remove_all().ok();
|
path!("/.backup").remove_all().ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn restore_ramdisk_init(&self) {
|
fn restore_ramdisk_init(&self) {
|
||||||
path!("/init").remove().ok();
|
path!("/init").remove().ok();
|
||||||
|
|
||||||
let orig_init = FsPath::from(backup_init());
|
let orig_init = FsPath::from(backup_init());
|
||||||
|
@ -1,26 +1,50 @@
|
|||||||
use crate::ffi::MagiskInit;
|
use crate::ffi::MagiskInit;
|
||||||
use crate::mount::is_rootfs;
|
|
||||||
use base::{
|
use base::{
|
||||||
LoggedResult, MappedFile, MutBytesExt, ResultExt, cstr, debug, error, info,
|
LoggedResult, MappedFile, MutBytesExt, ResultExt, cstr, debug, error,
|
||||||
libc::{O_CLOEXEC, O_CREAT, O_RDONLY, O_WRONLY},
|
libc::{O_CLOEXEC, O_CREAT, O_RDONLY, O_WRONLY},
|
||||||
path, raw_cstr,
|
path,
|
||||||
};
|
};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
|
||||||
fn patch_init_path(init: &mut MappedFile) {
|
pub(crate) fn hexpatch_init_for_second_stage(writable: bool) {
|
||||||
let from = "/system/bin/init";
|
let init = if writable {
|
||||||
let to = "/data/magiskinit";
|
MappedFile::open_rw(cstr!("/init"))
|
||||||
|
} else {
|
||||||
|
MappedFile::open(cstr!("/init"))
|
||||||
|
};
|
||||||
|
|
||||||
|
let Ok(mut init) = init else {
|
||||||
|
error!("Failed to open /init for hexpatch");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
// Redirect original init to magiskinit
|
// Redirect original init to magiskinit
|
||||||
|
let from = "/system/bin/init";
|
||||||
|
let to = "/data/magiskinit";
|
||||||
let v = init.patch(from.as_bytes(), to.as_bytes());
|
let v = init.patch(from.as_bytes(), to.as_bytes());
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
for off in &v {
|
for off in &v {
|
||||||
debug!("Patch @ {:#010X} [{}] -> [{}]", off, from, to);
|
debug!("Patch @ {:#010X} [{}] -> [{}]", off, from, to);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !writable {
|
||||||
|
// If we cannot directly modify /init, we need to bind mount a replacement on top of it
|
||||||
|
let src = path!("/init");
|
||||||
|
let dest = path!("/data/init");
|
||||||
|
let _: LoggedResult<()> = try {
|
||||||
|
{
|
||||||
|
let mut fd = dest.create(O_CREAT | O_WRONLY, 0)?;
|
||||||
|
fd.write_all(init.as_ref())?;
|
||||||
|
}
|
||||||
|
let attr = src.follow_link().get_attr()?;
|
||||||
|
dest.set_attr(&attr)?;
|
||||||
|
dest.bind_mount_to(src)?;
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MagiskInit {
|
impl MagiskInit {
|
||||||
fn hijack_init_with_switch_root(&self) {
|
pub(crate) fn hijack_init_with_switch_root(&self) {
|
||||||
// We make use of original init's `SwitchRoot` to help us bind mount
|
// We make use of original init's `SwitchRoot` to help us bind mount
|
||||||
// magiskinit to /system/bin/init to hijack second stage init.
|
// magiskinit to /system/bin/init to hijack second stage init.
|
||||||
//
|
//
|
||||||
@ -76,77 +100,4 @@ impl MagiskInit {
|
|||||||
debug!("Bind mount /data/magiskinit -> /sdcard");
|
debug!("Bind mount /data/magiskinit -> /sdcard");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn first_stage(&self) {
|
|
||||||
info!("First Stage Init");
|
|
||||||
self.prepare_data();
|
|
||||||
|
|
||||||
if !path!("/sdcard").exists() && !path!("/first_stage_ramdisk/sdcard").exists() {
|
|
||||||
self.hijack_init_with_switch_root();
|
|
||||||
self.restore_ramdisk_init();
|
|
||||||
} else {
|
|
||||||
self.restore_ramdisk_init();
|
|
||||||
|
|
||||||
// fallback to hexpatch if /sdcard exists
|
|
||||||
match MappedFile::open_rw(cstr!("/init")) {
|
|
||||||
Ok(mut map) => patch_init_path(&mut map),
|
|
||||||
_ => {
|
|
||||||
error!("Failed to open /init for hexpatch");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn patch_init_for_second_stage(&self) {
|
|
||||||
let src = path!("/init");
|
|
||||||
let dest = path!("/data/init");
|
|
||||||
// Patch init binary
|
|
||||||
match MappedFile::open(src) {
|
|
||||||
Ok(mut map) => {
|
|
||||||
patch_init_path(&mut map);
|
|
||||||
match dest.create(O_CREAT | O_WRONLY, 0) {
|
|
||||||
Ok(mut dest) => {
|
|
||||||
dest.write_all(map.as_ref()).log_ok();
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
error!("Failed to create {}", dest);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
error!("Failed to open {} for hexpatch", src);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let _: LoggedResult<()> = try {
|
|
||||||
let attr = src.follow_link().get_attr()?;
|
|
||||||
dest.set_attr(&attr)?;
|
|
||||||
dest.bind_mount_to(src)?;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn second_stage(&mut self) {
|
|
||||||
info!("Second Stage Init");
|
|
||||||
|
|
||||||
path!("/init").unmount().ok();
|
|
||||||
path!("/system/bin/init").unmount().ok(); // just in case
|
|
||||||
path!("/data/init").remove().ok();
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
// 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
|
|
||||||
if is_rootfs() {
|
|
||||||
// We are still on rootfs, so make sure we will execute the init of the 2nd stage
|
|
||||||
let init_path = path!("/init");
|
|
||||||
init_path.remove().ok();
|
|
||||||
init_path
|
|
||||||
.create_symlink_to(path!("/system/bin/init"))
|
|
||||||
.log_ok();
|
|
||||||
self.patch_rw_root();
|
|
||||||
} else {
|
|
||||||
self.patch_ro_root();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user