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:
5ec1cff
2023-05-19 18:28:56 +08:00
committed by GitHub
parent f5bf82fa93
commit 00f0a6e3fa
7 changed files with 88 additions and 37 deletions

View File

@@ -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;
} }

View File

@@ -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;

View File

@@ -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,
) )
} }

View File

@@ -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

View File

@@ -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"

View File

@@ -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;

View File

@@ -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