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