mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-08-14 00:57:24 +00:00
Introduce mount helper methods
This commit is contained in:
@@ -21,6 +21,7 @@ mod dir;
|
||||
mod files;
|
||||
mod logging;
|
||||
mod misc;
|
||||
mod mount;
|
||||
mod result;
|
||||
mod xwrap;
|
||||
|
||||
|
62
native/src/base/mount.rs
Normal file
62
native/src/base/mount.rs
Normal file
@@ -0,0 +1,62 @@
|
||||
use crate::{FsPath, LibcReturn};
|
||||
use libc::c_ulong;
|
||||
use std::ptr;
|
||||
|
||||
impl FsPath {
|
||||
pub fn bind_mount_to(&self, path: &FsPath) -> std::io::Result<()> {
|
||||
unsafe {
|
||||
libc::mount(
|
||||
self.as_ptr(),
|
||||
path.as_ptr(),
|
||||
ptr::null(),
|
||||
libc::MS_BIND,
|
||||
ptr::null(),
|
||||
)
|
||||
.as_os_err()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn remount_with_flags(&self, flags: c_ulong) -> std::io::Result<()> {
|
||||
unsafe {
|
||||
libc::mount(
|
||||
ptr::null(),
|
||||
self.as_ptr(),
|
||||
ptr::null(),
|
||||
libc::MS_BIND | libc::MS_REMOUNT | flags,
|
||||
ptr::null(),
|
||||
)
|
||||
.as_os_err()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn move_mount_to(&self, path: &FsPath) -> std::io::Result<()> {
|
||||
unsafe {
|
||||
libc::mount(
|
||||
self.as_ptr(),
|
||||
path.as_ptr(),
|
||||
ptr::null(),
|
||||
libc::MS_MOVE,
|
||||
ptr::null(),
|
||||
)
|
||||
.as_os_err()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unmount(&self) -> std::io::Result<()> {
|
||||
unsafe { libc::umount2(self.as_ptr(), libc::MNT_DETACH).as_os_err() }
|
||||
}
|
||||
|
||||
pub fn set_mount_private(&self, recursive: bool) -> std::io::Result<()> {
|
||||
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(),
|
||||
)
|
||||
.as_os_err()
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,15 +1,14 @@
|
||||
use std::{
|
||||
cmp::Ordering::{Greater, Less},
|
||||
path::{Path, PathBuf},
|
||||
ptr,
|
||||
};
|
||||
|
||||
use num_traits::AsPrimitive;
|
||||
|
||||
use base::libc::{c_uint, dev_t};
|
||||
use base::{
|
||||
cstr, cstr_buf, debug, info, libc, parse_mount_info, raw_cstr, warn, FsPath, FsPathBuf,
|
||||
LibcReturn, LoggedResult, MountInfo, ResultExt, Utf8CStr,
|
||||
FsPath, FsPathBuf, LibcReturn, LoggedResult, MountInfo, ResultExt, Utf8CStr, cstr, cstr_buf,
|
||||
debug, info, libc, parse_mount_info, path, warn,
|
||||
};
|
||||
|
||||
use crate::consts::{MODULEMNT, MODULEROOT, PREINITDEV, PREINITMIRR, WORKERDIR};
|
||||
@@ -73,24 +72,8 @@ pub fn setup_mounts() {
|
||||
let module_mnt = FsPathBuf::default().join(magisk_tmp).join(MODULEMNT);
|
||||
let _: LoggedResult<()> = try {
|
||||
module_mnt.mkdir(0o755)?;
|
||||
unsafe {
|
||||
libc::mount(
|
||||
raw_cstr!(MODULEROOT),
|
||||
module_mnt.as_ptr(),
|
||||
ptr::null(),
|
||||
libc::MS_BIND,
|
||||
ptr::null(),
|
||||
)
|
||||
.as_os_err()?;
|
||||
libc::mount(
|
||||
ptr::null(),
|
||||
module_mnt.as_ptr(),
|
||||
ptr::null(),
|
||||
libc::MS_REMOUNT | libc::MS_BIND | libc::MS_RDONLY,
|
||||
ptr::null(),
|
||||
)
|
||||
.as_os_err()?;
|
||||
}
|
||||
path!(MODULEROOT).bind_mount_to(&module_mnt)?;
|
||||
module_mnt.remount_with_flags(libc::MS_RDONLY)?;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -98,26 +81,13 @@ pub fn clean_mounts() {
|
||||
let magisk_tmp = get_magisk_tmp();
|
||||
|
||||
let mut module_mnt = FsPathBuf::default().join(magisk_tmp).join(MODULEMNT);
|
||||
let _: LoggedResult<()> = try {
|
||||
unsafe {
|
||||
libc::umount2(module_mnt.as_ptr(), libc::MNT_DETACH).as_os_err()?;
|
||||
}
|
||||
};
|
||||
module_mnt.unmount().log_ok();
|
||||
|
||||
module_mnt.clear();
|
||||
let worker_dir = module_mnt.join(magisk_tmp).join(WORKERDIR);
|
||||
let _: LoggedResult<()> = try {
|
||||
unsafe {
|
||||
libc::mount(
|
||||
ptr::null(),
|
||||
worker_dir.as_ptr(),
|
||||
ptr::null(),
|
||||
libc::MS_PRIVATE | libc::MS_REC,
|
||||
ptr::null(),
|
||||
)
|
||||
.as_os_err()?;
|
||||
libc::umount2(worker_dir.as_ptr(), libc::MNT_DETACH).as_os_err()?;
|
||||
}
|
||||
worker_dir.set_mount_private(true)?;
|
||||
worker_dir.unmount()?;
|
||||
};
|
||||
}
|
||||
|
||||
|
@@ -1,23 +1,23 @@
|
||||
use crate::ffi::MagiskInit;
|
||||
use base::libc::{TMPFS_MAGIC, statfs};
|
||||
use base::{
|
||||
cstr, debug, libc,
|
||||
libc::{chdir, chroot, execve, exit, mount, umount2, MNT_DETACH, MS_MOVE},
|
||||
parse_mount_info, path, raw_cstr, Directory, LibcReturn, LoggedResult, ResultExt, StringExt,
|
||||
Utf8CStr,
|
||||
Directory, FsPath, FsPathBuf, LibcReturn, LoggedResult, ResultExt, Utf8CStr, cstr, debug, libc,
|
||||
libc::{chdir, chroot, execve, exit, mount},
|
||||
parse_mount_info, path, raw_cstr,
|
||||
};
|
||||
use cxx::CxxString;
|
||||
use std::ffi::c_long;
|
||||
use std::{
|
||||
collections::BTreeSet,
|
||||
ops::Bound::{Excluded, Unbounded},
|
||||
pin::Pin,
|
||||
ptr::null as nullptr,
|
||||
};
|
||||
|
||||
unsafe extern "C" {
|
||||
static environ: *const *mut libc::c_char;
|
||||
}
|
||||
|
||||
pub fn switch_root(path: &Utf8CStr) {
|
||||
pub(crate) fn switch_root(path: &Utf8CStr) {
|
||||
let res: LoggedResult<()> = try {
|
||||
debug!("Switch root to {}", path);
|
||||
let mut mounts = BTreeSet::new();
|
||||
@@ -34,26 +34,19 @@ pub fn switch_root(path: &Utf8CStr) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
let mut new_path = format!("{}/{}", path.as_str(), &info.target);
|
||||
std::fs::create_dir(&new_path).ok();
|
||||
|
||||
unsafe {
|
||||
let mut target = info.target.clone();
|
||||
mount(
|
||||
target.nul_terminate().as_ptr().cast(),
|
||||
new_path.nul_terminate().as_ptr().cast(),
|
||||
nullptr(),
|
||||
MS_MOVE,
|
||||
nullptr(),
|
||||
)
|
||||
.as_os_err()?;
|
||||
}
|
||||
|
||||
let mut target = info.target.clone();
|
||||
let target = FsPath::from(Utf8CStr::from_string(&mut target));
|
||||
let new_path = FsPathBuf::default()
|
||||
.join(path)
|
||||
.join(info.target.trim_start_matches('/'));
|
||||
new_path.mkdirs(0o755).ok();
|
||||
target.move_mount_to(&new_path)?;
|
||||
mounts.insert(info.target);
|
||||
}
|
||||
unsafe {
|
||||
chdir(path.as_ptr()).as_os_err()?;
|
||||
mount(path.as_ptr(), raw_cstr!("/"), nullptr(), MS_MOVE, nullptr()).as_os_err()?;
|
||||
FsPath::from(path).move_mount_to(path!("/"))?;
|
||||
chroot(raw_cstr!("."));
|
||||
}
|
||||
|
||||
@@ -63,7 +56,7 @@ pub fn switch_root(path: &Utf8CStr) {
|
||||
res.ok();
|
||||
}
|
||||
|
||||
pub fn is_device_mounted(dev: u64, target: Pin<&mut CxxString>) -> bool {
|
||||
pub(crate) 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);
|
||||
@@ -73,6 +66,16 @@ pub fn is_device_mounted(dev: u64, target: Pin<&mut CxxString>) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
const RAMFS_MAGIC: u64 = 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
|
||||
}
|
||||
}
|
||||
|
||||
impl MagiskInit {
|
||||
pub(crate) fn prepare_data(&self) {
|
||||
debug!("Setup data tmp");
|
||||
@@ -96,21 +99,17 @@ impl MagiskInit {
|
||||
.log_ok();
|
||||
}
|
||||
|
||||
pub(crate) fn exec_init(&self) {
|
||||
unsafe {
|
||||
for p in self.mount_list.iter().rev() {
|
||||
if umount2(p.as_ptr().cast(), MNT_DETACH)
|
||||
.as_os_err()
|
||||
.log()
|
||||
.is_ok()
|
||||
{
|
||||
debug!("Unmount [{}]", p);
|
||||
}
|
||||
pub(crate) fn exec_init(&mut self) {
|
||||
for path in self.mount_list.iter_mut().rev() {
|
||||
let path = FsPath::from(Utf8CStr::from_string(path));
|
||||
if path.unmount().log().is_ok() {
|
||||
debug!("Unmount [{}]", path);
|
||||
}
|
||||
}
|
||||
unsafe {
|
||||
execve(raw_cstr!("/init"), self.argv.cast(), environ.cast())
|
||||
.as_os_err()
|
||||
.log()
|
||||
.ok();
|
||||
.log_ok();
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
@@ -2,8 +2,8 @@ use crate::consts::{ROOTMNT, ROOTOVL};
|
||||
use crate::ffi::MagiskInit;
|
||||
use base::libc::{O_CREAT, O_RDONLY, O_WRONLY};
|
||||
use base::{
|
||||
clone_attr, cstr, cstr_buf, debug, libc, path, BufReadExt, Directory, FsPath, FsPathBuf,
|
||||
LibcReturn, LoggedResult, ResultExt, Utf8CStr, Utf8CString,
|
||||
BufReadExt, Directory, FsPath, FsPathBuf, LoggedResult, ResultExt, Utf8CStr, Utf8CString,
|
||||
clone_attr, cstr, cstr_buf, debug, path,
|
||||
};
|
||||
use std::io::BufReader;
|
||||
use std::{
|
||||
@@ -11,7 +11,6 @@ use std::{
|
||||
io::Write,
|
||||
mem,
|
||||
os::fd::{FromRawFd, RawFd},
|
||||
ptr,
|
||||
};
|
||||
|
||||
pub fn inject_magisk_rc(fd: RawFd, tmp_dir: &Utf8CStr) {
|
||||
@@ -83,16 +82,7 @@ impl MagiskInit {
|
||||
debug!("Mount [{}] -> [{}]", src, dest);
|
||||
clone_attr(&dest, &src)?;
|
||||
dest.get_secontext(&mut con)?;
|
||||
unsafe {
|
||||
libc::mount(
|
||||
src.as_ptr(),
|
||||
dest.as_ptr(),
|
||||
ptr::null(),
|
||||
libc::MS_BIND,
|
||||
ptr::null(),
|
||||
)
|
||||
.as_os_err()?;
|
||||
};
|
||||
src.bind_mount_to(&dest)?;
|
||||
self.overlay_con
|
||||
.push(OverlayAttr(dest.to_owned(), con.to_owned()));
|
||||
mount_list.push_str(dest.as_str());
|
||||
|
@@ -1,15 +1,11 @@
|
||||
use crate::ffi::MagiskInit;
|
||||
use crate::mount::is_rootfs;
|
||||
use base::{
|
||||
LibcReturn, LoggedResult, MappedFile, MutBytesExt, ResultExt, cstr, debug, error, info,
|
||||
libc::{
|
||||
MNT_DETACH, MS_BIND, O_CLOEXEC, O_CREAT, O_RDONLY, O_WRONLY, TMPFS_MAGIC, mount, statfs,
|
||||
umount2,
|
||||
},
|
||||
LoggedResult, MappedFile, MutBytesExt, ResultExt, cstr, debug, error, info,
|
||||
libc::{O_CLOEXEC, O_CREAT, O_RDONLY, O_WRONLY},
|
||||
path, raw_cstr,
|
||||
};
|
||||
use std::{ffi::c_long, io::Write, ptr::null};
|
||||
|
||||
const RAMFS_MAGIC: u64 = 0x858458f6;
|
||||
use std::io::Write;
|
||||
|
||||
fn patch_init_path(init: &mut MappedFile) {
|
||||
let from = "/system/bin/init";
|
||||
@@ -70,28 +66,13 @@ impl MagiskInit {
|
||||
path!("/init").rename_to(path!("/sdcard")).log_ok();
|
||||
|
||||
// First try to mount magiskinit from rootfs to workaround Samsung RKP
|
||||
if unsafe {
|
||||
mount(
|
||||
raw_cstr!("/sdcard"),
|
||||
raw_cstr!("/sdcard"),
|
||||
null(),
|
||||
MS_BIND,
|
||||
null(),
|
||||
)
|
||||
} == 0
|
||||
{
|
||||
if path!("/sdcard").bind_mount_to(path!("/sdcard")).is_ok() {
|
||||
debug!("Bind mount /sdcard -> /sdcard");
|
||||
} else {
|
||||
// Binding mounting from rootfs is not supported before Linux 3.12
|
||||
unsafe {
|
||||
mount(
|
||||
raw_cstr!("/data/magiskinit"),
|
||||
raw_cstr!("/sdcard"),
|
||||
null(),
|
||||
MS_BIND,
|
||||
null(),
|
||||
)
|
||||
};
|
||||
path!("/data/magiskinit")
|
||||
.bind_mount_to(path!("/sdcard"))
|
||||
.log_ok();
|
||||
debug!("Bind mount /data/magiskinit -> /sdcard");
|
||||
}
|
||||
}
|
||||
@@ -139,36 +120,33 @@ impl MagiskInit {
|
||||
let _: LoggedResult<()> = try {
|
||||
let attr = src.follow_link().get_attr()?;
|
||||
dest.set_attr(&attr)?;
|
||||
unsafe {
|
||||
mount(dest.as_ptr(), src.as_ptr(), null(), MS_BIND, null()).as_os_err()?;
|
||||
}
|
||||
dest.bind_mount_to(src)?;
|
||||
};
|
||||
}
|
||||
|
||||
pub(crate) fn second_stage(&mut self) {
|
||||
info!("Second Stage Init");
|
||||
unsafe {
|
||||
umount2(raw_cstr!("/init"), MNT_DETACH);
|
||||
umount2(raw_cstr!("/system/bin/init"), MNT_DETACH); // just in case
|
||||
path!("/data/init").remove().ok();
|
||||
|
||||
path!("/init").unmount().ok();
|
||||
path!("/system/bin/init").unmount().ok(); // just in case
|
||||
path!("/data/init").remove().ok();
|
||||
|
||||
unsafe {
|
||||
// Make sure init dmesg logs won't get messed up
|
||||
*self.argv = raw_cstr!("/system/bin/init") as *mut _;
|
||||
}
|
||||
|
||||
// Some weird devices like meizu, uses 2SI but still have legacy rootfs
|
||||
let mut sfs: statfs = std::mem::zeroed();
|
||||
statfs(raw_cstr!("/"), &mut sfs);
|
||||
if sfs.f_type as u64 == RAMFS_MAGIC || 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 = path!("/init");
|
||||
init_path.remove().ok();
|
||||
init_path
|
||||
.create_symlink_to(path!("/system/bin/init"))
|
||||
.log_ok();
|
||||
self.patch_rw_root();
|
||||
} else {
|
||||
self.patch_ro_root();
|
||||
}
|
||||
// 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");
|
||||
init_path.remove().ok();
|
||||
init_path
|
||||
.create_symlink_to(path!("/system/bin/init"))
|
||||
.log_ok();
|
||||
self.patch_rw_root();
|
||||
} else {
|
||||
self.patch_ro_root();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user