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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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