Skip to content

Commit

Permalink
Use rustix to replace nix
Browse files Browse the repository at this point in the history
  • Loading branch information
Dr-TSNG committed Oct 18, 2023
1 parent e730ccd commit 2b41a83
Show file tree
Hide file tree
Showing 7 changed files with 36 additions and 57 deletions.
4 changes: 2 additions & 2 deletions zygiskd/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
Expand Down
1 change: 0 additions & 1 deletion zygiskd/src/dl.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down
1 change: 1 addition & 0 deletions zygiskd/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#![feature(exclusive_range_pattern)]
#![allow(dead_code)]

mod constants;
Expand Down
10 changes: 4 additions & 6 deletions zygiskd/src/root_impl/kernelsu.rs
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -17,7 +15,7 @@ pub enum Version {
pub fn get_kernel_su() -> Option<Version> {
let mut version = 0;
unsafe {
prctl(
libc::prctl(
KERNEL_SU_OPTION as i32,
CMD_GET_VERSION,
&mut version as *mut i32,
Expand All @@ -28,7 +26,7 @@ pub fn get_kernel_su() -> Option<Version> {
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),
}
}
Expand All @@ -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,
Expand All @@ -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,
Expand Down
25 changes: 11 additions & 14 deletions zygiskd/src/utils.rs
Original file line number Diff line number Diff line change
@@ -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]
Expand All @@ -31,12 +30,12 @@ macro_rules! debug_select {
}

pub struct LateInit<T> {
cell: OnceCell<T>,
cell: OnceLock<T>,
}

impl<T> LateInit<T> {
pub const fn new() -> Self {
LateInit { cell: OnceCell::new() }
LateInit { cell: OnceLock::new() }
}

pub fn init(&self, value: T) {
Expand All @@ -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(())
}
Expand Down Expand Up @@ -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<UnixListener> {
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" {
Expand Down
32 changes: 9 additions & 23 deletions zygiskd/src/watchdog.rs
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -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");
}

Expand Down Expand Up @@ -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=") {
Expand All @@ -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(())
}

Expand Down Expand Up @@ -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;
Expand Down
20 changes: 9 additions & 11 deletions zygiskd/src/zygiskd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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}");
Expand Down Expand Up @@ -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);
}
}
}
Expand Down

0 comments on commit 2b41a83

Please sign in to comment.