Make FsPath a trait

This commit is contained in:
topjohnwu
2025-04-21 18:00:43 -07:00
committed by John Wu
parent c34c7838bb
commit f3fef7bfe4
21 changed files with 191 additions and 229 deletions
+5 -5
View File
@@ -1,5 +1,5 @@
use crate::ffi::{BootConfig, MagiskInit, backup_init};
use base::{BytesExt, MappedFile, path};
use base::{BytesExt, FsPath, MappedFile, cstr};
impl BootConfig {
#[allow(unused_imports, unused_unsafe)]
@@ -37,11 +37,11 @@ impl BootConfig {
impl MagiskInit {
pub(crate) fn check_two_stage(&self) -> bool {
path!("/first_stage_ramdisk").exists() ||
path!("/second_stage_resources").exists() ||
path!("/system/bin/init").exists() ||
cstr!("/first_stage_ramdisk").exists() ||
cstr!("/second_stage_resources").exists() ||
cstr!("/system/bin/init").exists() ||
// Use the apex folder to determine whether 2SI (Android 10+)
path!("/apex").exists() ||
cstr!("/apex").exists() ||
// If we still have no indication, parse the original init and see what's up
MappedFile::open(backup_init())
.map(|data| data.contains(b"selinux_setup"))
+19 -19
View File
@@ -6,9 +6,9 @@ use crate::{
logging::setup_klog,
};
use base::{
FsPath, LibcReturn, LoggedResult, ResultExt, info,
FsPath, FsPathMnt, LibcReturn, LoggedResult, ResultExt, cstr, info,
libc::{basename, getpid, mount, umask},
path, raw_cstr,
raw_cstr,
};
use std::{
ffi::{CStr, c_char},
@@ -41,7 +41,7 @@ impl MagiskInit {
info!("First Stage Init");
self.prepare_data();
if !path!("/sdcard").exists() && !path!("/first_stage_ramdisk/sdcard").exists() {
if !cstr!("/sdcard").exists() && !cstr!("/first_stage_ramdisk/sdcard").exists() {
self.hijack_init_with_switch_root();
self.restore_ramdisk_init();
} else {
@@ -54,9 +54,9 @@ impl MagiskInit {
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();
cstr!("/init").unmount().ok();
cstr!("/system/bin/init").unmount().ok(); // just in case
cstr!("/data/init").remove().ok();
unsafe {
// Make sure init dmesg logs won't get messed up
@@ -66,10 +66,10 @@ impl MagiskInit {
// 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");
let init_path = cstr!("/init");
init_path.remove().ok();
init_path
.create_symlink_to(path!("/system/bin/init"))
.create_symlink_to(cstr!("/system/bin/init"))
.log_ok();
self.patch_rw_root();
} else {
@@ -98,29 +98,29 @@ impl MagiskInit {
fn recovery(&self) {
info!("Ramdisk is recovery, abort");
self.restore_ramdisk_init();
path!("/.backup").remove_all().ok();
cstr!("/.backup").remove_all().ok();
}
fn restore_ramdisk_init(&self) {
path!("/init").remove().ok();
cstr!("/init").remove().ok();
let orig_init = FsPath::from(backup_init());
let orig_init = backup_init();
if orig_init.exists() {
orig_init.rename_to(path!("/init")).log_ok();
orig_init.rename_to(cstr!("/init")).log_ok();
} else {
// If the backup init is missing, this means that the boot ramdisk
// was created from scratch, and the real init is in a separate CPIO,
// which is guaranteed to be placed at /system/bin/init.
path!("/init")
.create_symlink_to(path!("/system/bin/init"))
cstr!("/init")
.create_symlink_to(cstr!("/system/bin/init"))
.log_ok();
}
}
fn start(&mut self) -> LoggedResult<()> {
if !path!("/proc/cmdline").exists() {
path!("/proc").mkdir(0o755)?;
if !cstr!("/proc/cmdline").exists() {
cstr!("/proc").mkdir(0o755)?;
unsafe {
mount(
raw_cstr!("proc"),
@@ -133,8 +133,8 @@ impl MagiskInit {
.check_io_err()?;
self.mount_list.push("/proc".to_string());
}
if !path!("/sys/block").exists() {
path!("/sys").mkdir(0o755)?;
if !cstr!("/sys/block").exists() {
cstr!("/sys").mkdir(0o755)?;
unsafe {
mount(
raw_cstr!("sysfs"),
@@ -159,7 +159,7 @@ impl MagiskInit {
self.legacy_system_as_root();
} else if self.config.force_normal_boot {
self.first_stage();
} else if path!("/sbin/recovery").exists() || path!("/system/bin/recovery").exists() {
} else if cstr!("/sbin/recovery").exists() || cstr!("/system/bin/recovery").exists() {
self.recovery();
} else if self.check_two_stage() {
self.first_stage();
-16
View File
@@ -3,7 +3,6 @@
#![feature(try_blocks)]
#![allow(clippy::missing_safety_doc)]
use base::FsPath;
use logging::setup_klog;
// Has to be pub so all symbols in that crate is included
pub use magiskpolicy;
@@ -106,18 +105,3 @@ pub mod ffi {
unsafe fn patch_fissiond(self: &mut MagiskInit, tmp_path: *const c_char);
}
}
#[inline(always)]
fn preload_lib() -> &'static FsPath {
FsPath::from(ffi::preload_lib())
}
#[inline(always)]
fn preload_policy() -> &'static FsPath {
FsPath::from(ffi::preload_policy())
}
#[inline(always)]
fn preload_ack() -> &'static FsPath {
FsPath::from(ffi::preload_ack())
}
+4 -4
View File
@@ -1,10 +1,10 @@
use base::{
LOGGER, LogLevel, Logger, Utf8CStr, cstr,
FsPath, LOGGER, LogLevel, Logger, Utf8CStr, cstr,
libc::{
O_CLOEXEC, O_RDWR, O_WRONLY, S_IFCHR, STDERR_FILENO, STDIN_FILENO, STDOUT_FILENO, SYS_dup3,
makedev, mknod, syscall,
},
open_fd, path, raw_cstr,
open_fd, raw_cstr,
};
use std::{
fs::File,
@@ -23,7 +23,7 @@ pub fn setup_klog() {
if fd.is_err() {
mknod(raw_cstr!("/null"), S_IFCHR | 0o666, makedev(1, 3));
fd = open_fd!(cstr!("/null"), O_RDWR | O_CLOEXEC);
path!("/null").remove().ok();
cstr!("/null").remove().ok();
}
if let Ok(ref fd) = fd {
syscall(SYS_dup3, fd, STDIN_FILENO, O_CLOEXEC);
@@ -36,7 +36,7 @@ pub fn setup_klog() {
if fd.is_err() {
mknod(raw_cstr!("/kmsg"), S_IFCHR | 0o666, makedev(1, 11));
fd = open_fd!(cstr!("/kmsg"), O_WRONLY | O_CLOEXEC);
path!("/kmsg").remove().ok();
cstr!("/kmsg").remove().ok();
}
KMSG = fd.map(|fd| fd.into_raw_fd()).unwrap_or(-1);
}
+11 -10
View File
@@ -1,9 +1,10 @@
use crate::ffi::MagiskInit;
use base::libc::{TMPFS_MAGIC, statfs};
use base::{
Directory, FsPath, FsPathBuf, LibcReturn, LoggedResult, ResultExt, Utf8CStr, cstr, debug, libc,
Directory, FsPath, FsPathBuf, FsPathMnt, LibcReturn, LoggedResult, ResultExt, Utf8CStr, cstr,
debug, libc,
libc::{chdir, chroot, execve, exit, mount},
parse_mount_info, path, raw_cstr,
parse_mount_info, raw_cstr,
};
use cxx::CxxString;
use std::ffi::c_long;
@@ -36,7 +37,7 @@ pub(crate) fn switch_root(path: &Utf8CStr) {
}
let mut target = info.target.clone();
let target = FsPath::from(Utf8CStr::from_string(&mut target));
let target = Utf8CStr::from_string(&mut target);
let new_path = FsPathBuf::default()
.join(path)
.join(info.target.trim_start_matches('/'));
@@ -46,7 +47,7 @@ pub(crate) fn switch_root(path: &Utf8CStr) {
}
unsafe {
chdir(path.as_ptr()).check_io_err()?;
FsPath::from(path).move_mount_to(path!("/"))?;
path.move_mount_to(cstr!("/"))?;
chroot(raw_cstr!("."));
}
@@ -79,7 +80,7 @@ pub(crate) fn is_rootfs() -> bool {
impl MagiskInit {
pub(crate) fn prepare_data(&self) {
debug!("Setup data tmp");
path!("/data").mkdir(0o755).log_ok();
cstr!("/data").mkdir(0o755).log_ok();
unsafe {
mount(
raw_cstr!("magisk"),
@@ -92,16 +93,16 @@ impl MagiskInit {
.check_io_err()
.log_ok();
path!("/init").copy_to(path!("/data/magiskinit")).log_ok();
path!("/.backup").copy_to(path!("/data/.backup")).log_ok();
path!("/overlay.d")
.copy_to(path!("/data/overlay.d"))
cstr!("/init").copy_to(cstr!("/data/magiskinit")).log_ok();
cstr!("/.backup").copy_to(cstr!("/data/.backup")).log_ok();
cstr!("/overlay.d")
.copy_to(cstr!("/data/overlay.d"))
.log_ok();
}
pub(crate) fn exec_init(&mut self) {
for path in self.mount_list.iter_mut().rev() {
let path = FsPath::from(Utf8CStr::from_string(path));
let path = Utf8CStr::from_string(path);
if path.unmount().log().is_ok() {
debug!("Unmount [{}]", path);
}
+5 -5
View File
@@ -2,8 +2,8 @@ use crate::consts::{ROOTMNT, ROOTOVL};
use crate::ffi::MagiskInit;
use base::libc::{O_CREAT, O_RDONLY, O_WRONLY};
use base::{
BufReadExt, Directory, FsPath, FsPathBuf, LoggedResult, ResultExt, Utf8CStr, Utf8CString,
clone_attr, cstr, cstr_buf, debug, path,
BufReadExt, Directory, FsPath, FsPathBuf, FsPathMnt, LoggedResult, ResultExt, Utf8CStr,
Utf8CString, clone_attr, cstr, cstr_buf, debug,
};
use std::io::BufReader;
use std::{
@@ -47,7 +47,7 @@ pub struct OverlayAttr(Utf8CString, Utf8CString);
impl MagiskInit {
pub(crate) fn parse_config_file(&mut self) {
if let Ok(fd) = path!("/data/.backup/.magisk").open(O_RDONLY) {
if let Ok(fd) = cstr!("/data/.backup/.magisk").open(O_RDONLY) {
let mut reader = BufReader::new(fd);
reader.foreach_props(|key, val| {
if key == "PREINITDEVICE" {
@@ -102,7 +102,7 @@ impl MagiskInit {
let mut mount_list = String::new();
self.mount_impl(cstr!(ROOTOVL), dest, &mut mount_list)
.log_ok();
if let Ok(mut fd) = path!(ROOTMNT).create(O_CREAT | O_WRONLY, 0) {
if let Ok(mut fd) = cstr!(ROOTMNT).create(O_CREAT | O_WRONLY, 0) {
fd.write(mount_list.as_bytes()).log_ok();
}
}
@@ -110,7 +110,7 @@ impl MagiskInit {
pub(crate) fn restore_overlay_contexts(&self) {
self.overlay_con.iter().for_each(|attr| {
let OverlayAttr(path, con) = attr;
FsPath::from(path).set_secontext(con).log_ok();
path.set_secontext(con).log_ok();
})
}
}
+20 -21
View File
@@ -1,10 +1,9 @@
use crate::consts::{PREINITMIRR, SELINUXMOCK};
use crate::ffi::{MagiskInit, split_plat_cil};
use crate::{preload_ack, preload_lib, preload_policy};
use crate::ffi::{MagiskInit, preload_ack, preload_lib, preload_policy, split_plat_cil};
use base::const_format::concatcp;
use base::{
BytesExt, FsPath, LibcReturn, LoggedResult, MappedFile, ResultExt, cstr, debug, error, info,
libc, path, raw_cstr,
BytesExt, FsPath, FsPathMnt, LibcReturn, LoggedResult, MappedFile, ResultExt, Utf8CStr, cstr,
debug, error, info, libc, raw_cstr,
};
use magiskpolicy::ffi::SePolicy;
use std::io::{Read, Write};
@@ -12,17 +11,17 @@ use std::ptr;
use std::thread::sleep;
use std::time::Duration;
const POLICY_VERSION: &FsPath = path!("/selinux_version");
const POLICY_VERSION: &Utf8CStr = cstr!("/selinux_version");
const MOCK_VERSION: &FsPath = path!(concatcp!(SELINUXMOCK, "/version"));
const MOCK_LOAD: &FsPath = path!(concatcp!(SELINUXMOCK, "/load"));
const MOCK_ENFORCE: &FsPath = path!(concatcp!(SELINUXMOCK, "/enforce"));
const MOCK_REQPROT: &FsPath = path!(concatcp!(SELINUXMOCK, "/checkreqprot"));
const MOCK_VERSION: &Utf8CStr = cstr!(concatcp!(SELINUXMOCK, "/version"));
const MOCK_LOAD: &Utf8CStr = cstr!(concatcp!(SELINUXMOCK, "/load"));
const MOCK_ENFORCE: &Utf8CStr = cstr!(concatcp!(SELINUXMOCK, "/enforce"));
const MOCK_REQPROT: &Utf8CStr = cstr!(concatcp!(SELINUXMOCK, "/checkreqprot"));
const SELINUX_MNT: &str = "/sys/fs/selinux";
const SELINUX_ENFORCE: &FsPath = path!(concatcp!(SELINUX_MNT, "/enforce"));
const SELINUX_LOAD: &FsPath = path!(concatcp!(SELINUX_MNT, "/load"));
const SELINUX_REQPROT: &FsPath = path!(concatcp!(SELINUX_MNT, "/checkreqprot"));
const SELINUX_ENFORCE: &Utf8CStr = cstr!(concatcp!(SELINUX_MNT, "/enforce"));
const SELINUX_LOAD: &Utf8CStr = cstr!(concatcp!(SELINUX_MNT, "/load"));
const SELINUX_REQPROT: &Utf8CStr = cstr!(concatcp!(SELINUX_MNT, "/checkreqprot"));
enum SePatchStrategy {
// 2SI, Android 10+
@@ -49,13 +48,13 @@ enum SePatchStrategy {
// node, and because both has been replaced with FIFO files, init will block until we
// handle it, effectively hijacking its control flow until the patched sepolicy is loaded.
fn mock_fifo(target: &FsPath, mock: &FsPath) -> LoggedResult<()> {
fn mock_fifo(target: &Utf8CStr, mock: &Utf8CStr) -> LoggedResult<()> {
debug!("Hijack [{}]", target);
mock.mkfifo(0o666)?;
mock.bind_mount_to(target).log()
}
fn mock_file(target: &FsPath, mock: &FsPath) -> LoggedResult<()> {
fn mock_file(target: &Utf8CStr, mock: &Utf8CStr) -> LoggedResult<()> {
debug!("Hijack [{}]", target);
drop(mock.create(libc::O_RDONLY, 0o666)?);
mock.bind_mount_to(target).log()
@@ -68,7 +67,7 @@ impl MagiskInit {
fn cleanup_and_load(&self, rules: &str) {
// Cleanup the hijacks
path!("/init").unmount().ok();
cstr!("/init").unmount().ok();
SELINUX_LOAD.unmount().log_ok();
SELINUX_ENFORCE.unmount().ok();
SELINUX_REQPROT.unmount().ok();
@@ -79,7 +78,7 @@ impl MagiskInit {
sepol.to_file(SELINUX_LOAD);
// For some reason, restorecon on /init won't work in some cases
path!("/init")
cstr!("/init")
.follow_link()
.set_secontext(cstr!("u:object_r:init_exec:s0"))
.ok();
@@ -89,10 +88,10 @@ impl MagiskInit {
}
fn handle_sepolicy_impl(&mut self) -> LoggedResult<()> {
path!(SELINUXMOCK).mkdir(0o711)?;
cstr!(SELINUXMOCK).mkdir(0o711)?;
let mut rules = String::new();
let rule_file = path!(concatcp!("/data/", PREINITMIRR, "/sepolicy.rule"));
let rule_file = cstr!(concatcp!("/data/", PREINITMIRR, "/sepolicy.rule"));
if rule_file.exists() {
debug!("Loading custom sepolicy patch: [{}]", rule_file);
rule_file.open(libc::O_RDONLY)?.read_to_string(&mut rules)?;
@@ -102,7 +101,7 @@ impl MagiskInit {
let strat: SePatchStrategy;
if path!("/system/bin/init").exists() {
if cstr!("/system/bin/init").exists() {
strat = SePatchStrategy::LdPreload;
} else {
let init = MappedFile::open(cstr!("/init"))?;
@@ -124,7 +123,7 @@ impl MagiskInit {
SePatchStrategy::LdPreload => {
info!("SePatchStrategy: LD_PRELOAD");
path!("init-ld").copy_to(preload_lib())?;
cstr!("init-ld").copy_to(preload_lib())?;
unsafe {
libc::setenv(raw_cstr!("LD_PRELOAD"), preload_lib().as_ptr(), 1);
}
@@ -137,7 +136,7 @@ impl MagiskInit {
// selinuxfs was not already mounted, mount it ourselves
// Remount procfs with proper options
path!("/proc").remount_with_data(cstr!("hidepid=2,gid=3009"))?;
cstr!("/proc").remount_with_data(cstr!("hidepid=2,gid=3009"))?;
// Preserve sysfs and procfs
self.mount_list.retain(|s| s != "/proc" && s != "/sys");
+14 -15
View File
@@ -1,8 +1,7 @@
use crate::ffi::MagiskInit;
use base::{
LoggedResult, MappedFile, MutBytesExt, ResultExt, cstr, debug, error,
FsPath, FsPathMnt, LoggedResult, MappedFile, MutBytesExt, ResultExt, cstr, debug, error,
libc::{O_CLOEXEC, O_CREAT, O_RDONLY, O_WRONLY},
path,
};
use std::io::Write;
@@ -29,8 +28,8 @@ pub(crate) fn hexpatch_init_for_second_stage(writable: bool) {
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 src = cstr!("/init");
let dest = cstr!("/data/init");
let _: LoggedResult<()> = try {
{
let mut fd = dest.create(O_CREAT | O_WRONLY, 0)?;
@@ -70,32 +69,32 @@ impl MagiskInit {
// /sdcard exists and fallback to using hexpatch.
if self.config.force_normal_boot {
path!("/first_stage_ramdisk/storage/self")
cstr!("/first_stage_ramdisk/storage/self")
.mkdirs(0o755)
.log_ok();
path!("/first_stage_ramdisk/storage/self/primary")
.create_symlink_to(path!("/system/system/bin/init"))
cstr!("/first_stage_ramdisk/storage/self/primary")
.create_symlink_to(cstr!("/system/system/bin/init"))
.log_ok();
debug!("Symlink /first_stage_ramdisk/storage/self/primary -> /system/system/bin/init");
path!("/first_stage_ramdisk/sdcard")
cstr!("/first_stage_ramdisk/sdcard")
.create(O_RDONLY | O_CREAT | O_CLOEXEC, 0)
.log_ok();
} else {
path!("/storage/self").mkdirs(0o755).log_ok();
path!("/storage/self/primary")
.create_symlink_to(path!("/system/system/bin/init"))
cstr!("/storage/self").mkdirs(0o755).log_ok();
cstr!("/storage/self/primary")
.create_symlink_to(cstr!("/system/system/bin/init"))
.log_ok();
debug!("Symlink /storage/self/primary -> /system/system/bin/init");
}
path!("/init").rename_to(path!("/sdcard")).log_ok();
cstr!("/init").rename_to(cstr!("/sdcard")).log_ok();
// First try to mount magiskinit from rootfs to workaround Samsung RKP
if path!("/sdcard").bind_mount_to(path!("/sdcard")).is_ok() {
if cstr!("/sdcard").bind_mount_to(cstr!("/sdcard")).is_ok() {
debug!("Bind mount /sdcard -> /sdcard");
} else {
// Binding mounting from rootfs is not supported before Linux 3.12
path!("/data/magiskinit")
.bind_mount_to(path!("/sdcard"))
cstr!("/data/magiskinit")
.bind_mount_to(cstr!("/sdcard"))
.log_ok();
debug!("Bind mount /data/magiskinit -> /sdcard");
}