diff --git a/native/src/base/cstr.rs b/native/src/base/cstr.rs index 5d46d4926..5a3dd7bb1 100644 --- a/native/src/base/cstr.rs +++ b/native/src/base/cstr.rs @@ -704,26 +704,27 @@ impl_str_buf_with_slice!( (Utf8CStrBufArr, const N: usize) ); -// The cstr! macro is copied from https://github.com/bytecodealliance/rustix/blob/main/src/cstr.rs - #[macro_export] macro_rules! cstr { - ($($str:tt)*) => {{ - assert!( - !($($str)*).bytes().any(|b| b == b'\0'), - "cstr argument contains embedded NUL bytes", - ); + ($str:expr) => {{ + const NULL_STR: &str = $crate::const_format::concatcp!($str, "\0"); #[allow(unused_unsafe)] unsafe { - $crate::Utf8CStr::from_bytes_unchecked($crate::const_format::concatcp!($($str)*, "\0") - .as_bytes()) + $crate::Utf8CStr::from_bytes_unchecked(NULL_STR.as_bytes()) } }}; } #[macro_export] macro_rules! raw_cstr { - ($($str:tt)*) => {{ - $crate::cstr!($($str)*).as_ptr() + ($str:expr) => {{ + $crate::cstr!($str).as_ptr() + }}; +} + +#[macro_export] +macro_rules! path { + ($str:expr) => {{ + $crate::FsPath::from($crate::cstr!($str)) }}; } diff --git a/native/src/base/files.rs b/native/src/base/files.rs index 2b767d3b2..8554aa8a5 100644 --- a/native/src/base/files.rs +++ b/native/src/base/files.rs @@ -616,6 +616,7 @@ impl FsPath { self.remove() } + #[allow(clippy::unnecessary_cast)] pub fn read_link(&self, buf: &mut dyn Utf8CStrBuf) -> io::Result<()> { buf.clear(); unsafe { diff --git a/native/src/core/daemon.rs b/native/src/core/daemon.rs index 21eb36ffb..efce984f7 100644 --- a/native/src/core/daemon.rs +++ b/native/src/core/daemon.rs @@ -11,7 +11,7 @@ use crate::package::ManagerInfo; use crate::su::SuInfo; use base::libc::{O_CLOEXEC, O_RDONLY}; use base::{ - cstr, error, info, libc, open_fd, AtomicArc, BufReadExt, FsPath, FsPathBuf, ResultExt, Utf8CStr, + cstr, error, info, libc, open_fd, path, AtomicArc, BufReadExt, FsPathBuf, ResultExt, Utf8CStr, }; use std::fs::File; use std::io::BufReader; @@ -105,7 +105,7 @@ impl MagiskD { self.preserve_stub_apk(); // Check secure dir - let secure_dir = FsPath::from(cstr!(SECURE_DIR)); + let secure_dir = path!(SECURE_DIR); if !secure_dir.exists() { if self.sdk_int < 24 { secure_dir.mkdir(0o700).log_ok(); @@ -172,7 +172,7 @@ impl MagiskD { self.set_db_setting(DbEntryKey::BootloopCount, 0).log_ok(); // At this point it's safe to create the folder - let secure_dir = FsPath::from(cstr!(SECURE_DIR)); + let secure_dir = path!(SECURE_DIR); if !secure_dir.exists() { secure_dir.mkdir(0o700).log_ok(); } @@ -244,7 +244,7 @@ pub fn daemon_entry() { } let mut sdk_int = -1; - if let Ok(file) = FsPath::from(cstr!("/system/build.prop")).open(O_RDONLY | O_CLOEXEC) { + if let Ok(file) = path!("/system/build.prop").open(O_RDONLY | O_CLOEXEC) { let mut file = BufReader::new(file); file.foreach_props(|key, val| { if key == "ro.build.version.sdk" { diff --git a/native/src/core/resetprop/persist.rs b/native/src/core/resetprop/persist.rs index e246583d4..fc3aad034 100644 --- a/native/src/core/resetprop/persist.rs +++ b/native/src/core/resetprop/persist.rs @@ -9,28 +9,19 @@ use std::{ use quick_protobuf::{BytesReader, MessageRead, MessageWrite, Writer}; -use base::libc::{O_CLOEXEC, O_RDONLY}; -use base::{ - clone_attr, cstr, debug, libc::mkstemp, Directory, FsPath, FsPathBuf, LibcReturn, LoggedResult, - MappedFile, SilentResultExt, Utf8CStr, WalkResult, -}; - use crate::ffi::{prop_cb_exec, PropCb}; use crate::resetprop::proto::persistent_properties::{ mod_PersistentProperties::PersistentPropertyRecord, PersistentProperties, }; +use base::const_format::concatcp; +use base::libc::{O_CLOEXEC, O_RDONLY}; +use base::{ + clone_attr, cstr, debug, libc::mkstemp, path, Directory, FsPathBuf, LibcReturn, LoggedResult, + MappedFile, SilentResultExt, Utf8CStr, WalkResult, +}; -macro_rules! PERSIST_PROP_DIR { - () => { - "/data/property" - }; -} - -macro_rules! PERSIST_PROP { - () => { - concat!(PERSIST_PROP_DIR!(), "/persistent_properties") - }; -} +const PERSIST_PROP_DIR: &str = "/data/property"; +const PERSIST_PROP: &str = concatcp!(PERSIST_PROP_DIR, "/persistent_properties"); trait PropCbExec { fn exec(&mut self, name: &Utf8CStr, value: &Utf8CStr); @@ -73,11 +64,11 @@ impl PropExt for PersistentProperties { } fn check_proto() -> bool { - FsPath::from(cstr!(PERSIST_PROP!())).exists() + path!(PERSIST_PROP).exists() } fn file_get_prop(name: &Utf8CStr) -> LoggedResult { - let path = FsPathBuf::default().join(PERSIST_PROP_DIR!()).join(name); + let path = FsPathBuf::default().join(PERSIST_PROP_DIR).join(name); let mut file = path.open(O_RDONLY | O_CLOEXEC).silent()?; debug!("resetprop: read prop from [{}]", path); let mut s = String::new(); @@ -86,10 +77,10 @@ fn file_get_prop(name: &Utf8CStr) -> LoggedResult { } fn file_set_prop(name: &Utf8CStr, value: Option<&Utf8CStr>) -> LoggedResult<()> { - let path = FsPathBuf::default().join(PERSIST_PROP_DIR!()).join(name); + let path = FsPathBuf::default().join(PERSIST_PROP_DIR).join(name); if let Some(value) = value { let mut tmp = FsPathBuf::default() - .join(PERSIST_PROP_DIR!()) + .join(PERSIST_PROP_DIR) .join("prop.XXXXXX"); { let mut f = unsafe { @@ -108,8 +99,8 @@ fn file_set_prop(name: &Utf8CStr, value: Option<&Utf8CStr>) -> LoggedResult<()> } fn proto_read_props() -> LoggedResult { - debug!("resetprop: decode with protobuf [{}]", PERSIST_PROP!()); - let m = MappedFile::open(cstr!(PERSIST_PROP!()))?; + debug!("resetprop: decode with protobuf [{}]", PERSIST_PROP); + let m = MappedFile::open(cstr!(PERSIST_PROP))?; let m = m.as_ref(); let mut r = BytesReader::from_bytes(m); let mut props = PersistentProperties::from_reader(&mut r, m)?; @@ -119,7 +110,7 @@ fn proto_read_props() -> LoggedResult { } fn proto_write_props(props: &PersistentProperties) -> LoggedResult<()> { - let mut tmp = FsPathBuf::default().join(concat!(PERSIST_PROP!(), ".XXXXXX")); + let mut tmp = FsPathBuf::default().join(concatcp!(PERSIST_PROP, ".XXXXXX")); { let f = unsafe { let fd = mkstemp(tmp.as_mut_ptr()).check_os_err()?; @@ -128,8 +119,8 @@ fn proto_write_props(props: &PersistentProperties) -> LoggedResult<()> { debug!("resetprop: encode with protobuf [{}]", tmp); props.write_message(&mut Writer::new(BufWriter::new(f)))?; } - clone_attr(FsPath::from(cstr!(PERSIST_PROP!())), &tmp)?; - tmp.rename_to(cstr!(PERSIST_PROP!()))?; + clone_attr(path!(PERSIST_PROP), &tmp)?; + tmp.rename_to(cstr!(PERSIST_PROP))?; Ok(()) } @@ -168,7 +159,7 @@ pub fn persist_get_props(mut prop_cb: Pin<&mut PropCb>) { } }); } else { - let mut dir = Directory::open(cstr!(PERSIST_PROP_DIR!()))?; + let mut dir = Directory::open(cstr!(PERSIST_PROP_DIR))?; dir.pre_order_walk(|e| { if e.is_file() { if let Ok(name) = Utf8CStr::from_cstr(e.d_name()) { diff --git a/native/src/init/getinfo.rs b/native/src/init/getinfo.rs index 00f7ec589..a19c73c7b 100644 --- a/native/src/init/getinfo.rs +++ b/native/src/init/getinfo.rs @@ -1,5 +1,5 @@ use crate::ffi::{backup_init, BootConfig, MagiskInit}; -use base::{cstr, debug, BytesExt, FsPath, MappedFile}; +use base::{debug, path, BytesExt, MappedFile}; use std::ffi::CStr; impl BootConfig { @@ -27,11 +27,11 @@ impl BootConfig { impl MagiskInit { pub(crate) fn check_two_stage(&self) -> bool { - FsPath::from(cstr!("/first_stage_ramdisk")).exists() || - FsPath::from(cstr!("/second_stage_resources")).exists() || - FsPath::from(cstr!("/system/bin/init")).exists() || + path!("/first_stage_ramdisk").exists() || + path!("/second_stage_resources").exists() || + path!("/system/bin/init").exists() || // Use the apex folder to determine whether 2SI (Android 10+) - FsPath::from(cstr!("/apex")).exists() || + path!("/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")) diff --git a/native/src/init/init.rs b/native/src/init/init.rs index 75671bb65..accd868ac 100644 --- a/native/src/init/init.rs +++ b/native/src/init/init.rs @@ -4,9 +4,9 @@ use crate::{ logging::setup_klog, }; use base::{ - cstr, debug, info, + debug, info, libc::{basename, getpid, mount, umask}, - raw_cstr, FsPath, LibcReturn, LoggedResult, ResultExt, + path, raw_cstr, FsPath, LibcReturn, LoggedResult, ResultExt, }; use std::{ ffi::{c_char, CStr}, @@ -48,40 +48,36 @@ impl MagiskInit { info!("RootFS Init"); self.prepare_data(); debug!("Restoring /init\n"); - FsPath::from(cstr!("/.backup/init")) - .rename_to(FsPath::from(cstr!("/init"))) - .log() - .ok(); + path!("/.backup/init").rename_to(path!("/init")).log_ok(); self.patch_rw_root(); } pub(crate) fn recovery(&self) { info!("Ramdisk is recovery, abort"); self.restore_ramdisk_init(); - FsPath::from(cstr!("/.backup")).remove_all().ok(); + path!("/.backup").remove_all().ok(); } pub(crate) fn restore_ramdisk_init(&self) { - FsPath::from(cstr!("/init")).remove().ok(); + path!("/init").remove().ok(); let orig_init = FsPath::from(backup_init()); if orig_init.exists() { - orig_init.rename_to(FsPath::from(cstr!("/init"))).log_ok(); + orig_init.rename_to(path!("/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. - FsPath::from(cstr!("/system/bin/init")) - .symlink_to(FsPath::from(cstr!("/init"))) - .log() - .ok(); + path!("/system/bin/init") + .symlink_to(path!("/init")) + .log_ok(); } } fn start(&mut self) -> LoggedResult<()> { - if !FsPath::from(cstr!("/proc/cmdline")).exists() { - FsPath::from(cstr!("/proc")).mkdir(0o755)?; + if !path!("/proc/cmdline").exists() { + path!("/proc").mkdir(0o755)?; unsafe { mount( raw_cstr!("proc"), @@ -94,8 +90,8 @@ impl MagiskInit { .as_os_err()?; self.mount_list.push("/proc".to_string()); } - if !FsPath::from(cstr!("/sys/block")).exists() { - FsPath::from(cstr!("/sys")).mkdir(0o755)?; + if !path!("/sys/block").exists() { + path!("/sys").mkdir(0o755)?; unsafe { mount( raw_cstr!("sysfs"), @@ -120,9 +116,7 @@ impl MagiskInit { self.legacy_system_as_root(); } else if self.config.force_normal_boot { self.first_stage(); - } else if FsPath::from(cstr!("/sbin/recovery")).exists() - || FsPath::from(cstr!("/system/bin/recovery")).exists() - { + } else if path!("/sbin/recovery").exists() || path!("/system/bin/recovery").exists() { self.recovery(); } else if self.check_two_stage() { self.first_stage(); diff --git a/native/src/init/logging.rs b/native/src/init/logging.rs index 613aeecea..1dc8135ee 100644 --- a/native/src/init/logging.rs +++ b/native/src/init/logging.rs @@ -4,7 +4,7 @@ use base::{ makedev, mknod, syscall, SYS_dup3, O_CLOEXEC, O_RDWR, O_WRONLY, STDERR_FILENO, STDIN_FILENO, STDOUT_FILENO, S_IFCHR, }, - open_fd, raw_cstr, FsPath, LogLevel, Logger, Utf8CStr, LOGGER, + open_fd, path, raw_cstr, LogLevel, Logger, Utf8CStr, LOGGER, }; 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); - FsPath::from(cstr!("/null")).remove().ok(); + path!("/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); - FsPath::from(cstr!("/kmsg")).remove().ok(); + path!("/kmsg").remove().ok(); } KMSG = fd.map(|fd| fd.into_raw_fd()).unwrap_or(-1); } diff --git a/native/src/init/mount.rs b/native/src/init/mount.rs index 8ab56f159..634390e2d 100644 --- a/native/src/init/mount.rs +++ b/native/src/init/mount.rs @@ -2,7 +2,7 @@ use crate::ffi::MagiskInit; use base::{ cstr, debug, libc, libc::{chdir, chroot, execve, exit, mount, umount2, MNT_DETACH, MS_MOVE}, - parse_mount_info, raw_cstr, Directory, FsPath, LibcReturn, LoggedResult, ResultExt, StringExt, + parse_mount_info, path, raw_cstr, Directory, LibcReturn, LoggedResult, ResultExt, StringExt, Utf8CStr, }; use cxx::CxxString; @@ -76,7 +76,7 @@ pub fn is_device_mounted(dev: u64, target: Pin<&mut CxxString>) -> bool { impl MagiskInit { pub(crate) fn prepare_data(&self) { debug!("Setup data tmp"); - FsPath::from(cstr!("/data")).mkdir(0o755).log_ok(); + path!("/data").mkdir(0o755).log_ok(); unsafe { mount( raw_cstr!("magisk"), @@ -85,11 +85,15 @@ impl MagiskInit { 0, raw_cstr!("mode=755").cast(), ) - }.as_os_err().log_ok(); + } + .as_os_err() + .log_ok(); - FsPath::from(cstr!("/init")).copy_to(FsPath::from(cstr!("/data/magiskinit"))).log_ok(); - FsPath::from(cstr!("/.backup")).copy_to(FsPath::from(cstr!("/data/.backup"))).log_ok(); - FsPath::from(cstr!("/overlay.d")).copy_to(FsPath::from(cstr!("/data/overlay.d"))).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")) + .log_ok(); } pub(crate) fn exec_init(&self) { diff --git a/native/src/init/rootdir.rs b/native/src/init/rootdir.rs index 9b3b817a8..aab315f85 100644 --- a/native/src/init/rootdir.rs +++ b/native/src/init/rootdir.rs @@ -1,8 +1,8 @@ use crate::ffi::MagiskInit; use base::libc::O_RDONLY; use base::{ - cstr, debug, libc, BufReadExt, Directory, FsPath, LibcReturn, LoggedResult, ResultExt, - Utf8CStr, Utf8CStrBuf, Utf8CStrBufArr, WalkResult, + debug, libc, path, BufReadExt, Directory, LibcReturn, LoggedResult, ResultExt, Utf8CStr, + Utf8CStrBuf, Utf8CStrBufArr, WalkResult, }; use std::io::BufReader; use std::{ @@ -116,7 +116,7 @@ on property:init.svc.zygote=stopped impl MagiskInit { pub(crate) fn parse_config_file(&mut self) { - if let Ok(fd) = FsPath::from(cstr!("/data/.backup/.magisk")).open(O_RDONLY) { + if let Ok(fd) = path!("/data/.backup/.magisk").open(O_RDONLY) { let mut reader = BufReader::new(fd); reader.foreach_props(|key, val| { if key == "PREINITDEVICE" { diff --git a/native/src/init/selinux.rs b/native/src/init/selinux.rs index b94fd0b23..0400a1e18 100644 --- a/native/src/init/selinux.rs +++ b/native/src/init/selinux.rs @@ -1,5 +1,5 @@ use crate::ffi::MagiskInit; -use base::{cstr, debug, FsPath, Utf8CStr}; +use base::{debug, path, Utf8CStr}; use magiskpolicy::ffi::SePolicy; impl MagiskInit { @@ -10,7 +10,7 @@ impl MagiskInit { sepol.magisk_rules(); // Custom rules - let rule = FsPath::from(cstr!("/data/.magisk/preinit/sepolicy.rule")); + let rule = path!("/data/.magisk/preinit/sepolicy.rule"); if rule.exists() { debug!("Loading custom sepolicy patch: [{}]", rule); sepol.load_rule_file(rule); @@ -20,10 +20,10 @@ impl MagiskInit { sepol.to_file(out); // Remove OnePlus stupid debug sepolicy and use our own - let sepol_debug = FsPath::from(cstr!("/sepolicy_debug")); + let sepol_debug = path!("/sepolicy_debug"); if sepol_debug.exists() { sepol_debug.remove().ok(); - FsPath::from(cstr!("/sepolicy")).link_to(sepol_debug).ok(); + path!("/sepolicy").link_to(sepol_debug).ok(); } } } diff --git a/native/src/init/twostage.rs b/native/src/init/twostage.rs index 7643db361..f34a9edf5 100644 --- a/native/src/init/twostage.rs +++ b/native/src/init/twostage.rs @@ -5,7 +5,7 @@ use base::{ fstatat, mount, stat, statfs, umount2, AT_SYMLINK_NOFOLLOW, MNT_DETACH, MS_BIND, O_CLOEXEC, O_CREAT, O_RDONLY, O_WRONLY, TMPFS_MAGIC, }, - raw_cstr, FsPath, LibcReturn, MappedFile, MutBytesExt, ResultExt, + path, raw_cstr, LibcReturn, MappedFile, MutBytesExt, ResultExt, }; use std::{ffi::c_long, io::Write, ptr::null}; @@ -25,38 +25,26 @@ impl MagiskInit { ) != 0 } { if self.config.force_normal_boot { - FsPath::from(cstr!("/first_stage_ramdisk/storage/self")) + path!("/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(); + .log_ok(); + path!("/system/system/bin/init") + .symlink_to(path!("/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")) + path!("/first_stage_ramdisk/sdcard") .create(O_RDONLY | O_CREAT | O_CLOEXEC, 0) - .log() - .ok(); + .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(); + path!("/storage/self").mkdirs(0o755).log_ok(); + path!("/system/system/bin/init") + .symlink_to(path!("/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(); + path!("/init").rename_to(path!("/sdcard")).log_ok(); // Try to keep magiskinit in rootfs for samsung RKP if unsafe { mount( @@ -103,8 +91,8 @@ impl MagiskInit { } pub(crate) fn redirect_second_stage(&self) { - let src = FsPath::from(cstr!("/init")); - let dest = FsPath::from(cstr!("/data/init")); + let src = path!("/init"); + let dest = path!("/data/init"); // Patch init binary if let Ok(mut map) = MappedFile::open(src) { let from = "/system/bin/init"; @@ -136,7 +124,7 @@ impl MagiskInit { 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(); + path!("/data/init").remove().ok(); // Make sure init dmesg logs won't get messed up *self.argv = raw_cstr!("/system/bin/init") as *mut _; @@ -146,12 +134,9 @@ impl MagiskInit { statfs(raw_cstr!("/"), &mut sfs); 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")); + let init_path = path!("/init"); init_path.remove().ok(); - FsPath::from(cstr!("/system/bin/init")) - .symlink_to(init_path) - .log() - .ok(); + path!("/system/bin/init").symlink_to(init_path).log_ok(); self.patch_rw_root(); } else { self.patch_ro_root();