You've already forked ZygiskNext
mirror of
https://github.com/Dr-TSNG/ZygiskNext.git
synced 2025-08-27 23:46:34 +00:00
161 lines
4.5 KiB
Rust
161 lines
4.5 KiB
Rust
use anyhow::Result;
|
|
use std::{fs, io::{Read, Write}, os::unix::net::UnixStream};
|
|
use std::ffi::{c_char, CStr, CString};
|
|
use std::os::unix::net::UnixListener;
|
|
use std::process::Command;
|
|
use std::sync::OnceLock;
|
|
use rustix::net::{AddressFamily, bind_unix, listen, socket, SocketAddrUnix, SocketType};
|
|
use rustix::thread::gettid;
|
|
|
|
#[cfg(debug_assertions)]
|
|
#[macro_export]
|
|
macro_rules! debug_select {
|
|
($debug:expr, $release:expr) => { $debug };
|
|
}
|
|
#[cfg(not(debug_assertions))]
|
|
#[macro_export]
|
|
macro_rules! debug_select {
|
|
($debug:expr, $release:expr) => { $release };
|
|
}
|
|
|
|
pub struct LateInit<T> {
|
|
cell: OnceLock<T>,
|
|
}
|
|
|
|
impl<T> LateInit<T> {
|
|
pub const fn new() -> Self {
|
|
LateInit { cell: OnceLock::new() }
|
|
}
|
|
|
|
pub fn init(&self, value: T) {
|
|
assert!(self.cell.set(value).is_ok())
|
|
}
|
|
}
|
|
|
|
impl<T> std::ops::Deref for LateInit<T> {
|
|
type Target = T;
|
|
fn deref(&self) -> &T {
|
|
self.cell.get().unwrap()
|
|
}
|
|
}
|
|
|
|
pub fn set_socket_create_context(context: &str) -> Result<()> {
|
|
let path = "/proc/thread-self/attr/sockcreate";
|
|
match fs::write(path, context) {
|
|
Ok(_) => Ok(()),
|
|
Err(_) => {
|
|
let path = format!("/proc/self/task/{}/attr/sockcreate", gettid().as_raw_nonzero());
|
|
fs::write(path, context)?;
|
|
Ok(())
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn chcon(path: &str, context: &str) -> Result<()> {
|
|
Command::new("chcon").arg(context).arg(path).status()?;
|
|
Ok(())
|
|
}
|
|
|
|
pub fn log_raw(level: i32, tag: &str, message: &str) -> Result<()> {
|
|
let tag = CString::new(tag)?;
|
|
let message = CString::new(message)?;
|
|
unsafe {
|
|
__android_log_print(level, tag.as_ptr(), message.as_ptr());
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
pub fn get_property(name: &str) -> Result<String> {
|
|
let name = CString::new(name)?;
|
|
let mut buf = vec![0u8; 92];
|
|
let prop = unsafe {
|
|
__system_property_get(name.as_ptr(), buf.as_mut_ptr() as *mut c_char);
|
|
CStr::from_bytes_until_nul(&buf)?
|
|
};
|
|
Ok(prop.to_string_lossy().to_string())
|
|
}
|
|
|
|
pub fn set_property(name: &str, value: &str) -> Result<()> {
|
|
let name = CString::new(name)?;
|
|
let value = CString::new(value)?;
|
|
unsafe {
|
|
__system_property_set(name.as_ptr(), value.as_ptr());
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
pub trait UnixStreamExt {
|
|
fn read_u8(&mut self) -> Result<u8>;
|
|
fn read_u32(&mut self) -> Result<u32>;
|
|
fn read_usize(&mut self) -> Result<usize>;
|
|
fn read_string(&mut self) -> Result<String>;
|
|
fn write_u8(&mut self, value: u8) -> Result<()>;
|
|
fn write_u32(&mut self, value: u32) -> Result<()>;
|
|
fn write_usize(&mut self, value: usize) -> Result<()>;
|
|
fn write_string(&mut self, value: &str) -> Result<()>;
|
|
}
|
|
|
|
impl UnixStreamExt for UnixStream {
|
|
fn read_u8(&mut self) -> Result<u8> {
|
|
let mut buf = [0u8; 1];
|
|
self.read_exact(&mut buf)?;
|
|
Ok(buf[0])
|
|
}
|
|
|
|
fn read_u32(&mut self) -> Result<u32> {
|
|
let mut buf = [0u8; 4];
|
|
self.read_exact(&mut buf)?;
|
|
Ok(u32::from_ne_bytes(buf))
|
|
}
|
|
|
|
fn read_usize(&mut self) -> Result<usize> {
|
|
let mut buf = [0u8; std::mem::size_of::<usize>()];
|
|
self.read_exact(&mut buf)?;
|
|
Ok(usize::from_ne_bytes(buf))
|
|
}
|
|
|
|
fn read_string(&mut self) -> Result<String> {
|
|
let len = self.read_usize()?;
|
|
let mut buf = vec![0u8; len];
|
|
self.read_exact(&mut buf)?;
|
|
Ok(String::from_utf8(buf)?)
|
|
}
|
|
|
|
fn write_u8(&mut self, value: u8) -> Result<()> {
|
|
self.write_all(&value.to_ne_bytes())?;
|
|
Ok(())
|
|
}
|
|
|
|
fn write_u32(&mut self, value: u32) -> Result<()> {
|
|
self.write_all(&value.to_ne_bytes())?;
|
|
Ok(())
|
|
}
|
|
|
|
fn write_usize(&mut self, value: usize) -> Result<()> {
|
|
self.write_all(&value.to_ne_bytes())?;
|
|
Ok(())
|
|
}
|
|
|
|
fn write_string(&mut self, value: &str) -> Result<()> {
|
|
self.write_usize(value.len())?;
|
|
self.write_all(value.as_bytes())?;
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
pub fn unix_listener_from_path(path: &str) -> Result<UnixListener> {
|
|
let _ = fs::remove_file(path);
|
|
let addr = SocketAddrUnix::new(path)?;
|
|
let socket = socket(AddressFamily::UNIX, SocketType::STREAM, None)?;
|
|
bind_unix(&socket, &addr)?;
|
|
listen(&socket, 2)?;
|
|
chcon(path, "u:object_r:magisk_file:s0")?;
|
|
Ok(UnixListener::from(socket))
|
|
}
|
|
|
|
extern "C" {
|
|
fn __android_log_print(prio: i32, tag: *const c_char, fmt: *const c_char, ...) -> i32;
|
|
fn __system_property_get(name: *const c_char, value: *mut c_char) -> u32;
|
|
fn __system_property_set(name: *const c_char, value: *const c_char) -> u32;
|
|
}
|