From 2b41a8336ceec5ac6a264316b37e99c00797c0b2 Mon Sep 17 00:00:00 2001 From: Nullptr Date: Thu, 19 Oct 2023 01:23:45 +0800 Subject: [PATCH] Use rustix to replace nix --- zygiskd/Cargo.toml | 4 ++-- zygiskd/src/dl.rs | 1 - zygiskd/src/main.rs | 1 + zygiskd/src/root_impl/kernelsu.rs | 10 ++++------ zygiskd/src/utils.rs | 25 +++++++++++------------- zygiskd/src/watchdog.rs | 32 +++++++++---------------------- zygiskd/src/zygiskd.rs | 20 +++++++++---------- 7 files changed, 36 insertions(+), 57 deletions(-) diff --git a/zygiskd/Cargo.toml b/zygiskd/Cargo.toml index a377a41..06b9ccd 100644 --- a/zygiskd/Cargo.toml +++ b/zygiskd/Cargo.toml @@ -14,13 +14,13 @@ const_format = "0.2" futures = "0.3" konst = "0.3" lazy_static = "1.4" +libc = "0.2" log = "0.4" memfd = "0.6" -nix = { version = "0.26", features = ["process","poll"] } num_enum = "0.5" -once_cell = "1.17" passfd = "0.1" rand = "0.8" +rustix = { version = "0.38", features = [ "fs", "process", "mount", "net", "thread"] } tokio = { version = "1.28", features = ["full"] } binder = { git = "https://github.com/Kernel-SU/binder_rs", rev = "c9f2b62d6a744fd2264056c638c1b061a6a2932d" } diff --git a/zygiskd/src/dl.rs b/zygiskd/src/dl.rs index f96f27d..dcc9d48 100644 --- a/zygiskd/src/dl.rs +++ b/zygiskd/src/dl.rs @@ -1,6 +1,5 @@ use anyhow::{bail, Result}; use std::ffi::{c_char, c_void}; -use nix::libc; const ANDROID_NAMESPACE_TYPE_SHARED: u64 = 0x2; const ANDROID_DLEXT_USE_NAMESPACE: u64 = 0x200; diff --git a/zygiskd/src/main.rs b/zygiskd/src/main.rs index 25fd53a..3ee2ae2 100644 --- a/zygiskd/src/main.rs +++ b/zygiskd/src/main.rs @@ -1,3 +1,4 @@ +#![feature(exclusive_range_pattern)] #![allow(dead_code)] mod constants; diff --git a/zygiskd/src/root_impl/kernelsu.rs b/zygiskd/src/root_impl/kernelsu.rs index 29e5860..3139314 100644 --- a/zygiskd/src/root_impl/kernelsu.rs +++ b/zygiskd/src/root_impl/kernelsu.rs @@ -1,6 +1,4 @@ use crate::constants::{MAX_KSU_VERSION, MIN_KSU_VERSION}; -use nix::libc; -use nix::libc::prctl; const KERNEL_SU_OPTION: u32 = 0xdeadbeefu32; @@ -17,7 +15,7 @@ pub enum Version { pub fn get_kernel_su() -> Option { let mut version = 0; unsafe { - prctl( + libc::prctl( KERNEL_SU_OPTION as i32, CMD_GET_VERSION, &mut version as *mut i32, @@ -28,7 +26,7 @@ pub fn get_kernel_su() -> Option { match version { 0 => None, MIN_KSU_VERSION..=MAX_KSU_VERSION => Some(Version::Supported), - 1..=MIN_KSU_VERSION => Some(Version::TooOld), + 1..MIN_KSU_VERSION => Some(Version::TooOld), _ => Some(Version::Abnormal), } } @@ -37,7 +35,7 @@ pub fn uid_granted_root(uid: i32) -> bool { let mut result: u32 = 0; let mut granted = false; unsafe { - prctl( + libc::prctl( KERNEL_SU_OPTION as i32, CMD_UID_GRANTED_ROOT, uid, @@ -55,7 +53,7 @@ pub fn uid_should_umount(uid: i32) -> bool { let mut result: u32 = 0; let mut umount = false; unsafe { - prctl( + libc::prctl( KERNEL_SU_OPTION as i32, CMD_UID_SHOULD_UMOUNT, uid, diff --git a/zygiskd/src/utils.rs b/zygiskd/src/utils.rs index ea43288..6354776 100644 --- a/zygiskd/src/utils.rs +++ b/zygiskd/src/utils.rs @@ -1,12 +1,11 @@ use anyhow::Result; -use nix::unistd::gettid; use std::{fs, io::{Read, Write}, os::unix::net::UnixStream, process::Command}; use std::ffi::c_char; -use std::os::fd::FromRawFd; use std::os::unix::net::UnixListener; -use nix::sys::socket::{AddressFamily, SockFlag, SockType, UnixAddr}; -use once_cell::sync::OnceCell; +use std::sync::OnceLock; use rand::distributions::{Alphanumeric, DistString}; +use rustix::net::{AddressFamily, bind_unix, listen, socket, SocketAddrUnix, SocketType}; +use rustix::thread::gettid; #[cfg(target_pointer_width = "64")] #[macro_export] @@ -31,12 +30,12 @@ macro_rules! debug_select { } pub struct LateInit { - cell: OnceCell, + cell: OnceLock, } impl LateInit { pub const fn new() -> Self { - LateInit { cell: OnceCell::new() } + LateInit { cell: OnceLock::new() } } pub fn init(&self, value: T) { @@ -60,7 +59,7 @@ pub fn set_socket_create_context(context: &str) -> Result<()> { match fs::write(path, context) { Ok(_) => Ok(()), Err(_) => { - let path = format!("/proc/self/task/{}/attr/sockcreate", gettid().as_raw()); + let path = format!("/proc/self/task/{}/attr/sockcreate", gettid().as_raw_nonzero()); fs::write(path, context)?; Ok(()) } @@ -156,14 +155,12 @@ impl UnixStreamExt for UnixStream { } } -// TODO: Replace with SockAddrExt::from_abstract_name when it's stable pub fn abstract_namespace_socket(name: &str) -> Result { - let addr = UnixAddr::new_abstract(name.as_bytes())?; - let socket = nix::sys::socket::socket(AddressFamily::Unix, SockType::Stream, SockFlag::empty(), None)?; - nix::sys::socket::bind(socket, &addr)?; - nix::sys::socket::listen(socket, 2)?; - let listener = unsafe { UnixListener::from_raw_fd(socket) }; - Ok(listener) + let addr = SocketAddrUnix::new_abstract_name(name.as_bytes())?; + let socket = socket(AddressFamily::UNIX, SocketType::STREAM, None)?; + bind_unix(&socket, &addr)?; + listen(&socket, 2)?; + Ok(UnixListener::from(socket)) } extern "C" { diff --git a/zygiskd/src/watchdog.rs b/zygiskd/src/watchdog.rs index ce3f7f5..62f478d 100644 --- a/zygiskd/src/watchdog.rs +++ b/zygiskd/src/watchdog.rs @@ -1,19 +1,16 @@ use crate::{constants, magic, root_impl, utils}; use anyhow::{bail, Result}; -use nix::unistd::{getgid, getuid, Pid}; -use std::{fs, io}; -use std::ffi::CString; +use std::fs; use std::future::Future; -use std::io::{BufRead, Write}; +use std::io::{BufRead, BufReader, Write}; use std::os::unix::net::UnixListener; use std::pin::Pin; use std::time::Duration; use binder::IBinder; use futures::stream::FuturesUnordered; use futures::StreamExt; -use nix::errno::Errno; -use nix::libc; -use nix::sys::signal::{kill, Signal}; +use rustix::mount::mount_bind; +use rustix::process::{getgid, getuid, kill_process, Pid, Signal}; use tokio::process::{Child, Command}; use crate::utils::LateInit; @@ -38,12 +35,12 @@ pub async fn entry() -> Result<()> { fn check_permission() -> Result<()> { log::info!("Check permission"); let uid = getuid(); - if uid.as_raw() != 0 { + if !uid.is_root() { bail!("UID is not 0"); } let gid = getgid(); - if gid.as_raw() != 0 { + if !gid.is_root() { bail!("GID is not 0"); } @@ -81,7 +78,7 @@ async fn mount_prop() -> Result<()> { let module_prop_file = fs::File::open(&module_prop)?; let mut section = 0; let mut sections: [String; 2] = [String::new(), String::new()]; - let lines = io::BufReader::new(module_prop_file).lines(); + let lines = BufReader::new(module_prop_file).lines(); for line in lines { let line = line?; if line.starts_with("description=") { @@ -99,18 +96,7 @@ async fn mount_prop() -> Result<()> { fs::create_dir(magic::PATH_TMP_DIR.as_str())?; fs::File::create(magic::PATH_TMP_PROP.as_str())?; - // FIXME: sys_mount cannot be compiled on 32 bit - unsafe { - let r = libc::mount( - CString::new(magic::PATH_TMP_PROP.as_str())?.as_ptr(), - CString::new(module_prop)?.as_ptr(), - std::ptr::null(), - libc::MS_BIND, - std::ptr::null(), - ); - Errno::result(r)?; - } - + mount_bind(magic::PATH_TMP_PROP.as_str(), &module_prop)?; Ok(()) } @@ -190,7 +176,7 @@ async fn spawn_daemon() -> Result<()> { for child in child_ids { log::debug!("Killing child process {}", child); - let _ = kill(Pid::from_raw(child as i32), Signal::SIGKILL); + let _ = kill_process(Pid::from_raw(child as i32).unwrap(), Signal::Kill); } lives -= 1; diff --git a/zygiskd/src/zygiskd.rs b/zygiskd/src/zygiskd.rs index 27dd4c4..184e92c 100644 --- a/zygiskd/src/zygiskd.rs +++ b/zygiskd/src/zygiskd.rs @@ -7,15 +7,14 @@ use passfd::FdPassingExt; use std::sync::Arc; use std::thread; use std::fs; -use std::os::fd::{IntoRawFd, OwnedFd}; +use std::os::fd::OwnedFd; use std::os::unix::{ net::{UnixListener, UnixStream}, prelude::AsRawFd, }; use std::path::PathBuf; -use nix::libc; -use nix::sys::stat::fstat; -use nix::unistd::close; +use rustix::fs::fstat; +use rustix::process::Signal; type ZygiskCompanionEntryFn = unsafe extern "C" fn(i32); @@ -31,7 +30,7 @@ struct Context { } pub fn entry() -> Result<()> { - unsafe { libc::prctl(libc::PR_SET_PDEATHSIG, libc::SIGKILL) }; + rustix::process::set_parent_process_death_signal(Some(Signal::Kill))?; let arch = get_arch()?; log::debug!("Daemon architecture: {arch}"); @@ -209,16 +208,15 @@ fn handle_daemon_action(mut stream: UnixStream, context: &Context) -> Result<()> } Some(companion) => { stream.write_u8(1)?; - let fd = stream.into_raw_fd(); - let st0 = fstat(fd)?; - unsafe { companion(fd); } + let st0 = fstat(&stream)?; + unsafe { companion(stream.as_raw_fd()); } // Only close client if it is the same file so we don't // accidentally close a re-used file descriptor. // This check is required because the module companion // handler could've closed the file descriptor already. - if let Ok(st1) = fstat(fd) { - if st0.st_dev == st1.st_dev && st0.st_ino == st1.st_ino { - close(fd)?; + if let Ok(st1) = fstat(&stream) { + if st0.st_dev != st1.st_dev || st0.st_ino != st1.st_ino { + std::mem::forget(stream); } } }