Merge pull request #1325 from tiann/rustix
This commit is contained in:
75
userspace/ksud/Cargo.lock
generated
75
userspace/ksud/Cargo.lock
generated
@@ -256,9 +256,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clang-sys"
|
||||
version = "1.4.0"
|
||||
version = "1.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa2e27ae6ab525c3d369ded447057bca5438d86dc3a68f6faafb8269ba82ebf3"
|
||||
checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1"
|
||||
dependencies = [
|
||||
"glob",
|
||||
"libc",
|
||||
@@ -853,15 +853,16 @@ dependencies = [
|
||||
"jwalk",
|
||||
"libc",
|
||||
"log",
|
||||
"loopdev",
|
||||
"nom",
|
||||
"procfs",
|
||||
"regex",
|
||||
"retry",
|
||||
"rust-embed",
|
||||
"rustix 0.38.30",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha256",
|
||||
"sys-mount",
|
||||
"tempdir",
|
||||
"which",
|
||||
"zip 0.6.4",
|
||||
@@ -908,12 +909,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
version = "0.7.4"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
|
||||
checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"winapi",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1376,8 +1377,10 @@ checksum = "322394588aaf33c24007e8bb3238ee3e4c5c09c084ab32bc73890b99ff326bca"
|
||||
dependencies = [
|
||||
"bitflags 2.4.1",
|
||||
"errno 0.3.8",
|
||||
"itoa",
|
||||
"libc",
|
||||
"linux-raw-sys 0.4.13",
|
||||
"once_cell",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
@@ -1456,20 +1459,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.1.0"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3"
|
||||
|
||||
[[package]]
|
||||
name = "smart-default"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "133659a15339456eeeb07572eb02a91c91e9815e9cbc89566944d2c8d3efdbf6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.107",
|
||||
]
|
||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
@@ -1505,19 +1497,6 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sys-mount"
|
||||
version = "2.0.2"
|
||||
source = "git+https://github.com/tiann/sys-mount?branch=loopfix#c7c4048e4a4ffdf8b108a85956363a75f2c554f0"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"libc",
|
||||
"loopdev",
|
||||
"smart-default",
|
||||
"thiserror",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tempdir"
|
||||
version = "0.3.7"
|
||||
@@ -1596,38 +1575,6 @@ dependencies = [
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing"
|
||||
version = "0.1.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"pin-project-lite",
|
||||
"tracing-attributes",
|
||||
"tracing-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-attributes"
|
||||
version = "0.1.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.107",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-core"
|
||||
version = "0.1.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.16.0"
|
||||
|
||||
@@ -39,10 +39,11 @@ chrono = "0.4"
|
||||
hole-punch = { git = "https://github.com/tiann/hole-punch" }
|
||||
|
||||
[target.'cfg(any(target_os = "android", target_os = "linux"))'.dependencies]
|
||||
sys-mount = { git = "https://github.com/tiann/sys-mount", branch = "loopfix" }
|
||||
rustix = { version = "0.38", features = ["all-apis"] }
|
||||
# some android specific dependencies which compiles under unix are also listed here for convenience of coding
|
||||
android-properties = { version = "0.2.2", features = ["bionic-deprecated"] }
|
||||
procfs = "0.16"
|
||||
loopdev = { git = "https://github.com/tiann/loopdev", branch = "loopfix" }
|
||||
|
||||
[target.'cfg(target_os = "android")'.dependencies]
|
||||
android_logger = "0.13"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use anyhow::{bail, Context, Result};
|
||||
use log::{info, warn};
|
||||
#[cfg(target_os = "android")]
|
||||
use std::path::PathBuf;
|
||||
use std::{collections::HashMap, path::Path};
|
||||
|
||||
|
||||
@@ -14,6 +14,12 @@ use crate::{
|
||||
utils::{self, umask},
|
||||
};
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
use rustix::{
|
||||
process::getuid,
|
||||
thread::{set_thread_res_gid, set_thread_res_uid, Gid, Uid},
|
||||
};
|
||||
|
||||
pub const KERNEL_SU_OPTION: u32 = 0xDEAD_BEEF;
|
||||
|
||||
const CMD_GRANT_ROOT: u64 = 0;
|
||||
@@ -65,8 +71,13 @@ fn set_identity(uid: u32, gid: u32, groups: &[u32]) {
|
||||
if !groups.is_empty() {
|
||||
libc::setgroups(groups.len(), groups.as_ptr());
|
||||
}
|
||||
libc::setresgid(gid, gid, gid);
|
||||
libc::setresuid(uid, uid, uid);
|
||||
}
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
{
|
||||
let gid = unsafe { Gid::from_raw(gid) };
|
||||
let uid = unsafe { Uid::from_raw(uid) };
|
||||
set_thread_res_gid(gid, gid, gid).ok();
|
||||
set_thread_res_uid(uid, uid, uid).ok();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,7 +214,7 @@ pub fn root_shell() -> Result<()> {
|
||||
}
|
||||
|
||||
// use current uid if no user specified, these has been done in kernel!
|
||||
let mut uid = unsafe { libc::getuid() };
|
||||
let mut uid = getuid().as_raw();
|
||||
if free_idx < matches.free.len() {
|
||||
let name = &matches.free[free_idx];
|
||||
uid = unsafe {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use anyhow::{bail, Ok, Result};
|
||||
use anyhow::{anyhow, bail, Ok, Result};
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
use anyhow::Context;
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
use retry::delay::NoDelay;
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
use sys_mount::{unmount, FilesystemType, Mount, MountFlags, Unmount, UnmountFlags};
|
||||
use rustix::{fd::AsFd, fs::CWD, mount::*};
|
||||
|
||||
use crate::defs::KSU_OVERLAY_SOURCE;
|
||||
use log::{info, warn};
|
||||
@@ -14,49 +14,32 @@ use procfs::process::Process;
|
||||
use std::path::Path;
|
||||
|
||||
pub struct AutoMountExt4 {
|
||||
mnt: String,
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
mount: Option<Mount>,
|
||||
target: String,
|
||||
auto_umount: bool,
|
||||
}
|
||||
|
||||
impl AutoMountExt4 {
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
pub fn try_new(src: &str, mnt: &str, auto_umount: bool) -> Result<Self> {
|
||||
let result = Mount::builder()
|
||||
.fstype(FilesystemType::from("ext4"))
|
||||
.flags(MountFlags::empty())
|
||||
.create_loop(true)
|
||||
.mount(src, mnt)
|
||||
.map(|mount| {
|
||||
pub fn try_new(source: &str, target: &str, auto_umount: bool) -> Result<Self> {
|
||||
let new_loopback = loopdev::LoopControl::open()?.next_free()?;
|
||||
new_loopback.with().attach(source)?;
|
||||
let lo = new_loopback.path().ok_or(anyhow!("no loop"))?;
|
||||
let fs = fsopen("ext4", FsOpenFlags::FSOPEN_CLOEXEC)?;
|
||||
let fs = fs.as_fd();
|
||||
fsconfig_set_string(fs, "source", lo)?;
|
||||
fsconfig_create(fs)?;
|
||||
let mount = fsmount(fs, FsMountFlags::FSMOUNT_CLOEXEC, MountAttrFlags::empty())?;
|
||||
move_mount(
|
||||
mount.as_fd(),
|
||||
"",
|
||||
CWD,
|
||||
target,
|
||||
MoveMountFlags::MOVE_MOUNT_F_EMPTY_PATH,
|
||||
)?;
|
||||
Ok(Self {
|
||||
mnt: mnt.to_string(),
|
||||
mount: Some(mount),
|
||||
target: target.to_string(),
|
||||
auto_umount,
|
||||
})
|
||||
});
|
||||
if let Err(e) = result {
|
||||
println!("- Mount failed: {e}, retry with system mount");
|
||||
let result = std::process::Command::new("mount")
|
||||
.arg("-t")
|
||||
.arg("ext4")
|
||||
.arg(src)
|
||||
.arg(mnt)
|
||||
.status();
|
||||
if let Err(e) = result {
|
||||
Err(anyhow::anyhow!(
|
||||
"mount partition: {src} -> {mnt} failed: {e}"
|
||||
))
|
||||
} else {
|
||||
Ok(Self {
|
||||
mnt: mnt.to_string(),
|
||||
mount: None,
|
||||
auto_umount,
|
||||
})
|
||||
}
|
||||
} else {
|
||||
result.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "linux", target_os = "android")))]
|
||||
@@ -66,27 +49,17 @@ impl AutoMountExt4 {
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
pub fn umount(&self) -> Result<()> {
|
||||
if let Some(ref mount) = self.mount {
|
||||
mount
|
||||
.unmount(UnmountFlags::empty())
|
||||
.map_err(|e| anyhow::anyhow!(e))
|
||||
} else {
|
||||
let result = std::process::Command::new("umount").arg(&self.mnt).status();
|
||||
if let Err(e) = result {
|
||||
Err(anyhow::anyhow!("umount: {} failed: {e}", self.mnt))
|
||||
} else {
|
||||
unmount(self.target.as_str(), UnmountFlags::DETACH)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
impl Drop for AutoMountExt4 {
|
||||
fn drop(&mut self) {
|
||||
log::info!(
|
||||
"AutoMountExt4 drop: {}, auto_umount: {}",
|
||||
self.mnt,
|
||||
self.target,
|
||||
self.auto_umount
|
||||
);
|
||||
if self.auto_umount {
|
||||
@@ -98,18 +71,7 @@ impl Drop for AutoMountExt4 {
|
||||
#[allow(dead_code)]
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
fn mount_image(src: &str, target: &str, autodrop: bool) -> Result<()> {
|
||||
if autodrop {
|
||||
Mount::builder()
|
||||
.fstype(FilesystemType::from("ext4"))
|
||||
.create_loop(true)
|
||||
.mount_autodrop(src, target, UnmountFlags::empty())
|
||||
.with_context(|| format!("Failed to do mount: {src} -> {target}"))?;
|
||||
} else {
|
||||
Mount::builder()
|
||||
.fstype(FilesystemType::from("ext4"))
|
||||
.mount(src, target)
|
||||
.with_context(|| format!("Failed to do mount: {src} -> {target}"))?;
|
||||
}
|
||||
AutoMountExt4::try_new(src, target, autodrop)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -146,28 +108,37 @@ fn mount_overlayfs(
|
||||
dest.as_ref().display(),
|
||||
options
|
||||
);
|
||||
Mount::builder()
|
||||
.fstype(FilesystemType::from("overlay"))
|
||||
.data(&options)
|
||||
.flags(MountFlags::RDONLY)
|
||||
.mount(KSU_OVERLAY_SOURCE, dest.as_ref())
|
||||
.with_context(|| {
|
||||
format!(
|
||||
"mount overlayfs on {} options {} failed",
|
||||
dest.as_ref().display(),
|
||||
options
|
||||
)
|
||||
})?;
|
||||
let fs = fsopen("overlay", FsOpenFlags::FSOPEN_CLOEXEC)?;
|
||||
let fs = fs.as_fd();
|
||||
fsconfig_set_string(fs, "lowerdir", lower_dirs.join(":"))?;
|
||||
fsconfig_set_string(fs, "source", KSU_OVERLAY_SOURCE)?;
|
||||
fsconfig_create(fs)?;
|
||||
let mount = fsmount(fs, FsMountFlags::FSMOUNT_CLOEXEC, MountAttrFlags::empty())?;
|
||||
move_mount(
|
||||
mount.as_fd(),
|
||||
"",
|
||||
CWD,
|
||||
dest.as_ref(),
|
||||
MoveMountFlags::MOVE_MOUNT_F_EMPTY_PATH,
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
pub fn mount_tmpfs(dest: impl AsRef<Path>) -> Result<()> {
|
||||
info!("mount tmpfs on {}", dest.as_ref().display());
|
||||
Mount::builder()
|
||||
.fstype(FilesystemType::from("tmpfs"))
|
||||
.mount(KSU_OVERLAY_SOURCE, dest.as_ref())
|
||||
.with_context(|| format!("mount tmpfs on {} failed", dest.as_ref().display()))?;
|
||||
let fs = fsopen("tmpfs", FsOpenFlags::FSOPEN_CLOEXEC)?;
|
||||
let fs = fs.as_fd();
|
||||
fsconfig_set_string(fs, "source", KSU_OVERLAY_SOURCE)?;
|
||||
fsconfig_create(fs)?;
|
||||
let mount = fsmount(fs, FsMountFlags::FSMOUNT_CLOEXEC, MountAttrFlags::empty())?;
|
||||
move_mount(
|
||||
mount.as_fd(),
|
||||
"",
|
||||
CWD,
|
||||
dest.as_ref(),
|
||||
MoveMountFlags::MOVE_MOUNT_F_EMPTY_PATH,
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -178,16 +149,12 @@ fn bind_mount(from: impl AsRef<Path>, to: impl AsRef<Path>) -> Result<()> {
|
||||
from.as_ref().display(),
|
||||
to.as_ref().display()
|
||||
);
|
||||
Mount::builder()
|
||||
.flags(MountFlags::BIND)
|
||||
.mount(from.as_ref(), to.as_ref())
|
||||
.with_context(|| {
|
||||
format!(
|
||||
"bind mount failed: {} -> {}",
|
||||
from.as_ref().display(),
|
||||
to.as_ref().display()
|
||||
)
|
||||
})?;
|
||||
let tree = open_tree(
|
||||
CWD,
|
||||
from.as_ref(),
|
||||
OpenTreeFlags::OPEN_TREE_CLOEXEC | OpenTreeFlags::OPEN_TREE_CLONE,
|
||||
)?;
|
||||
move_mount(tree.as_fd(), "", CWD, to.as_ref(), MoveMountFlags::empty())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,12 @@ use std::os::unix::prelude::PermissionsExt;
|
||||
use hole_punch::*;
|
||||
use std::io::{Read, Seek, SeekFrom};
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
use rustix::{
|
||||
process,
|
||||
thread::{move_into_link_name_space, unshare, LinkNameSpaceType, UnshareFlags},
|
||||
};
|
||||
|
||||
pub fn ensure_clean_dir(dir: &str) -> Result<()> {
|
||||
let path = Path::new(dir);
|
||||
log::debug!("ensure_clean_dir: {}", path.display());
|
||||
@@ -115,24 +121,23 @@ pub fn get_zip_uncompressed_size(zip_path: &str) -> Result<u64> {
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
pub fn switch_mnt_ns(pid: i32) -> Result<()> {
|
||||
use anyhow::ensure;
|
||||
use std::os::fd::AsRawFd;
|
||||
use rustix::{
|
||||
fd::AsFd,
|
||||
fs::{open, Mode, OFlags},
|
||||
};
|
||||
let path = format!("/proc/{pid}/ns/mnt");
|
||||
let fd = std::fs::File::open(path)?;
|
||||
let fd = open(path, OFlags::RDONLY, Mode::from_raw_mode(0))?;
|
||||
let current_dir = std::env::current_dir();
|
||||
let ret = unsafe { libc::setns(fd.as_raw_fd(), libc::CLONE_NEWNS) };
|
||||
move_into_link_name_space(fd.as_fd(), Some(LinkNameSpaceType::Mount))?;
|
||||
if let std::result::Result::Ok(current_dir) = current_dir {
|
||||
let _ = std::env::set_current_dir(current_dir);
|
||||
}
|
||||
ensure!(ret == 0, "switch mnt ns failed");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
pub fn unshare_mnt_ns() -> Result<()> {
|
||||
use anyhow::ensure;
|
||||
let ret = unsafe { libc::unshare(libc::CLONE_NEWNS) };
|
||||
ensure!(ret == 0, "unshare mnt ns failed");
|
||||
unshare(UnshareFlags::NEWNS)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -164,7 +169,7 @@ pub fn switch_cgroups() {
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
pub fn umask(mask: u32) {
|
||||
unsafe { libc::umask(mask) };
|
||||
process::umask(rustix::fs::Mode::from_raw_mode(mask));
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "linux", target_os = "android")))]
|
||||
|
||||
Reference in New Issue
Block a user