diff --git a/native/src/Cargo.lock b/native/src/Cargo.lock index 8d15e957f..dd30f4f8f 100644 --- a/native/src/Cargo.lock +++ b/native/src/Cargo.lock @@ -694,6 +694,7 @@ dependencies = [ "cxx", "cxx-gen", "magiskpolicy", + "num-traits", ] [[package]] diff --git a/native/src/base/Cargo.toml b/native/src/base/Cargo.toml index 14223a3aa..63e6ff2d0 100644 --- a/native/src/base/Cargo.toml +++ b/native/src/base/Cargo.toml @@ -23,4 +23,4 @@ bytemuck = { workspace = true } num-traits = { workspace = true } num-derive = { workspace = true } const_format = { workspace = true } -nix = { workspace = true, features = ["fs"] } \ No newline at end of file +nix = { workspace = true, features = ["fs", "mount"] } diff --git a/native/src/base/cstr.rs b/native/src/base/cstr.rs index e208cb3f3..88471038b 100644 --- a/native/src/base/cstr.rs +++ b/native/src/base/cstr.rs @@ -335,6 +335,11 @@ impl Utf8CStr { unsafe { CStr::from_bytes_with_nul_unchecked(&self.0) } } + #[inline(always)] + pub fn as_utf8_cstr(&self) -> &Utf8CStr { + self + } + #[inline(always)] pub fn as_str(&self) -> &str { // SAFETY: Already UTF-8 validated during construction diff --git a/native/src/base/mount.rs b/native/src/base/mount.rs index b72f66110..4c0dc7818 100644 --- a/native/src/base/mount.rs +++ b/native/src/base/mount.rs @@ -1,91 +1,84 @@ use crate::{LibcReturn, OsResult, Utf8CStr}; -use libc::c_ulong; -use std::ptr; +use nix::mount::{MntFlags, MsFlags, mount, umount2}; impl Utf8CStr { pub fn bind_mount_to<'a>(&'a self, path: &'a Utf8CStr, rec: bool) -> OsResult<'a, ()> { - let flag = if rec { libc::MS_REC } else { 0 }; - unsafe { - libc::mount( - self.as_ptr(), - path.as_ptr(), - ptr::null(), - libc::MS_BIND | flag, - ptr::null(), - ) - .check_os_err("bind_mount", Some(self), Some(path)) - } + let flag = if rec { + MsFlags::MS_REC + } else { + MsFlags::empty() + }; + mount( + Some(self), + path, + None::<&Utf8CStr>, + flag | MsFlags::MS_BIND, + None::<&Utf8CStr>, + ) + .check_os_err("bind_mount", Some(self), Some(path)) } - pub fn remount_mount_point_flags(&self, flags: c_ulong) -> OsResult<'_, ()> { - unsafe { - libc::mount( - ptr::null(), - self.as_ptr(), - ptr::null(), - libc::MS_BIND | libc::MS_REMOUNT | flags, - ptr::null(), - ) - .check_os_err("remount", Some(self), None) - } + pub fn remount_mount_point_flags(&self, flags: MsFlags) -> OsResult<'_, ()> { + mount( + None::<&Utf8CStr>, + self, + None::<&Utf8CStr>, + MsFlags::MS_BIND | MsFlags::MS_REMOUNT | flags, + None::<&Utf8CStr>, + ) + .check_os_err("remount", Some(self), None) } - pub fn remount_mount_flags(&self, flags: c_ulong) -> OsResult<'_, ()> { - unsafe { - libc::mount( - ptr::null(), - self.as_ptr(), - ptr::null(), - libc::MS_REMOUNT | flags, - ptr::null(), - ) - .check_os_err("remount", Some(self), None) - } + pub fn remount_mount_flags(&self, flags: MsFlags) -> OsResult<'_, ()> { + mount( + None::<&Utf8CStr>, + self, + None::<&Utf8CStr>, + MsFlags::MS_REMOUNT | flags, + None::<&Utf8CStr>, + ) + .check_os_err("remount", Some(self), None) } pub fn remount_with_data(&self, data: &Utf8CStr) -> OsResult<'_, ()> { - unsafe { - libc::mount( - ptr::null(), - self.as_ptr(), - ptr::null(), - libc::MS_REMOUNT, - data.as_ptr().cast(), - ) - .check_os_err("remount", Some(self), None) - } + mount( + None::<&Utf8CStr>, + self, + None::<&Utf8CStr>, + MsFlags::MS_REMOUNT, + Some(data), + ) + .check_os_err("remount", Some(self), None) } pub fn move_mount_to<'a>(&'a self, path: &'a Utf8CStr) -> OsResult<'a, ()> { - unsafe { - libc::mount( - self.as_ptr(), - path.as_ptr(), - ptr::null(), - libc::MS_MOVE, - ptr::null(), - ) - .check_os_err("move_mount", Some(self), Some(path)) - } + mount( + Some(self), + path, + None::<&Utf8CStr>, + MsFlags::MS_MOVE, + None::<&Utf8CStr>, + ) + .check_os_err("move_mount", Some(self), Some(path)) } pub fn unmount(&self) -> OsResult<'_, ()> { - unsafe { - libc::umount2(self.as_ptr(), libc::MNT_DETACH).check_os_err("unmount", Some(self), None) - } + umount2(self, MntFlags::MNT_DETACH).check_os_err("unmount", Some(self), None) } - pub fn set_mount_private(&self, recursive: bool) -> OsResult<'_, ()> { - let flag = if recursive { libc::MS_REC } else { 0 }; - unsafe { - libc::mount( - ptr::null(), - self.as_ptr(), - ptr::null(), - libc::MS_PRIVATE | flag, - ptr::null(), - ) - .check_os_err("set_mount_private", Some(self), None) - } + pub fn set_mount_private(&self, rec: bool) -> OsResult<'_, ()> { + let flag = if rec { + MsFlags::MS_REC + } else { + MsFlags::empty() + }; + mount( + None::<&Utf8CStr>, + self, + None::<&Utf8CStr>, + flag | MsFlags::MS_PRIVATE, + None::<&Utf8CStr>, + ) + .check_os_err("set_mount_private", Some(self), None) } } diff --git a/native/src/core/Cargo.toml b/native/src/core/Cargo.toml index 62cfb8bf9..a260ea077 100644 --- a/native/src/core/Cargo.toml +++ b/native/src/core/Cargo.toml @@ -26,4 +26,4 @@ bytemuck = { workspace = true, features = ["derive"] } thiserror = { workspace = true } bit-set = { workspace = true } argh = { workspace = true } -nix = { workspace = true, features = ["fs", "poll", "signal", "term", "zerocopy"] } +nix = { workspace = true, features = ["fs", "mount", "poll", "signal", "term", "zerocopy"] } diff --git a/native/src/core/daemon.rs b/native/src/core/daemon.rs index a4379269b..3f6d83db3 100644 --- a/native/src/core/daemon.rs +++ b/native/src/core/daemon.rs @@ -23,6 +23,7 @@ use base::{ cstr, error, info, libc, }; use nix::fcntl::OFlag; +use nix::mount::MsFlags; use std::fmt::Write as FmtWrite; use std::fs::File; use std::io::{BufReader, Write}; @@ -384,7 +385,7 @@ pub fn daemon_entry() { // Remount rootfs as read-only if requested if std::env::var_os("REMOUNT_ROOT").is_some() { - cstr!("/").remount_mount_flags(libc::MS_RDONLY).log_ok(); + cstr!("/").remount_mount_flags(MsFlags::MS_RDONLY).log_ok(); unsafe { std::env::remove_var("REMOUNT_ROOT") }; } diff --git a/native/src/core/module.rs b/native/src/core/module.rs index ad8126356..8b2e43425 100644 --- a/native/src/core/module.rs +++ b/native/src/core/module.rs @@ -8,8 +8,7 @@ use base::{ Utf8CStrBuf, Utf8CString, WalkResult, clone_attr, cstr, debug, error, info, libc, raw_cstr, warn, }; -use libc::MS_RDONLY; -use nix::{fcntl::OFlag, unistd::UnlinkatFlags}; +use nix::{fcntl::OFlag, mount::MsFlags, unistd::UnlinkatFlags}; use std::collections::BTreeMap; use std::os::fd::IntoRawFd; use std::path::{Component, Path}; @@ -40,7 +39,7 @@ fn bind_mount(reason: &str, src: &Utf8CStr, dest: &Utf8CStr, rec: bool) { // Ignore any kind of error here. If a single bind mount fails due to selinux permissions or // kernel limitations, don't let it break module mount entirely. src.bind_mount_to(dest, rec).log_ok(); - dest.remount_mount_point_flags(MS_RDONLY).log_ok(); + dest.remount_mount_point_flags(MsFlags::MS_RDONLY).log_ok(); } fn mount_dummy<'a>( diff --git a/native/src/core/mount.rs b/native/src/core/mount.rs index e26cdfc44..163c8457b 100644 --- a/native/src/core/mount.rs +++ b/native/src/core/mount.rs @@ -1,19 +1,17 @@ -use std::{ - cmp::Ordering::{Greater, Less}, - path::{Path, PathBuf}, -}; - -use num_traits::AsPrimitive; - -use base::libc::{c_uint, dev_t}; +use crate::consts::{MODULEMNT, MODULEROOT, PREINITDEV, PREINITMIRR, WORKERDIR}; +use crate::ffi::{get_magisk_tmp, resolve_preinit_dir, switch_mnt_ns}; +use crate::resetprop::get_prop; use base::{ FsPathBuilder, LibcReturn, LoggedResult, MountInfo, ResultExt, Utf8CStr, Utf8CStrBuf, cstr, debug, info, libc, parse_mount_info, warn, }; - -use crate::consts::{MODULEMNT, MODULEROOT, PREINITDEV, PREINITMIRR, WORKERDIR}; -use crate::ffi::{get_magisk_tmp, resolve_preinit_dir, switch_mnt_ns}; -use crate::resetprop::get_prop; +use libc::{c_uint, dev_t}; +use nix::{ + mount::MsFlags, + sys::stat::{Mode, SFlag, mknod}, +}; +use num_traits::AsPrimitive; +use std::{cmp::Ordering::Greater, cmp::Ordering::Less, path::Path, path::PathBuf}; pub fn setup_preinit_dir() { let magisk_tmp = get_magisk_tmp(); @@ -69,7 +67,7 @@ pub fn setup_module_mount() { let _: LoggedResult<()> = try { module_mnt.mkdir(0o755)?; cstr!(MODULEROOT).bind_mount_to(&module_mnt, false)?; - module_mnt.remount_mount_point_flags(libc::MS_RDONLY)?; + module_mnt.remount_mount_point_flags(MsFlags::MS_RDONLY)?; }; } @@ -194,15 +192,14 @@ pub fn find_preinit_device() -> String { if std::env::var_os("MAKEDEV").is_some() { buf.clear(); let dev_path = buf.append_path(&tmp).append_path(PREINITDEV); - unsafe { - libc::mknod( - dev_path.as_ptr(), - libc::S_IFBLK | 0o600, - info.device as dev_t, - ) - .check_os_err("mknod", Some(dev_path), None) - .log_ok(); - } + mknod( + dev_path.as_utf8_cstr(), + SFlag::S_IFBLK, + Mode::from_bits_truncate(0o600), + info.device as dev_t, + ) + .check_os_err("mknod", Some(dev_path), None) + .log_ok(); } } Path::new(&info.source) @@ -248,10 +245,8 @@ pub fn revert_unmount(pid: i32) { for mut target in targets { let target = Utf8CStr::from_string(&mut target); - unsafe { - if libc::umount2(target.as_ptr(), libc::MNT_DETACH) == 0 { - debug!("denylist: Unmounted ({})", target); - } + if target.unmount().is_ok() { + debug!("denylist: Unmounted ({})", target); } } } diff --git a/native/src/external/crt0 b/native/src/external/crt0 index f7f5d092b..9dfa67b4d 160000 --- a/native/src/external/crt0 +++ b/native/src/external/crt0 @@ -1 +1 @@ -Subproject commit f7f5d092b28e8ba8ae073f2be72cc6cb96c52843 +Subproject commit 9dfa67b4d543f1b6bf2e936f560fbe77ca2a226a diff --git a/native/src/init/Cargo.toml b/native/src/init/Cargo.toml index 7f41e9415..2cb8023b4 100644 --- a/native/src/init/Cargo.toml +++ b/native/src/init/Cargo.toml @@ -14,3 +14,4 @@ cxx-gen = { workspace = true } base = { path = "../base" } magiskpolicy = { path = "../sepolicy", default-features = false } cxx = { workspace = true } +num-traits = { workspace = true } diff --git a/native/src/init/mount.rs b/native/src/init/mount.rs index 39ecf5087..789fb7a20 100644 --- a/native/src/init/mount.rs +++ b/native/src/init/mount.rs @@ -1,12 +1,15 @@ use crate::ffi::MagiskInit; -use base::libc::{TMPFS_MAGIC, statfs}; use base::{ Directory, FsPathBuilder, LibcReturn, LoggedResult, ResultExt, Utf8CStr, cstr, debug, libc, - libc::{chdir, chroot, execve, exit, mount}, - parse_mount_info, raw_cstr, + nix, parse_mount_info, raw_cstr, }; use cxx::CxxString; -use std::ffi::c_long; +use nix::{ + mount::MsFlags, + sys::statfs::{FsType, TMPFS_MAGIC, statfs}, + unistd::{chdir, chroot}, +}; +use num_traits::AsPrimitive; use std::{ collections::BTreeSet, ops::Bound::{Excluded, Unbounded}, @@ -43,11 +46,9 @@ pub(crate) fn switch_root(path: &Utf8CStr) { target.move_mount_to(&new_path)?; mounts.insert(info.target); } - unsafe { - chdir(path.as_ptr()).check_err()?; - path.move_mount_to(cstr!("/"))?; - chroot(raw_cstr!(".")); - } + chdir(path)?; + path.move_mount_to(cstr!("/"))?; + chroot(cstr!("."))?; debug!("Cleaning rootfs"); rootfs.remove_all()?; @@ -65,13 +66,13 @@ pub(crate) fn is_device_mounted(dev: u64, target: Pin<&mut CxxString>) -> bool { false } -const RAMFS_MAGIC: u64 = 0x858458f6; +const RAMFS_MAGIC: u32 = 0x858458f6; pub(crate) fn is_rootfs() -> bool { - unsafe { - let mut sfs: statfs = std::mem::zeroed(); - statfs(raw_cstr!("/"), &mut sfs); - sfs.f_type as u64 == RAMFS_MAGIC || sfs.f_type as c_long == TMPFS_MAGIC + if let Ok(s) = statfs(cstr!("/")) { + s.filesystem_type() == FsType(RAMFS_MAGIC.as_()) || s.filesystem_type() == TMPFS_MAGIC + } else { + false } } @@ -79,23 +80,19 @@ impl MagiskInit { pub(crate) fn prepare_data(&self) { debug!("Setup data tmp"); cstr!("/data").mkdir(0o755).log_ok(); - unsafe { - mount( - raw_cstr!("magisk"), - raw_cstr!("/data"), - raw_cstr!("tmpfs"), - 0, - raw_cstr!("mode=755").cast(), - ) - } - .check_err() + nix::mount::mount( + Some(cstr!("magisk")), + cstr!("/data"), + Some(cstr!("tmpfs")), + MsFlags::empty(), + Some(cstr!("mode=755")), + ) + .check_os_err("mount", Some("/data"), Some("tmpfs")) .log_ok(); - 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(); + cstr!("/init").copy_to(cstr!("/data/magiskinit")).ok(); + cstr!("/.backup").copy_to(cstr!("/data/.backup")).ok(); + cstr!("/overlay.d").copy_to(cstr!("/data/overlay.d")).ok(); } pub(crate) fn exec_init(&mut self) { @@ -106,10 +103,10 @@ impl MagiskInit { } } unsafe { - execve(raw_cstr!("/init"), self.argv.cast(), environ.cast()) + libc::execve(raw_cstr!("/init"), self.argv.cast(), environ.cast()) .check_err() .log_ok(); - exit(1); } + std::process::exit(1); } }