You've already forked ReZygisk
mirror of
https://github.com/PerformanC/ReZygisk.git
synced 2025-09-06 06:37:01 +00:00
WIP
This commit is contained in:
@@ -20,7 +20,7 @@ num_enum = "0.5"
|
||||
passfd = "0.1"
|
||||
proc-maps = "0.3"
|
||||
|
||||
rustix = { version = "0.38", features = [ "fs", "process", "mount", "net", "thread"] }
|
||||
rustix = { version = "0.38", features = [ "fs", "process", "mount", "net", "thread" ] }
|
||||
tokio = { version = "1.28", features = ["full"] }
|
||||
|
||||
[profile.release]
|
||||
|
||||
@@ -16,19 +16,20 @@ pub const MAX_LOG_LEVEL: LevelFilter = LevelFilter::Trace;
|
||||
pub const MAX_LOG_LEVEL: LevelFilter = LevelFilter::Info;
|
||||
|
||||
pub const PROP_CTL_RESTART: &str = "ctl.restart";
|
||||
pub const PROP_CTL_SIGSTOP_OFF: &str = "ctl.sigstop_off";
|
||||
|
||||
pub const PATH_PCL: &str = "/system/etc/preloaded-classes";
|
||||
pub const PATH_ZYGISK_LIB: &str = concatcp!(lp_select!("/system/lib", "/system/lib64"), "/libzygisk.so");
|
||||
pub const PATH_WORK_DIR: &str = "/dev/zygisk"; // TODO: Replace with /debug_ramdisk/zygisk
|
||||
pub const PATH_PROP_OVERLAY: &str = concatcp!(PATH_WORK_DIR, "/module.prop");
|
||||
pub const PATH_CP_SOCKET: &str = concatcp!(PATH_WORK_DIR, lp_select!("/cp32.sock", "/cp64.sock"));
|
||||
pub const PATH_PT_LOCK32: &str = concatcp!(PATH_WORK_DIR, "/lock32");
|
||||
pub const PATH_PT_LOCK64: &str = concatcp!(PATH_WORK_DIR, "/lock64");
|
||||
|
||||
pub const PATH_MODULES_DIR: &str = "..";
|
||||
pub const PATH_MODULE_PROP: &str = "module.prop";
|
||||
pub const PATH_CP_BIN32: &str = "bin/zygisk-cp32";
|
||||
pub const PATH_CP_BIN64: &str = "bin/zygisk-cp64";
|
||||
pub const PATH_PTRACE_BIN32: &str = "bin/zygisk-ptrace32";
|
||||
pub const PATH_PTRACE_BIN64: &str = "bin/zygisk-ptrace64";
|
||||
pub const PATH_PT_BIN32: &str = "bin/zygisk-ptracer32";
|
||||
pub const PATH_PT_BIN64: &str = "bin/zygisk-ptracer64";
|
||||
|
||||
|
||||
pub const STATUS_LOADED: &str = "😋 Zygisk Next is loaded";
|
||||
@@ -47,6 +48,7 @@ pub enum DaemonSocketAction {
|
||||
ReadModules,
|
||||
RequestCompanionSocket,
|
||||
GetModuleDir,
|
||||
ZygoteRestarted,
|
||||
}
|
||||
|
||||
// Zygisk process flags
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use anyhow::Result;
|
||||
use std::{fs, io::{Read, Write}, os::unix::net::UnixStream};
|
||||
use std::ffi::{c_char, CStr, CString};
|
||||
use std::ffi::{c_char, c_void, CStr, CString};
|
||||
use std::os::fd::AsFd;
|
||||
use std::os::unix::net::UnixListener;
|
||||
use std::process::Command;
|
||||
@@ -177,4 +177,6 @@ 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;
|
||||
fn __system_property_find(name: *const c_char) -> *const c_void;
|
||||
fn __system_property_wait(info: *const c_void, old_serial: u32, new_serial: *u32, timeout: *const libc::timespec) -> bool;
|
||||
}
|
||||
|
||||
@@ -3,13 +3,18 @@ use anyhow::{bail, Result};
|
||||
use std::fs;
|
||||
use std::future::Future;
|
||||
use std::io::{BufRead, BufReader, Write};
|
||||
use std::os::fd::AsRawFd;
|
||||
use std::path::Path;
|
||||
use std::pin::Pin;
|
||||
use futures::stream::FuturesUnordered;
|
||||
use futures::StreamExt;
|
||||
use futures::{FutureExt, pin_mut, select, StreamExt};
|
||||
use futures::future::Fuse;
|
||||
use log::{debug, error, info};
|
||||
use rustix::mount::mount_bind;
|
||||
use rustix::process::{getgid, getuid, kill_process, Pid, Signal};
|
||||
use tokio::process::{Child, Command};
|
||||
use tokio::task;
|
||||
use tokio::task::JoinHandle;
|
||||
use crate::utils::LateInit;
|
||||
|
||||
static PROP_SECTIONS: LateInit<[String; 2]> = LateInit::new();
|
||||
@@ -105,16 +110,72 @@ fn check_and_set_hint() -> Result<bool> {
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
fn wait_for_ptrace(is_32bit: bool) -> Option<JoinHandle<Result<()>>> {
|
||||
let lock_path = if is_32bit {
|
||||
if !Path::new(constants::PATH_PT_BIN32).is_file() {
|
||||
return None
|
||||
}
|
||||
constants::PATH_PT_LOCK32
|
||||
} else {
|
||||
if !Path::new(constants::PATH_PT_BIN64).is_file() {
|
||||
return None
|
||||
}
|
||||
constants::PATH_PT_LOCK64
|
||||
};
|
||||
info!("wait for ptrace 32={}", is_32bit);
|
||||
Some(task::spawn_blocking(move || -> Result<()> {
|
||||
let file = match fs::OpenOptions::new().write(true).open(lock_path) {
|
||||
Ok(f) => f,
|
||||
Err(e) => {
|
||||
bail!("failed to open lock: {}", e)
|
||||
}
|
||||
};
|
||||
unsafe {
|
||||
let lock = libc::flock {
|
||||
l_type: libc::F_WRLCK as libc::c_short,
|
||||
l_whence: libc::SEEK_SET as libc::c_short,
|
||||
l_start: 0,
|
||||
l_len: 0,
|
||||
l_pid: 0,
|
||||
};
|
||||
loop {
|
||||
if libc::fcntl(file.as_raw_fd(), libc::F_SETLKW, &lock) == 0 {
|
||||
bail!("file lock obtained")
|
||||
} else {
|
||||
let errno = *libc::__errno();
|
||||
match errno {
|
||||
libc::EINTR => continue,
|
||||
_ => {
|
||||
bail!("failed to wait on lock: {}", errno)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
async fn spawn_daemon() -> Result<()> {
|
||||
let mut lives = 5;
|
||||
let lock32 = match wait_for_ptrace(true) {
|
||||
Some(f) => f.fuse(),
|
||||
None => Fuse::terminated()
|
||||
};
|
||||
let lock64 = match wait_for_ptrace(false) {
|
||||
Some(f) => f.fuse(),
|
||||
None => Fuse::terminated()
|
||||
};
|
||||
pin_mut!(lock32, lock64);
|
||||
loop {
|
||||
let mut futures = FuturesUnordered::<Pin<Box<dyn Future<Output=Result<()>>>>>::new();
|
||||
let mut child_ids = vec![];
|
||||
let daemon32 = Command::new(constants::PATH_CP_BIN32).arg("daemon").spawn();
|
||||
let daemon64 = Command::new(constants::PATH_CP_BIN64).arg("daemon").spawn();
|
||||
async fn spawn_daemon(mut daemon: Child) -> Result<()> {
|
||||
let id = daemon.id().unwrap();
|
||||
let result = daemon.wait().await?;
|
||||
log::error!("Daemon process {} died: {}", daemon.id().unwrap(), result);
|
||||
// FIXME: we must not get id here
|
||||
log::error!("Daemon process {} died: {}", id, result);
|
||||
Ok(())
|
||||
}
|
||||
if let Ok(it) = daemon32 {
|
||||
@@ -126,8 +187,35 @@ async fn spawn_daemon() -> Result<()> {
|
||||
futures.push(Box::pin(spawn_daemon(it)));
|
||||
}
|
||||
|
||||
if let Err(e) = futures.next().await.unwrap() {
|
||||
error!("{}", e);
|
||||
let mut stop = false;
|
||||
|
||||
select! {
|
||||
l32 = lock32 => {
|
||||
if let Ok(Err(it)) = l32 {
|
||||
error!("wait on lock 32: {}", it);
|
||||
}
|
||||
error!("wait on lock 32");
|
||||
stop = true;
|
||||
},
|
||||
l64 = lock64 => {
|
||||
if let Ok(Err(it)) = l64 {
|
||||
error!("wait on lock 64: {}", it);
|
||||
}
|
||||
error!("wait on lock 64");
|
||||
stop = true;
|
||||
},
|
||||
res = futures.select_next_some() => {
|
||||
if let Err(it) = res {
|
||||
error!("wait on daemon: {}", it);
|
||||
}
|
||||
lives -= 1;
|
||||
if lives == 0 {
|
||||
error!("Too many crashes, abort");
|
||||
stop = true;
|
||||
}
|
||||
error!("wait on daemon");
|
||||
},
|
||||
complete => panic!("completed unexpectedly")
|
||||
}
|
||||
|
||||
for child in child_ids {
|
||||
@@ -135,12 +223,14 @@ async fn spawn_daemon() -> Result<()> {
|
||||
let _ = kill_process(Pid::from_raw(child as i32).unwrap(), Signal::Kill);
|
||||
}
|
||||
|
||||
lives -= 1;
|
||||
if lives == 0 {
|
||||
bail!("Too many crashes, abort");
|
||||
if stop {
|
||||
utils::set_property(constants::PROP_CTL_SIGSTOP_OFF, "zygote")?;
|
||||
utils::set_property(constants::PROP_CTL_SIGSTOP_OFF, "zygote_secondary")?;
|
||||
}
|
||||
|
||||
error!("Restarting zygote...");
|
||||
utils::set_property(constants::PROP_CTL_RESTART, "zygote")?;
|
||||
if stop {
|
||||
bail!("Injecting failed or crashed too much times, Resetting ...");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@ use std::os::unix::{
|
||||
prelude::AsRawFd,
|
||||
};
|
||||
use std::path::PathBuf;
|
||||
use std::process::exit;
|
||||
use log::info;
|
||||
use rustix::fs::fstat;
|
||||
use rustix::process::{set_parent_process_death_signal, Signal};
|
||||
|
||||
@@ -223,6 +225,10 @@ fn handle_daemon_action(mut stream: UnixStream, context: &Context) -> Result<()>
|
||||
let dir = fs::File::open(dir)?;
|
||||
stream.send_fd(dir.as_raw_fd())?;
|
||||
}
|
||||
DaemonSocketAction::ZygoteRestarted => {
|
||||
info!("zygote restarted, exit");
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user