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;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* DlopenMem(int memfd, int flags) {
|
void* DlopenMem(int fd, int flags) {
|
||||||
char path[PATH_MAX];
|
auto info = android_dlextinfo{
|
||||||
sprintf(path, "/proc/self/fd/%d", memfd);
|
.flags = ANDROID_DLEXT_USE_LIBRARY_FD,
|
||||||
return DlopenExt(path, flags);
|
.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(Fd fd) : fd_(fd) {}
|
||||||
|
|
||||||
~UniqueFd() { close(fd_); }
|
~UniqueFd() { if (fd_ >= 0) close(fd_); }
|
||||||
|
|
||||||
// Disallow copy
|
// Disallow copy
|
||||||
UniqueFd(const UniqueFd&) = delete;
|
UniqueFd(const UniqueFd&) = delete;
|
||||||
|
|||||||
@@ -45,8 +45,8 @@ androidComponents.onVariants { variant ->
|
|||||||
include("module.prop")
|
include("module.prop")
|
||||||
expand(
|
expand(
|
||||||
"moduleId" to moduleId,
|
"moduleId" to moduleId,
|
||||||
"moduleName" to moduleName,
|
"moduleName" to "$moduleName-$variantCapped",
|
||||||
"versionName" to "$verName ($verCode)",
|
"versionName" to "$verName ($verCode)-($variantCapped)",
|
||||||
"versionCode" to verCode,
|
"versionCode" to verCode,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,6 +80,11 @@ extract "$ZIPFILE" 'customize.sh' "$TMPDIR/.vunzip"
|
|||||||
extract "$ZIPFILE" 'verify.sh' "$TMPDIR/.vunzip"
|
extract "$ZIPFILE" 'verify.sh' "$TMPDIR/.vunzip"
|
||||||
extract "$ZIPFILE" 'sepolicy.rule' "$TMPDIR"
|
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
|
if [ "$KSU" ]; then
|
||||||
ui_print "- Checking SELinux patches"
|
ui_print "- Checking SELinux patches"
|
||||||
if ! check_sepolicy "$TMPDIR/sepolicy.rule"; then
|
if ! check_sepolicy "$TMPDIR/sepolicy.rule"; then
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ konst = "0.3.4"
|
|||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
memfd = "0.6.2"
|
memfd = "0.6.2"
|
||||||
nix = "0.26.2"
|
nix = { version = "0.26.2", features = ["process","poll"] }
|
||||||
num_enum = "0.5.9"
|
num_enum = "0.5.9"
|
||||||
once_cell = "1.17.1"
|
once_cell = "1.17.1"
|
||||||
passfd = "0.1.5"
|
passfd = "0.1.5"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use anyhow::Result;
|
use anyhow::{bail, ensure, Result};
|
||||||
use nix::unistd::gettid;
|
use nix::unistd::gettid;
|
||||||
use std::{fs, io::{Read, Write}, os::unix::net::UnixStream, process::Command};
|
use std::{fs, io::{Read, Write}, os::unix::net::UnixStream, process::Command};
|
||||||
use std::ffi::c_char;
|
use std::ffi::c_char;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use crate::constants::DaemonSocketAction;
|
use crate::constants::DaemonSocketAction;
|
||||||
use crate::utils::UnixStreamExt;
|
use crate::utils::{UnixStreamExt};
|
||||||
use crate::{constants, debug_select, lp_select, magic, root_impl, utils};
|
use crate::{constants, debug_select, lp_select, magic, root_impl, utils};
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, ensure, Result};
|
||||||
use memfd::Memfd;
|
use memfd::Memfd;
|
||||||
use nix::{
|
use nix::{
|
||||||
fcntl::{fcntl, FcntlArg, FdFlag},
|
fcntl::{fcntl, FcntlArg, FdFlag},
|
||||||
@@ -11,6 +11,7 @@ use passfd::FdPassingExt;
|
|||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
use std::os::fd::{IntoRawFd, OwnedFd, RawFd};
|
||||||
use std::os::unix::{
|
use std::os::unix::{
|
||||||
net::{UnixListener, UnixStream},
|
net::{UnixListener, UnixStream},
|
||||||
prelude::AsRawFd,
|
prelude::AsRawFd,
|
||||||
@@ -18,10 +19,13 @@ use std::os::unix::{
|
|||||||
use std::os::unix::process::CommandExt;
|
use std::os::unix::process::CommandExt;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
use nix::poll::{poll, PollFd, PollFlags};
|
||||||
|
use nix::sys::wait::{waitpid, WaitStatus};
|
||||||
|
use nix::unistd::{fork, ForkResult};
|
||||||
|
|
||||||
struct Module {
|
struct Module {
|
||||||
name: String,
|
name: String,
|
||||||
memfd: Memfd,
|
memfd: OwnedFd,
|
||||||
companion: Mutex<Option<UnixStream>>,
|
companion: Mutex<Option<UnixStream>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,32 +95,30 @@ fn load_modules(arch: &str) -> Result<Vec<Module>> {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
log::info!(" Loading module `{name}`...");
|
log::info!(" Loading module `{name}`...");
|
||||||
let memfd = match create_memfd(&so_path, &name) {
|
let fd = match create_library_fd(&so_path) {
|
||||||
Ok(memfd) => memfd,
|
Ok(fd) => fd,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::warn!(" Failed to create memfd for `{name}`: {e}");
|
log::warn!(" Failed to create memfd for `{name}`: {e}");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let companion = match spawn_companion(&name, &memfd) {
|
let companion = Mutex::new(None);
|
||||||
Ok(companion) => companion,
|
let module = Module { name, memfd: fd, companion };
|
||||||
Err(e) => {
|
|
||||||
log::warn!(" Failed to spawn companion for `{name}`: {e}");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let companion = Mutex::new(companion);
|
|
||||||
let module = Module { name, memfd, companion };
|
|
||||||
modules.push(module);
|
modules.push(module);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(modules)
|
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 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 file = fs::File::open(so_path)?;
|
||||||
let mut reader = std::io::BufReader::new(file);
|
let mut reader = std::io::BufReader::new(file);
|
||||||
let mut writer = memfd.as_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);
|
seals.insert(memfd::FileSeal::SealSeal);
|
||||||
memfd.add_seals(&seals)?;
|
memfd.add_seals(&seals)?;
|
||||||
|
|
||||||
Ok(memfd)
|
Ok(OwnedFd::from(memfd.into_file()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_daemon_socket() -> Result<UnixListener> {
|
fn create_daemon_socket() -> Result<UnixListener> {
|
||||||
@@ -141,22 +143,36 @@ fn create_daemon_socket() -> Result<UnixListener> {
|
|||||||
Ok(listener)
|
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()?;
|
let (mut daemon, companion) = UnixStream::pair()?;
|
||||||
// Remove FD_CLOEXEC flag
|
// Remove FD_CLOEXEC flag
|
||||||
fcntl(companion.as_raw_fd(), FcntlArg::F_SETFD(FdFlag::empty()))?;
|
fcntl(companion.as_raw_fd(), FcntlArg::F_SETFD(FdFlag::empty()))?;
|
||||||
|
|
||||||
let process = std::env::args().next().unwrap();
|
let process = std::env::args().next().unwrap();
|
||||||
let nice_name = process.split('/').last().unwrap();
|
let nice_name = process.split('/').last().unwrap();
|
||||||
Command::new(&process)
|
|
||||||
.arg0(format!("{}-{}", nice_name, name))
|
match unsafe { fork()? } {
|
||||||
.arg("companion")
|
ForkResult::Parent { child, ..} => {
|
||||||
.arg(format!("{}", companion.as_raw_fd()))
|
if let Ok(WaitStatus::Exited(.., code)) = waitpid(child, None) {
|
||||||
.spawn()?;
|
ensure!(code == 0, format!("process exited with {code}"));
|
||||||
drop(companion);
|
} 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.write_string(name)?;
|
||||||
daemon.send_fd(memfd.as_raw_fd())?;
|
daemon.send_fd(*fd)?;
|
||||||
match daemon.read_u8()? {
|
match daemon.read_u8()? {
|
||||||
0 => Ok(None),
|
0 => Ok(None),
|
||||||
1 => Ok(Some(daemon)),
|
1 => Ok(Some(daemon)),
|
||||||
@@ -213,12 +229,33 @@ fn handle_daemon_action(mut stream: UnixStream, context: &Context) -> Result<()>
|
|||||||
DaemonSocketAction::RequestCompanionSocket => {
|
DaemonSocketAction::RequestCompanionSocket => {
|
||||||
let index = stream.read_usize()?;
|
let index = stream.read_usize()?;
|
||||||
let module = &context.modules[index];
|
let module = &context.modules[index];
|
||||||
|
let name = &module.name;
|
||||||
|
let fd = &module.memfd;
|
||||||
let mut companion = module.companion.lock().unwrap();
|
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() {
|
match companion.as_ref() {
|
||||||
Some(sock) => {
|
Some(sock) => {
|
||||||
if let Err(_) = sock.send_fd(stream.as_raw_fd()) {
|
if let Err(_) = sock.send_fd(stream.as_raw_fd()) {
|
||||||
log::error!("Companion of module `{}` crashed", module.name);
|
log::error!("Companion socket of module `{}` missing", module.name);
|
||||||
companion.take();
|
|
||||||
stream.write_u8(0)?;
|
stream.write_u8(0)?;
|
||||||
}
|
}
|
||||||
// Ok: Send by companion
|
// Ok: Send by companion
|
||||||
|
|||||||
Reference in New Issue
Block a user