mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-10-28 02:42:07 +00:00
Enable mount for nix
This commit is contained in:
1
native/src/Cargo.lock
generated
1
native/src/Cargo.lock
generated
@@ -694,6 +694,7 @@ dependencies = [
|
|||||||
"cxx",
|
"cxx",
|
||||||
"cxx-gen",
|
"cxx-gen",
|
||||||
"magiskpolicy",
|
"magiskpolicy",
|
||||||
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
@@ -23,4 +23,4 @@ bytemuck = { workspace = true }
|
|||||||
num-traits = { workspace = true }
|
num-traits = { workspace = true }
|
||||||
num-derive = { workspace = true }
|
num-derive = { workspace = true }
|
||||||
const_format = { workspace = true }
|
const_format = { workspace = true }
|
||||||
nix = { workspace = true, features = ["fs"] }
|
nix = { workspace = true, features = ["fs", "mount"] }
|
||||||
|
|||||||
@@ -335,6 +335,11 @@ impl Utf8CStr {
|
|||||||
unsafe { CStr::from_bytes_with_nul_unchecked(&self.0) }
|
unsafe { CStr::from_bytes_with_nul_unchecked(&self.0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn as_utf8_cstr(&self) -> &Utf8CStr {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn as_str(&self) -> &str {
|
pub fn as_str(&self) -> &str {
|
||||||
// SAFETY: Already UTF-8 validated during construction
|
// SAFETY: Already UTF-8 validated during construction
|
||||||
|
|||||||
@@ -1,91 +1,84 @@
|
|||||||
use crate::{LibcReturn, OsResult, Utf8CStr};
|
use crate::{LibcReturn, OsResult, Utf8CStr};
|
||||||
use libc::c_ulong;
|
use nix::mount::{MntFlags, MsFlags, mount, umount2};
|
||||||
use std::ptr;
|
|
||||||
|
|
||||||
impl Utf8CStr {
|
impl Utf8CStr {
|
||||||
pub fn bind_mount_to<'a>(&'a self, path: &'a Utf8CStr, rec: bool) -> OsResult<'a, ()> {
|
pub fn bind_mount_to<'a>(&'a self, path: &'a Utf8CStr, rec: bool) -> OsResult<'a, ()> {
|
||||||
let flag = if rec { libc::MS_REC } else { 0 };
|
let flag = if rec {
|
||||||
unsafe {
|
MsFlags::MS_REC
|
||||||
libc::mount(
|
} else {
|
||||||
self.as_ptr(),
|
MsFlags::empty()
|
||||||
path.as_ptr(),
|
};
|
||||||
ptr::null(),
|
mount(
|
||||||
libc::MS_BIND | flag,
|
Some(self),
|
||||||
ptr::null(),
|
path,
|
||||||
)
|
None::<&Utf8CStr>,
|
||||||
.check_os_err("bind_mount", Some(self), Some(path))
|
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<'_, ()> {
|
pub fn remount_mount_point_flags(&self, flags: MsFlags) -> OsResult<'_, ()> {
|
||||||
unsafe {
|
mount(
|
||||||
libc::mount(
|
None::<&Utf8CStr>,
|
||||||
ptr::null(),
|
self,
|
||||||
self.as_ptr(),
|
None::<&Utf8CStr>,
|
||||||
ptr::null(),
|
MsFlags::MS_BIND | MsFlags::MS_REMOUNT | flags,
|
||||||
libc::MS_BIND | libc::MS_REMOUNT | flags,
|
None::<&Utf8CStr>,
|
||||||
ptr::null(),
|
)
|
||||||
)
|
.check_os_err("remount", Some(self), None)
|
||||||
.check_os_err("remount", Some(self), None)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remount_mount_flags(&self, flags: c_ulong) -> OsResult<'_, ()> {
|
pub fn remount_mount_flags(&self, flags: MsFlags) -> OsResult<'_, ()> {
|
||||||
unsafe {
|
mount(
|
||||||
libc::mount(
|
None::<&Utf8CStr>,
|
||||||
ptr::null(),
|
self,
|
||||||
self.as_ptr(),
|
None::<&Utf8CStr>,
|
||||||
ptr::null(),
|
MsFlags::MS_REMOUNT | flags,
|
||||||
libc::MS_REMOUNT | flags,
|
None::<&Utf8CStr>,
|
||||||
ptr::null(),
|
)
|
||||||
)
|
.check_os_err("remount", Some(self), None)
|
||||||
.check_os_err("remount", Some(self), None)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remount_with_data(&self, data: &Utf8CStr) -> OsResult<'_, ()> {
|
pub fn remount_with_data(&self, data: &Utf8CStr) -> OsResult<'_, ()> {
|
||||||
unsafe {
|
mount(
|
||||||
libc::mount(
|
None::<&Utf8CStr>,
|
||||||
ptr::null(),
|
self,
|
||||||
self.as_ptr(),
|
None::<&Utf8CStr>,
|
||||||
ptr::null(),
|
MsFlags::MS_REMOUNT,
|
||||||
libc::MS_REMOUNT,
|
Some(data),
|
||||||
data.as_ptr().cast(),
|
)
|
||||||
)
|
.check_os_err("remount", Some(self), None)
|
||||||
.check_os_err("remount", Some(self), None)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn move_mount_to<'a>(&'a self, path: &'a Utf8CStr) -> OsResult<'a, ()> {
|
pub fn move_mount_to<'a>(&'a self, path: &'a Utf8CStr) -> OsResult<'a, ()> {
|
||||||
unsafe {
|
mount(
|
||||||
libc::mount(
|
Some(self),
|
||||||
self.as_ptr(),
|
path,
|
||||||
path.as_ptr(),
|
None::<&Utf8CStr>,
|
||||||
ptr::null(),
|
MsFlags::MS_MOVE,
|
||||||
libc::MS_MOVE,
|
None::<&Utf8CStr>,
|
||||||
ptr::null(),
|
)
|
||||||
)
|
.check_os_err("move_mount", Some(self), Some(path))
|
||||||
.check_os_err("move_mount", Some(self), Some(path))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unmount(&self) -> OsResult<'_, ()> {
|
pub fn unmount(&self) -> OsResult<'_, ()> {
|
||||||
unsafe {
|
umount2(self, MntFlags::MNT_DETACH).check_os_err("unmount", Some(self), None)
|
||||||
libc::umount2(self.as_ptr(), libc::MNT_DETACH).check_os_err("unmount", Some(self), None)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_mount_private(&self, recursive: bool) -> OsResult<'_, ()> {
|
pub fn set_mount_private(&self, rec: bool) -> OsResult<'_, ()> {
|
||||||
let flag = if recursive { libc::MS_REC } else { 0 };
|
let flag = if rec {
|
||||||
unsafe {
|
MsFlags::MS_REC
|
||||||
libc::mount(
|
} else {
|
||||||
ptr::null(),
|
MsFlags::empty()
|
||||||
self.as_ptr(),
|
};
|
||||||
ptr::null(),
|
mount(
|
||||||
libc::MS_PRIVATE | flag,
|
None::<&Utf8CStr>,
|
||||||
ptr::null(),
|
self,
|
||||||
)
|
None::<&Utf8CStr>,
|
||||||
.check_os_err("set_mount_private", Some(self), None)
|
flag | MsFlags::MS_PRIVATE,
|
||||||
}
|
None::<&Utf8CStr>,
|
||||||
|
)
|
||||||
|
.check_os_err("set_mount_private", Some(self), None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,4 +26,4 @@ bytemuck = { workspace = true, features = ["derive"] }
|
|||||||
thiserror = { workspace = true }
|
thiserror = { workspace = true }
|
||||||
bit-set = { workspace = true }
|
bit-set = { workspace = true }
|
||||||
argh = { workspace = true }
|
argh = { workspace = true }
|
||||||
nix = { workspace = true, features = ["fs", "poll", "signal", "term", "zerocopy"] }
|
nix = { workspace = true, features = ["fs", "mount", "poll", "signal", "term", "zerocopy"] }
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ use base::{
|
|||||||
cstr, error, info, libc,
|
cstr, error, info, libc,
|
||||||
};
|
};
|
||||||
use nix::fcntl::OFlag;
|
use nix::fcntl::OFlag;
|
||||||
|
use nix::mount::MsFlags;
|
||||||
use std::fmt::Write as FmtWrite;
|
use std::fmt::Write as FmtWrite;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{BufReader, Write};
|
use std::io::{BufReader, Write};
|
||||||
@@ -384,7 +385,7 @@ pub fn daemon_entry() {
|
|||||||
|
|
||||||
// Remount rootfs as read-only if requested
|
// Remount rootfs as read-only if requested
|
||||||
if std::env::var_os("REMOUNT_ROOT").is_some() {
|
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") };
|
unsafe { std::env::remove_var("REMOUNT_ROOT") };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,8 +8,7 @@ use base::{
|
|||||||
Utf8CStrBuf, Utf8CString, WalkResult, clone_attr, cstr, debug, error, info, libc, raw_cstr,
|
Utf8CStrBuf, Utf8CString, WalkResult, clone_attr, cstr, debug, error, info, libc, raw_cstr,
|
||||||
warn,
|
warn,
|
||||||
};
|
};
|
||||||
use libc::MS_RDONLY;
|
use nix::{fcntl::OFlag, mount::MsFlags, unistd::UnlinkatFlags};
|
||||||
use nix::{fcntl::OFlag, unistd::UnlinkatFlags};
|
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::os::fd::IntoRawFd;
|
use std::os::fd::IntoRawFd;
|
||||||
use std::path::{Component, Path};
|
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
|
// 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.
|
// kernel limitations, don't let it break module mount entirely.
|
||||||
src.bind_mount_to(dest, rec).log_ok();
|
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>(
|
fn mount_dummy<'a>(
|
||||||
|
|||||||
@@ -1,19 +1,17 @@
|
|||||||
use std::{
|
use crate::consts::{MODULEMNT, MODULEROOT, PREINITDEV, PREINITMIRR, WORKERDIR};
|
||||||
cmp::Ordering::{Greater, Less},
|
use crate::ffi::{get_magisk_tmp, resolve_preinit_dir, switch_mnt_ns};
|
||||||
path::{Path, PathBuf},
|
use crate::resetprop::get_prop;
|
||||||
};
|
|
||||||
|
|
||||||
use num_traits::AsPrimitive;
|
|
||||||
|
|
||||||
use base::libc::{c_uint, dev_t};
|
|
||||||
use base::{
|
use base::{
|
||||||
FsPathBuilder, LibcReturn, LoggedResult, MountInfo, ResultExt, Utf8CStr, Utf8CStrBuf, cstr,
|
FsPathBuilder, LibcReturn, LoggedResult, MountInfo, ResultExt, Utf8CStr, Utf8CStrBuf, cstr,
|
||||||
debug, info, libc, parse_mount_info, warn,
|
debug, info, libc, parse_mount_info, warn,
|
||||||
};
|
};
|
||||||
|
use libc::{c_uint, dev_t};
|
||||||
use crate::consts::{MODULEMNT, MODULEROOT, PREINITDEV, PREINITMIRR, WORKERDIR};
|
use nix::{
|
||||||
use crate::ffi::{get_magisk_tmp, resolve_preinit_dir, switch_mnt_ns};
|
mount::MsFlags,
|
||||||
use crate::resetprop::get_prop;
|
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() {
|
pub fn setup_preinit_dir() {
|
||||||
let magisk_tmp = get_magisk_tmp();
|
let magisk_tmp = get_magisk_tmp();
|
||||||
@@ -69,7 +67,7 @@ pub fn setup_module_mount() {
|
|||||||
let _: LoggedResult<()> = try {
|
let _: LoggedResult<()> = try {
|
||||||
module_mnt.mkdir(0o755)?;
|
module_mnt.mkdir(0o755)?;
|
||||||
cstr!(MODULEROOT).bind_mount_to(&module_mnt, false)?;
|
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() {
|
if std::env::var_os("MAKEDEV").is_some() {
|
||||||
buf.clear();
|
buf.clear();
|
||||||
let dev_path = buf.append_path(&tmp).append_path(PREINITDEV);
|
let dev_path = buf.append_path(&tmp).append_path(PREINITDEV);
|
||||||
unsafe {
|
mknod(
|
||||||
libc::mknod(
|
dev_path.as_utf8_cstr(),
|
||||||
dev_path.as_ptr(),
|
SFlag::S_IFBLK,
|
||||||
libc::S_IFBLK | 0o600,
|
Mode::from_bits_truncate(0o600),
|
||||||
info.device as dev_t,
|
info.device as dev_t,
|
||||||
)
|
)
|
||||||
.check_os_err("mknod", Some(dev_path), None)
|
.check_os_err("mknod", Some(dev_path), None)
|
||||||
.log_ok();
|
.log_ok();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Path::new(&info.source)
|
Path::new(&info.source)
|
||||||
@@ -248,10 +245,8 @@ pub fn revert_unmount(pid: i32) {
|
|||||||
|
|
||||||
for mut target in targets {
|
for mut target in targets {
|
||||||
let target = Utf8CStr::from_string(&mut target);
|
let target = Utf8CStr::from_string(&mut target);
|
||||||
unsafe {
|
if target.unmount().is_ok() {
|
||||||
if libc::umount2(target.as_ptr(), libc::MNT_DETACH) == 0 {
|
debug!("denylist: Unmounted ({})", target);
|
||||||
debug!("denylist: Unmounted ({})", target);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
2
native/src/external/crt0
vendored
2
native/src/external/crt0
vendored
Submodule native/src/external/crt0 updated: f7f5d092b2...9dfa67b4d5
@@ -14,3 +14,4 @@ cxx-gen = { workspace = true }
|
|||||||
base = { path = "../base" }
|
base = { path = "../base" }
|
||||||
magiskpolicy = { path = "../sepolicy", default-features = false }
|
magiskpolicy = { path = "../sepolicy", default-features = false }
|
||||||
cxx = { workspace = true }
|
cxx = { workspace = true }
|
||||||
|
num-traits = { workspace = true }
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
use crate::ffi::MagiskInit;
|
use crate::ffi::MagiskInit;
|
||||||
use base::libc::{TMPFS_MAGIC, statfs};
|
|
||||||
use base::{
|
use base::{
|
||||||
Directory, FsPathBuilder, LibcReturn, LoggedResult, ResultExt, Utf8CStr, cstr, debug, libc,
|
Directory, FsPathBuilder, LibcReturn, LoggedResult, ResultExt, Utf8CStr, cstr, debug, libc,
|
||||||
libc::{chdir, chroot, execve, exit, mount},
|
nix, parse_mount_info, raw_cstr,
|
||||||
parse_mount_info, raw_cstr,
|
|
||||||
};
|
};
|
||||||
use cxx::CxxString;
|
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::{
|
use std::{
|
||||||
collections::BTreeSet,
|
collections::BTreeSet,
|
||||||
ops::Bound::{Excluded, Unbounded},
|
ops::Bound::{Excluded, Unbounded},
|
||||||
@@ -43,11 +46,9 @@ pub(crate) fn switch_root(path: &Utf8CStr) {
|
|||||||
target.move_mount_to(&new_path)?;
|
target.move_mount_to(&new_path)?;
|
||||||
mounts.insert(info.target);
|
mounts.insert(info.target);
|
||||||
}
|
}
|
||||||
unsafe {
|
chdir(path)?;
|
||||||
chdir(path.as_ptr()).check_err()?;
|
path.move_mount_to(cstr!("/"))?;
|
||||||
path.move_mount_to(cstr!("/"))?;
|
chroot(cstr!("."))?;
|
||||||
chroot(raw_cstr!("."));
|
|
||||||
}
|
|
||||||
|
|
||||||
debug!("Cleaning rootfs");
|
debug!("Cleaning rootfs");
|
||||||
rootfs.remove_all()?;
|
rootfs.remove_all()?;
|
||||||
@@ -65,13 +66,13 @@ pub(crate) fn is_device_mounted(dev: u64, target: Pin<&mut CxxString>) -> bool {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
const RAMFS_MAGIC: u64 = 0x858458f6;
|
const RAMFS_MAGIC: u32 = 0x858458f6;
|
||||||
|
|
||||||
pub(crate) fn is_rootfs() -> bool {
|
pub(crate) fn is_rootfs() -> bool {
|
||||||
unsafe {
|
if let Ok(s) = statfs(cstr!("/")) {
|
||||||
let mut sfs: statfs = std::mem::zeroed();
|
s.filesystem_type() == FsType(RAMFS_MAGIC.as_()) || s.filesystem_type() == TMPFS_MAGIC
|
||||||
statfs(raw_cstr!("/"), &mut sfs);
|
} else {
|
||||||
sfs.f_type as u64 == RAMFS_MAGIC || sfs.f_type as c_long == TMPFS_MAGIC
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,23 +80,19 @@ impl MagiskInit {
|
|||||||
pub(crate) fn prepare_data(&self) {
|
pub(crate) fn prepare_data(&self) {
|
||||||
debug!("Setup data tmp");
|
debug!("Setup data tmp");
|
||||||
cstr!("/data").mkdir(0o755).log_ok();
|
cstr!("/data").mkdir(0o755).log_ok();
|
||||||
unsafe {
|
nix::mount::mount(
|
||||||
mount(
|
Some(cstr!("magisk")),
|
||||||
raw_cstr!("magisk"),
|
cstr!("/data"),
|
||||||
raw_cstr!("/data"),
|
Some(cstr!("tmpfs")),
|
||||||
raw_cstr!("tmpfs"),
|
MsFlags::empty(),
|
||||||
0,
|
Some(cstr!("mode=755")),
|
||||||
raw_cstr!("mode=755").cast(),
|
)
|
||||||
)
|
.check_os_err("mount", Some("/data"), Some("tmpfs"))
|
||||||
}
|
|
||||||
.check_err()
|
|
||||||
.log_ok();
|
.log_ok();
|
||||||
|
|
||||||
cstr!("/init").copy_to(cstr!("/data/magiskinit")).log_ok();
|
cstr!("/init").copy_to(cstr!("/data/magiskinit")).ok();
|
||||||
cstr!("/.backup").copy_to(cstr!("/data/.backup")).log_ok();
|
cstr!("/.backup").copy_to(cstr!("/data/.backup")).ok();
|
||||||
cstr!("/overlay.d")
|
cstr!("/overlay.d").copy_to(cstr!("/data/overlay.d")).ok();
|
||||||
.copy_to(cstr!("/data/overlay.d"))
|
|
||||||
.log_ok();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn exec_init(&mut self) {
|
pub(crate) fn exec_init(&mut self) {
|
||||||
@@ -106,10 +103,10 @@ impl MagiskInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
unsafe {
|
unsafe {
|
||||||
execve(raw_cstr!("/init"), self.argv.cast(), environ.cast())
|
libc::execve(raw_cstr!("/init"), self.argv.cast(), environ.cast())
|
||||||
.check_err()
|
.check_err()
|
||||||
.log_ok();
|
.log_ok();
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user