diff --git a/native/src/Cargo.lock b/native/src/Cargo.lock index 3d935bce9..ebf6ba778 100644 --- a/native/src/Cargo.lock +++ b/native/src/Cargo.lock @@ -98,12 +98,6 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" -[[package]] -name = "bitflags" -version = "2.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" - [[package]] name = "block-buffer" version = "0.10.4" @@ -159,7 +153,7 @@ checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" dependencies = [ "ansi_term", "atty", - "bitflags 1.3.2", + "bitflags", "strsim", "textwrap", "unicode-width", @@ -329,16 +323,6 @@ dependencies = [ "termcolor", ] -[[package]] -name = "errno" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" -dependencies = [ - "libc", - "windows-sys", -] - [[package]] name = "fdt" version = "0.1.5" @@ -403,12 +387,6 @@ dependencies = [ "libc", ] -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - [[package]] name = "hkdf" version = "0.12.4" @@ -457,12 +435,6 @@ version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" -[[package]] -name = "linux-raw-sys" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" - [[package]] name = "log" version = "0.4.20" @@ -516,7 +488,6 @@ dependencies = [ "cxx", "cxx-gen", "magiskpolicy", - "procfs", ] [[package]] @@ -697,29 +668,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "procfs" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "731e0d9356b0c25f16f33b5be79b1c57b562f141ebfcdb0ad8ac2c13a24293b4" -dependencies = [ - "bitflags 2.4.2", - "hex", - "lazy_static", - "procfs-core", - "rustix", -] - -[[package]] -name = "procfs-core" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d3554923a69f4ce04c4a754260c338f505ce22642d3830e049a399fc2059a29" -dependencies = [ - "bitflags 2.4.2", - "hex", -] - [[package]] name = "quick-error" version = "1.2.3" @@ -832,19 +780,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "rustix" -version = "0.38.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" -dependencies = [ - "bitflags 2.4.2", - "errno", - "libc", - "linux-raw-sys", - "windows-sys", -] - [[package]] name = "sec1" version = "0.7.3" @@ -1088,72 +1023,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.52.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d380ba1dc7187569a8a9e91ed34b8ccfc33123bbacb8c0aed2d1ad7f3ef2dc5f" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68e5dcfb9413f53afd9c8f86e56a7b4d86d9a2fa26090ea2dc9e40fba56c6ec6" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8dab469ebbc45798319e69eebf92308e541ce46760b49b18c6b3fe5e8965b30f" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a4e9b6a7cac734a8b4138a4e1044eac3404d8326b6c0f939276560687a033fb" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28b0ec9c422ca95ff34a78755cfa6ad4a51371da2a5ace67500cf7ca5f232c58" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "704131571ba93e89d7cd43482277d6632589b18ecf4468f591fbae0a8b101614" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42079295511643151e98d61c38c0acc444e52dd42ab456f7ccfd5152e8ecf21c" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0770833d60a970638e989b3fa9fd2bb1aaadcf88963d1659fd7d9990196ed2d6" - [[package]] name = "x509-cert" version = "0.2.5" diff --git a/native/src/Cargo.toml b/native/src/Cargo.toml index a333ba927..8e38aaf4d 100644 --- a/native/src/Cargo.toml +++ b/native/src/Cargo.toml @@ -23,7 +23,6 @@ x509-cert = "0.2" der = "0.7" bytemuck = "1.14" fdt = "0.1" -procfs = { version = "0.16", default-features = false } [workspace.dependencies.argh] git = "https://github.com/google/argh.git" diff --git a/native/src/init/Cargo.toml b/native/src/init/Cargo.toml index 12dc3700d..c1b541faa 100644 --- a/native/src/init/Cargo.toml +++ b/native/src/init/Cargo.toml @@ -14,4 +14,3 @@ cxx-gen = { workspace = true } base = { path = "../base" } magiskpolicy = { path = "../sepolicy" } cxx = { workspace = true } -procfs = { workspace = true } diff --git a/native/src/init/lib.rs b/native/src/init/lib.rs index d2ab22711..448940658 100644 --- a/native/src/init/lib.rs +++ b/native/src/init/lib.rs @@ -17,7 +17,7 @@ pub mod ffi { fn setup_klog(); fn inject_magisk_rc(fd: i32, tmp_dir: Utf8CStrRef); fn switch_root(path: Utf8CStrRef); - fn is_device_mounted(dev: u64, mnt_point: &mut Vec) -> bool; + fn is_device_mounted(dev: u64, target: Pin<&mut CxxString>) -> bool; } unsafe extern "C++" { diff --git a/native/src/init/mount.cpp b/native/src/init/mount.cpp index 69ab19363..63276901c 100644 --- a/native/src/init/mount.cpp +++ b/native/src/init/mount.cpp @@ -114,10 +114,10 @@ static void mount_preinit_dir(string preinit_dev) { xmkdir(PREINITMNT, 0); bool mounted = false; // First, find if it is already mounted - rust::Vec mnt_point; + std::string mnt_point; if (rust::is_device_mounted(dev, mnt_point)) { // Already mounted, just bind mount - xmount((const char *) mnt_point.data(), PREINITMNT, nullptr, MS_BIND, nullptr); + xmount(mnt_point.data(), PREINITMNT, nullptr, MS_BIND, nullptr); mounted = true; } diff --git a/native/src/init/mount.rs b/native/src/init/mount.rs index 0c804bd7d..7f0931607 100644 --- a/native/src/init/mount.rs +++ b/native/src/init/mount.rs @@ -1,62 +1,134 @@ -use std::collections::BTreeSet; -use std::ops::Bound::{Excluded, Unbounded}; -use std::path::{Path, PathBuf}; -use std::{fs, ptr}; - -use procfs::process::Process; - use base::{ - cstr, debug, libc, raw_cstr, Directory, LibcReturn, LoggedError, LoggedResult, StringExt, - Utf8CStr, + cstr, debug, + libc::{chdir, chroot, makedev, mount, MS_MOVE}, + raw_cstr, BufReadExt, Directory, LibcReturn, LoggedResult, StringExt, Utf8CStr, }; +use cxx::CxxString; +use std::{ + collections::BTreeSet, + fs::File, + io::BufReader, + ops::Bound::{Excluded, Unbounded}, + pin::Pin, + ptr::null as nullptr, +}; + +#[allow(dead_code)] +struct MountInfo { + id: u32, + parent: u32, + device: u64, + root: String, + target: String, + vfs_option: String, + shared: u32, + master: u32, + propagation_from: u32, + unbindable: bool, + fs_type: String, + source: String, + fs_option: String, +} + +fn parse_mount_info_line(line: &str) -> Option { + let mut iter = line.split_whitespace(); + let id = iter.next()?.parse().ok()?; + let parent = iter.next()?.parse().ok()?; + let (maj, min) = iter.next()?.split_once(":")?; + let maj = maj.parse().ok()?; + let min = min.parse().ok()?; + let device = makedev(maj, min).into(); + let root = iter.next()?.to_string(); + let target = iter.next()?.to_string(); + let vfs_option = iter.next()?.to_string(); + let mut optional = iter.next()?; + let mut shared = 0; + let mut master = 0; + let mut propagation_from = 0; + let mut unbindable = false; + while optional != "-" { + if let Some(peer) = optional.strip_prefix("master:") { + master = peer.parse().ok()?; + } else if let Some(peer) = optional.strip_prefix("shared:") { + shared = peer.parse().ok()?; + } else if let Some(peer) = optional.strip_prefix("propagate_from:") { + propagation_from = peer.parse().ok()?; + } else if optional == "unbindable" { + unbindable = true; + } + optional = iter.next()?; + } + let fs_type = iter.next()?.to_string(); + let source = iter.next()?.to_string(); + let fs_option = iter.next()?.to_string(); + Some(MountInfo { + id, + parent, + device, + root, + target, + vfs_option, + shared, + master, + propagation_from, + unbindable, + fs_type, + source, + fs_option, + }) +} + +fn parse_mount_info(pid: &str) -> Vec { + let mut res = vec![]; + + if let Ok(file) = File::open(format!("/proc/{}/mountinfo", pid)) { + BufReader::new(file).foreach_lines(|line| { + parse_mount_info_line(line) + .map(|info| res.push(info)) + .is_some() + }); + } + res +} pub fn switch_root(path: &Utf8CStr) { fn inner(path: &Utf8CStr) -> LoggedResult<()> { - debug!("Switching root to {}", path); + debug!("Switch root to {}", path); + let mut mounts = BTreeSet::new(); let mut rootfs = Directory::open(cstr!("/"))?; - - let procfs = Process::myself()?; - let mut mounts: BTreeSet = BTreeSet::new(); - for info in procfs.mountinfo()?.0.into_iter() { - let mut target = info.mount_point; - if target == Path::new("/") || target == Path::new(path) { + for info in parse_mount_info("self") { + if info.target == "/" || info.target.as_str() == path.as_str() { continue; } - let iter = mounts.range::((Unbounded, Excluded(target.as_path()))); - if let Some(last_mount) = iter.last() { - if Path::new(path).starts_with(last_mount) { + if let Some(last_mount) = mounts + .range::((Unbounded, Excluded(&info.target))) + .last() + { + if info.target.starts_with(&format!("{}/", *last_mount)) { continue; } } - let mut new_path = PathBuf::from(path); - new_path.push(target.strip_prefix("/").unwrap()); - fs::create_dir(&new_path).ok(); /* Error is OK */ + let mut new_path = format!("{}/{}", path.as_str(), &info.target); + std::fs::create_dir(&new_path).ok(); + unsafe { - libc::mount( + let mut target = info.target.clone(); + mount( target.nul_terminate().as_ptr().cast(), new_path.nul_terminate().as_ptr().cast(), - ptr::null(), - libc::MS_MOVE, - ptr::null(), + nullptr(), + MS_MOVE, + nullptr(), ) .as_os_err()?; } - // Record all moved paths - mounts.insert(target); + mounts.insert(info.target); } - unsafe { - libc::chdir(path.as_ptr()).as_os_err()?; - libc::mount( - path.as_ptr(), - raw_cstr!("/"), - ptr::null(), - libc::MS_MOVE, - ptr::null(), - ) - .as_os_err()?; - libc::chroot(raw_cstr!(".")).as_os_err()?; + chdir(path.as_ptr()).as_os_err()?; + mount(path.as_ptr(), raw_cstr!("/"), nullptr(), MS_MOVE, nullptr()).as_os_err()?; + chroot(raw_cstr!(".")); } debug!("Cleaning rootfs"); @@ -66,28 +138,12 @@ pub fn switch_root(path: &Utf8CStr) { inner(path).ok(); } -pub fn is_device_mounted(dev: u64, mnt_point: &mut Vec) -> bool { - fn inner(dev: u64, mount_point: &mut Vec) -> LoggedResult<()> { - let procfs = Process::myself()?; - for mut info in procfs.mountinfo()?.0 { - if info.root != "/" { - continue; - } - let mut iter = info.majmin.split(':').map(|s| s.parse::()); - let maj = match iter.next() { - Some(Ok(s)) => s, - _ => continue, - }; - let min = match iter.next() { - Some(Ok(s)) => s, - _ => continue, - }; - if dev == libc::makedev(maj, min).into() { - *mount_point = info.mount_point.nul_terminate().to_vec(); - return Ok(()); - } +pub fn is_device_mounted(dev: u64, target: Pin<&mut CxxString>) -> bool { + for mount in parse_mount_info("self") { + if mount.root == "/" && mount.device == dev { + target.push_str(&mount.target); + return true; } - Err(LoggedError::default()) } - inner(dev, mnt_point).is_ok() + false }