Replace all parse_mount_info usage with Rust

This commit is contained in:
topjohnwu 2024-02-27 03:14:26 -08:00
parent af6965eefa
commit 1a70796339
8 changed files with 278 additions and 61 deletions

181
native/src/Cargo.lock generated
View File

@ -98,6 +98,12 @@ 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"
@ -109,9 +115,9 @@ dependencies = [
[[package]]
name = "bytemuck"
version = "1.14.1"
version = "1.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed2490600f404f2b94c167e31d3ed1d5f3c225a0f3b80230053b3e0b7b962bd9"
checksum = "a2ef034f05691a48569bd920a96c81b9d91bbad1ab5ac7c4616c1f6ef36cb79f"
dependencies = [
"bytemuck_derive",
]
@ -135,12 +141,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "cc"
version = "1.0.83"
version = "1.0.88"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
dependencies = [
"libc",
]
checksum = "02f341c093d19155a6e41631ce5971aac4e9a868262212153124c15fa22d1cdc"
[[package]]
name = "cfg-if"
@ -156,7 +159,7 @@ checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
dependencies = [
"ansi_term",
"atty",
"bitflags",
"bitflags 1.3.2",
"strsim",
"textwrap",
"unicode-width",
@ -326,6 +329,16 @@ 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"
@ -390,6 +403,12 @@ 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"
@ -438,6 +457,12 @@ 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"
@ -491,6 +516,7 @@ dependencies = [
"cxx",
"cxx-gen",
"magiskpolicy",
"procfs",
]
[[package]]
@ -543,9 +569,9 @@ dependencies = [
[[package]]
name = "num-derive"
version = "0.4.1"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfb77679af88f8b125209d354a202862602672222e7f2313fdd6dc349bad4712"
checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"
dependencies = [
"proc-macro2",
"quote",
@ -554,19 +580,18 @@ dependencies = [
[[package]]
name = "num-integer"
version = "0.1.45"
version = "0.1.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
dependencies = [
"autocfg",
"num-traits",
]
[[package]]
name = "num-iter"
version = "0.1.43"
version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252"
checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9"
dependencies = [
"autocfg",
"num-integer",
@ -575,9 +600,9 @@ dependencies = [
[[package]]
name = "num-traits"
version = "0.2.17"
version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a"
dependencies = [
"autocfg",
"libm",
@ -672,6 +697,29 @@ 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"
@ -784,6 +832,19 @@ 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"
@ -800,18 +861,18 @@ dependencies = [
[[package]]
name = "serde"
version = "1.0.196"
version = "1.0.197"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32"
checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.196"
version = "1.0.197"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67"
checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
dependencies = [
"proc-macro2",
"quote",
@ -892,9 +953,9 @@ checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
[[package]]
name = "syn"
version = "2.0.48"
version = "2.0.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
checksum = "6ab617d94515e94ae53b8406c628598680aa0c9587474ecbe58188f7b345d66c"
dependencies = [
"proc-macro2",
"quote",
@ -921,18 +982,18 @@ dependencies = [
[[package]]
name = "thiserror"
version = "1.0.56"
version = "1.0.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad"
checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.56"
version = "1.0.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471"
checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81"
dependencies = [
"proc-macro2",
"quote",
@ -1027,6 +1088,72 @@ 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"

View File

@ -23,6 +23,7 @@ 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"

View File

@ -2,9 +2,10 @@ use std::cmp::min;
use std::ffi::{CStr, FromBytesWithNulError, OsStr};
use std::fmt::{Arguments, Debug, Display, Formatter, Write};
use std::ops::{Deref, DerefMut};
use std::path::Path;
use std::path::{Path, PathBuf};
use std::str::{Utf8Chunks, Utf8Error};
use std::{fmt, mem, slice, str};
use std::os::unix::ffi::OsStrExt;
use cxx::{type_id, ExternType};
use libc::c_char;
@ -105,7 +106,7 @@ trait AsUtf8CStr {
// Implementation for Utf8CString
trait StringExt {
pub trait StringExt {
fn nul_terminate(&mut self) -> &mut [u8];
}
@ -122,6 +123,21 @@ impl StringExt for String {
}
}
impl StringExt for PathBuf {
#[allow(mutable_transmutes)]
fn nul_terminate(&mut self) -> &mut [u8] {
self.reserve(1);
// SAFETY: the PathBuf is reserved to have enough capacity to fit in the null byte
// SAFETY: the null byte is explicitly added outside of the PathBuf's length
unsafe {
let bytes: &mut [u8] = mem::transmute(self.as_mut_os_str().as_bytes());
let buf = slice::from_raw_parts_mut(bytes.as_mut_ptr(), bytes.len() + 1);
*buf.get_unchecked_mut(bytes.len()) = b'\0';
buf
}
}
}
#[derive(Default)]
pub struct Utf8CString(String);

@ -1 +1 @@
Subproject commit ba8166a48cf9424d0fb46691c64467c20da7cdfe
Subproject commit 9790b7ee48d3c396c94ef69e164004f50a1f5587

View File

@ -14,3 +14,4 @@ cxx-gen = { workspace = true }
base = { path = "../base" }
magiskpolicy = { path = "../sepolicy" }
cxx = { workspace = true }
procfs = { workspace = true }

View File

@ -1,11 +1,13 @@
#![feature(format_args_nl)]
use logging::setup_klog;
use mount::{is_device_mounted, switch_root};
use rootdir::inject_magisk_rc;
// Has to be pub so all symbols in that crate is included
pub use magiskpolicy;
mod logging;
mod mount;
mod rootdir;
#[cxx::bridge]
@ -14,6 +16,8 @@ pub mod ffi {
extern "Rust" {
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<u8>) -> bool;
}
unsafe extern "C++" {

View File

@ -100,29 +100,6 @@ static dev_t setup_block() {
return 0;
}
static void switch_root(const string &path) {
LOGD("Switch root to %s\n", path.data());
int root = xopen("/", O_RDONLY);
for (set<string, greater<>> mounts; auto &info : parse_mount_info("self")) {
if (info.target == "/" || info.target == path)
continue;
if (auto last_mount = mounts.upper_bound(info.target);
last_mount != mounts.end() && info.target.starts_with(*last_mount + '/')) {
continue;
}
mounts.emplace(info.target);
auto new_path = path + info.target;
xmkdir(new_path.data(), 0755);
xmount(info.target.data(), new_path.data(), nullptr, MS_MOVE, nullptr);
}
chdir(path.data());
xmount(path.data(), "/", nullptr, MS_MOVE, nullptr);
chroot(".");
LOGD("Cleaning rootfs\n");
frm_rf(root);
}
#define PREINITMNT MIRRDIR "/preinit"
static void mount_preinit_dir(string preinit_dev) {
@ -137,13 +114,11 @@ static void mount_preinit_dir(string preinit_dev) {
xmkdir(PREINITMNT, 0);
bool mounted = false;
// First, find if it is already mounted
for (auto &info : parse_mount_info("self")) {
if (info.root == "/" && info.device == dev) {
// Already mounted, just bind mount
xmount(info.target.data(), PREINITMNT, nullptr, MS_BIND, nullptr);
mounted = true;
break;
}
rust::Vec<uint8_t> 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);
mounted = true;
}
// Since we are mounting the block device directly, make sure to ONLY mount the partitions
@ -212,7 +187,7 @@ mount_root:
}
}
switch_root("/system_root");
rust::switch_root("/system_root");
// Make dev writable
xmount("tmpfs", "/dev", "tmpfs", 0, "mode=755");

93
native/src/init/mount.rs Normal file
View File

@ -0,0 +1,93 @@
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,
};
pub fn switch_root(path: &Utf8CStr) {
fn inner(path: &Utf8CStr) -> LoggedResult<()> {
debug!("Switching root to {}", path);
let mut rootfs = Directory::open(cstr!("/"))?;
let procfs = Process::myself()?;
let mut mounts: BTreeSet<PathBuf> = BTreeSet::new();
for info in procfs.mountinfo()?.0.into_iter() {
let mut target = info.mount_point;
if target == Path::new("/") || target == Path::new(path) {
continue;
}
let iter = mounts.range::<Path, _>((Unbounded, Excluded(target.as_path())));
if let Some(last_mount) = iter.last() {
if Path::new(path).starts_with(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 */
unsafe {
libc::mount(
target.nul_terminate().as_ptr().cast(),
new_path.nul_terminate().as_ptr().cast(),
ptr::null(),
libc::MS_MOVE,
ptr::null(),
)
.as_os_err()?;
}
// Record all moved paths
mounts.insert(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()?;
}
debug!("Cleaning rootfs");
rootfs.remove_all()?;
Ok(())
}
inner(path).ok();
}
pub fn is_device_mounted(dev: u64, mnt_point: &mut Vec<u8>) -> bool {
fn inner(dev: u64, mount_point: &mut Vec<u8>) -> 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::<u32>());
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(());
}
}
Err(LoggedError::default())
}
inner(dev, mnt_point).is_ok()
}