You've already forked ReZygisk
mirror of
https://github.com/PerformanC/ReZygisk.git
synced 2025-09-06 06:37:01 +00:00
several changes (#21)
* umount for ksu 10763 Signed-off-by: 5ec1cff <ewtqyqyewtqyqy@gmail.com> * Add crashdump sepolicy Signed-off-by: 5ec1cff <ewtqyqyewtqyqy@gmail.com> * Add more information about debug Signed-off-by: 5ec1cff <ewtqyqyewtqyqy@gmail.com> * daemonize zygiskd companion Signed-off-by: 5ec1cff <ewtqyqyewtqyqy@gmail.com> * create zygiskd if crash Signed-off-by: 5ec1cff <ewtqyqyewtqyqy@gmail.com> * injector: use ANDROID_DLEXT_USE_LIBRARY_FD to load module Signed-off-by: 5ec1cff <ewtqyqyewtqyqy@gmail.com> * zygiskd: use file as module fd instead of memfd on debug build Signed-off-by: 5ec1cff <ewtqyqyewtqyqy@gmail.com> * use OwnedFd Signed-off-by: 5ec1cff <ewtqyqyewtqyqy@gmail.com> * dlopen: no need to create ns Signed-off-by: 5ec1cff <ewtqyqyewtqyqy@gmail.com> --------- Signed-off-by: 5ec1cff <ewtqyqyewtqyqy@gmail.com>
This commit is contained in:
@@ -44,8 +44,17 @@ void* DlopenExt(const char* path, int flags) {
|
||||
return handle;
|
||||
}
|
||||
|
||||
void* DlopenMem(int memfd, int flags) {
|
||||
char path[PATH_MAX];
|
||||
sprintf(path, "/proc/self/fd/%d", memfd);
|
||||
return DlopenExt(path, flags);
|
||||
void* DlopenMem(int fd, int flags) {
|
||||
auto info = android_dlextinfo{
|
||||
.flags = ANDROID_DLEXT_USE_LIBRARY_FD,
|
||||
.library_fd = fd
|
||||
};
|
||||
|
||||
auto* handle = android_dlopen_ext("/jit-cache", flags, &info);
|
||||
if (handle) {
|
||||
LOGD("dlopen fd %d: %p", fd, handle);
|
||||
} else {
|
||||
LOGE("dlopen fd %d: %s", fd, dlerror());
|
||||
}
|
||||
return handle;
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ public:
|
||||
|
||||
UniqueFd(Fd fd) : fd_(fd) {}
|
||||
|
||||
~UniqueFd() { close(fd_); }
|
||||
~UniqueFd() { if (fd_ >= 0) close(fd_); }
|
||||
|
||||
// Disallow copy
|
||||
UniqueFd(const UniqueFd&) = delete;
|
||||
|
||||
@@ -45,8 +45,8 @@ androidComponents.onVariants { variant ->
|
||||
include("module.prop")
|
||||
expand(
|
||||
"moduleId" to moduleId,
|
||||
"moduleName" to moduleName,
|
||||
"versionName" to "$verName ($verCode)",
|
||||
"moduleName" to "$moduleName-$variantCapped",
|
||||
"versionName" to "$verName ($verCode)-($variantCapped)",
|
||||
"versionCode" to verCode,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -80,6 +80,11 @@ extract "$ZIPFILE" 'customize.sh' "$TMPDIR/.vunzip"
|
||||
extract "$ZIPFILE" 'verify.sh' "$TMPDIR/.vunzip"
|
||||
extract "$ZIPFILE" 'sepolicy.rule' "$TMPDIR"
|
||||
|
||||
if [ "$DEBUG" = true ]; then
|
||||
ui_print "- Add debug SELinux policy"
|
||||
echo "allow crash_dump adb_data_file dir search" >> "$TMPDIR/sepolicy.rule"
|
||||
fi
|
||||
|
||||
if [ "$KSU" ]; then
|
||||
ui_print "- Checking SELinux patches"
|
||||
if ! check_sepolicy "$TMPDIR/sepolicy.rule"; then
|
||||
|
||||
@@ -14,7 +14,7 @@ konst = "0.3.4"
|
||||
lazy_static = "1.4.0"
|
||||
log = "0.4.17"
|
||||
memfd = "0.6.2"
|
||||
nix = "0.26.2"
|
||||
nix = { version = "0.26.2", features = ["process","poll"] }
|
||||
num_enum = "0.5.9"
|
||||
once_cell = "1.17.1"
|
||||
passfd = "0.1.5"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use anyhow::Result;
|
||||
use anyhow::{bail, ensure, Result};
|
||||
use nix::unistd::gettid;
|
||||
use std::{fs, io::{Read, Write}, os::unix::net::UnixStream, process::Command};
|
||||
use std::ffi::c_char;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::constants::DaemonSocketAction;
|
||||
use crate::utils::UnixStreamExt;
|
||||
use crate::utils::{UnixStreamExt};
|
||||
use crate::{constants, debug_select, lp_select, magic, root_impl, utils};
|
||||
use anyhow::{bail, Result};
|
||||
use anyhow::{bail, ensure, Result};
|
||||
use memfd::Memfd;
|
||||
use nix::{
|
||||
fcntl::{fcntl, FcntlArg, FdFlag},
|
||||
@@ -11,6 +11,7 @@ use passfd::FdPassingExt;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::thread;
|
||||
use std::fs;
|
||||
use std::os::fd::{IntoRawFd, OwnedFd, RawFd};
|
||||
use std::os::unix::{
|
||||
net::{UnixListener, UnixStream},
|
||||
prelude::AsRawFd,
|
||||
@@ -18,10 +19,13 @@ use std::os::unix::{
|
||||
use std::os::unix::process::CommandExt;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
use nix::poll::{poll, PollFd, PollFlags};
|
||||
use nix::sys::wait::{waitpid, WaitStatus};
|
||||
use nix::unistd::{fork, ForkResult};
|
||||
|
||||
struct Module {
|
||||
name: String,
|
||||
memfd: Memfd,
|
||||
memfd: OwnedFd,
|
||||
companion: Mutex<Option<UnixStream>>,
|
||||
}
|
||||
|
||||
@@ -91,32 +95,30 @@ fn load_modules(arch: &str) -> Result<Vec<Module>> {
|
||||
continue;
|
||||
}
|
||||
log::info!(" Loading module `{name}`...");
|
||||
let memfd = match create_memfd(&so_path, &name) {
|
||||
Ok(memfd) => memfd,
|
||||
let fd = match create_library_fd(&so_path) {
|
||||
Ok(fd) => fd,
|
||||
Err(e) => {
|
||||
log::warn!(" Failed to create memfd for `{name}`: {e}");
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let companion = match spawn_companion(&name, &memfd) {
|
||||
Ok(companion) => companion,
|
||||
Err(e) => {
|
||||
log::warn!(" Failed to spawn companion for `{name}`: {e}");
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
let companion = Mutex::new(companion);
|
||||
let module = Module { name, memfd, companion };
|
||||
let companion = Mutex::new(None);
|
||||
let module = Module { name, memfd: fd, companion };
|
||||
modules.push(module);
|
||||
}
|
||||
|
||||
Ok(modules)
|
||||
}
|
||||
|
||||
fn create_memfd(so_path: &PathBuf, debug_name: &str) -> Result<Memfd> {
|
||||
#[cfg(debug_assertions)]
|
||||
fn create_library_fd(so_path: &PathBuf) -> Result<OwnedFd> {
|
||||
Ok(OwnedFd::from(fs::File::open(so_path)?))
|
||||
}
|
||||
|
||||
#[cfg(not(debug_assertions))]
|
||||
fn create_library_fd(so_path: &PathBuf) -> Result<OwnedFd> {
|
||||
let opts = memfd::MemfdOptions::default().allow_sealing(true);
|
||||
let memfd = opts.create(debug_select!(debug_name, "jit-cache"))?;
|
||||
let memfd = opts.create("jit-cache")?;
|
||||
let file = fs::File::open(so_path)?;
|
||||
let mut reader = std::io::BufReader::new(file);
|
||||
let mut writer = memfd.as_file();
|
||||
@@ -129,7 +131,7 @@ fn create_memfd(so_path: &PathBuf, debug_name: &str) -> Result<Memfd> {
|
||||
seals.insert(memfd::FileSeal::SealSeal);
|
||||
memfd.add_seals(&seals)?;
|
||||
|
||||
Ok(memfd)
|
||||
Ok(OwnedFd::from(memfd.into_file()))
|
||||
}
|
||||
|
||||
fn create_daemon_socket() -> Result<UnixListener> {
|
||||
@@ -141,22 +143,36 @@ fn create_daemon_socket() -> Result<UnixListener> {
|
||||
Ok(listener)
|
||||
}
|
||||
|
||||
fn spawn_companion(name: &str, memfd: &Memfd) -> Result<Option<UnixStream>> {
|
||||
fn spawn_companion(name: &str, fd: &RawFd) -> Result<Option<UnixStream>> {
|
||||
let (mut daemon, companion) = UnixStream::pair()?;
|
||||
// Remove FD_CLOEXEC flag
|
||||
fcntl(companion.as_raw_fd(), FcntlArg::F_SETFD(FdFlag::empty()))?;
|
||||
|
||||
let process = std::env::args().next().unwrap();
|
||||
let nice_name = process.split('/').last().unwrap();
|
||||
Command::new(&process)
|
||||
.arg0(format!("{}-{}", nice_name, name))
|
||||
.arg("companion")
|
||||
.arg(format!("{}", companion.as_raw_fd()))
|
||||
.spawn()?;
|
||||
drop(companion);
|
||||
|
||||
match unsafe { fork()? } {
|
||||
ForkResult::Parent { child, ..} => {
|
||||
if let Ok(WaitStatus::Exited(.., code)) = waitpid(child, None) {
|
||||
ensure!(code == 0, format!("process exited with {code}"));
|
||||
} else {
|
||||
bail!("process exited abnormally");
|
||||
}
|
||||
}
|
||||
ForkResult::Child => {
|
||||
Command::new(&process)
|
||||
.arg0(format!("{}-{}", nice_name, name))
|
||||
.arg("companion")
|
||||
.arg(format!("{}", companion.as_raw_fd()))
|
||||
.spawn()?;
|
||||
drop(companion);
|
||||
|
||||
std::process::exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
daemon.write_string(name)?;
|
||||
daemon.send_fd(memfd.as_raw_fd())?;
|
||||
daemon.send_fd(*fd)?;
|
||||
match daemon.read_u8()? {
|
||||
0 => Ok(None),
|
||||
1 => Ok(Some(daemon)),
|
||||
@@ -213,12 +229,33 @@ fn handle_daemon_action(mut stream: UnixStream, context: &Context) -> Result<()>
|
||||
DaemonSocketAction::RequestCompanionSocket => {
|
||||
let index = stream.read_usize()?;
|
||||
let module = &context.modules[index];
|
||||
let name = &module.name;
|
||||
let fd = &module.memfd;
|
||||
let mut companion = module.companion.lock().unwrap();
|
||||
if let Some(sock) = companion.as_ref() {
|
||||
let mut pfds = [PollFd::new(sock.as_raw_fd(), PollFlags::empty())];
|
||||
poll(&mut pfds, 0)?;
|
||||
if !pfds[0].revents().unwrap().is_empty() {
|
||||
log::error!("poll companion for module `{}` crashed", name);
|
||||
companion.take();
|
||||
}
|
||||
}
|
||||
if companion.as_ref().is_none() {
|
||||
match spawn_companion(&name, &fd.as_raw_fd()) {
|
||||
Ok(c) => {
|
||||
log::trace!(" spawned companion for `{name}`");
|
||||
*companion = c;
|
||||
},
|
||||
Err(e) => {
|
||||
log::warn!(" Failed to spawn companion for `{name}`: {e}");
|
||||
}
|
||||
};
|
||||
}
|
||||
match companion.as_ref() {
|
||||
Some(sock) => {
|
||||
if let Err(_) = sock.send_fd(stream.as_raw_fd()) {
|
||||
log::error!("Companion of module `{}` crashed", module.name);
|
||||
companion.take();
|
||||
log::error!("Companion socket of module `{}` missing", module.name);
|
||||
|
||||
stream.write_u8(0)?;
|
||||
}
|
||||
// Ok: Send by companion
|
||||
|
||||
Reference in New Issue
Block a user