You've already forked ReZygisk
mirror of
https://github.com/PerformanC/ReZygisk.git
synced 2025-09-06 06:37:01 +00:00
Separate companion
This commit is contained in:
10
README.md
10
README.md
@@ -12,11 +12,7 @@ Warning: The current version of Zygisksu is UNSTABLE. You may suffer boot loop o
|
|||||||
|
|
||||||
## Compatibility
|
## Compatibility
|
||||||
|
|
||||||
- [x] LSPosed
|
Should work with everything except those rely on Magisk internal behaviors.
|
||||||
- [x] Storage Isolation
|
|
||||||
- [ ] IFW Enhance
|
|
||||||
- [ ] Universal SafetyNet Fix
|
|
||||||
- [ ] Shamiko
|
|
||||||
|
|
||||||
## Development road map
|
## Development road map
|
||||||
|
|
||||||
@@ -24,8 +20,8 @@ Warning: The current version of Zygisksu is UNSTABLE. You may suffer boot loop o
|
|||||||
- [x] [Inject] Stabilize injector
|
- [x] [Inject] Stabilize injector
|
||||||
- [x] [Inject] Unload
|
- [x] [Inject] Unload
|
||||||
- [x] [Daemon] Linker namespace
|
- [x] [Daemon] Linker namespace
|
||||||
- [ ] [Daemon] Separate zygiskd process
|
- [x] [Daemon] Separate zygiskd process
|
||||||
- [ ] [Daemon] Handle 64 bit only devices
|
- [x] [Daemon] Handle 64 bit only devices
|
||||||
- [ ] [Daemon] Handle zygote death
|
- [ ] [Daemon] Handle zygote death
|
||||||
|
|
||||||
## Running on Magisk
|
## Running on Magisk
|
||||||
|
|||||||
@@ -98,10 +98,6 @@ namespace zygiskd {
|
|||||||
}
|
}
|
||||||
socket_utils::write_u8(fd, (uint8_t) SocketAction::GetModuleDir);
|
socket_utils::write_u8(fd, (uint8_t) SocketAction::GetModuleDir);
|
||||||
socket_utils::write_usize(fd, index);
|
socket_utils::write_usize(fd, index);
|
||||||
if (socket_utils::read_u8(fd) == 1) {
|
return socket_utils::recv_fd(fd);
|
||||||
return fd;
|
|
||||||
} else {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,4 +9,4 @@ export NATIVE_BRIDGE=$(getprop ro.dalvik.vm.native.bridge)
|
|||||||
|
|
||||||
log -p i -t "zygisksu" "Start watchdog"
|
log -p i -t "zygisksu" "Start watchdog"
|
||||||
resetprop ro.dalvik.vm.native.bridge libzygiskloader.so
|
resetprop ro.dalvik.vm.native.bridge libzygiskloader.so
|
||||||
exec "$MODDIR/bin/zygiskwd" >/dev/null 2>&1
|
exec "$MODDIR/bin/zygiskwd" "watchdog" >/dev/null 2>&1
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ rust-version = "1.67"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
android_logger = "0.12.0"
|
android_logger = "0.12.0"
|
||||||
anyhow = { version = "1.0.68", features = ["backtrace"] }
|
anyhow = { version = "1.0.68", features = ["backtrace"] }
|
||||||
|
clap = { version = "4.1.4", features = ["derive"] }
|
||||||
const_format = "0.2.5"
|
const_format = "0.2.5"
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
memfd = "0.6.2"
|
memfd = "0.6.2"
|
||||||
|
|||||||
@@ -3,6 +3,9 @@ plugins {
|
|||||||
id("org.mozilla.rust-android-gradle.rust-android")
|
id("org.mozilla.rust-android-gradle.rust-android")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val verName: String by rootProject.extra
|
||||||
|
val verCode: Int by rootProject.extra
|
||||||
|
|
||||||
android.buildFeatures {
|
android.buildFeatures {
|
||||||
androidResources = false
|
androidResources = false
|
||||||
buildConfig = false
|
buildConfig = false
|
||||||
@@ -16,4 +19,8 @@ cargo {
|
|||||||
targetDirectory = "build/intermediates/rust"
|
targetDirectory = "build/intermediates/rust"
|
||||||
val isDebug = gradle.startParameter.taskNames.any { it.toLowerCase().contains("debug") }
|
val isDebug = gradle.startParameter.taskNames.any { it.toLowerCase().contains("debug") }
|
||||||
profile = if (isDebug) "debug" else "release"
|
profile = if (isDebug) "debug" else "release"
|
||||||
|
exec = { spec, _ ->
|
||||||
|
spec.environment("VERSION_CODE", verCode)
|
||||||
|
spec.environment("VERSION_NAME", verName)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
61
zygiskd/src/companion.rs
Normal file
61
zygiskd/src/companion.rs
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
use std::ffi::c_void;
|
||||||
|
use std::os::fd::{FromRawFd, RawFd};
|
||||||
|
use std::os::unix::net::UnixStream;
|
||||||
|
use std::thread;
|
||||||
|
use anyhow::Result;
|
||||||
|
use nix::libc;
|
||||||
|
use passfd::FdPassingExt;
|
||||||
|
use crate::utils::UnixStreamExt;
|
||||||
|
use crate::dl;
|
||||||
|
|
||||||
|
type ZygiskCompanionEntryFn = unsafe extern "C" fn(i32);
|
||||||
|
|
||||||
|
pub fn entry(fd: i32) -> Result<()> {
|
||||||
|
unsafe { libc::prctl(libc::PR_SET_PDEATHSIG, libc::SIGKILL) };
|
||||||
|
let mut stream = unsafe { UnixStream::from_raw_fd(fd) };
|
||||||
|
let name = stream.read_string()?;
|
||||||
|
let library = stream.recv_fd()?;
|
||||||
|
let entry = load_module(library)?;
|
||||||
|
unsafe { libc::close(library) };
|
||||||
|
|
||||||
|
let entry = match entry {
|
||||||
|
Some(entry) => {
|
||||||
|
log::debug!("Companion process created for `{name}`");
|
||||||
|
stream.write_u8(1)?;
|
||||||
|
entry
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
log::debug!("No companion entry for `{name}`");
|
||||||
|
stream.write_u8(0)?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let fd = stream.recv_fd()?;
|
||||||
|
log::trace!("New companion request from module `{name}`");
|
||||||
|
thread::spawn(move || {
|
||||||
|
unsafe {
|
||||||
|
let mut s = UnixStream::from_raw_fd(fd);
|
||||||
|
match s.write_u8(1) { // Ack
|
||||||
|
Ok(_) => entry(fd),
|
||||||
|
Err(_) => log::warn!("Ack failed?"),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_module(fd: RawFd) -> Result<Option<ZygiskCompanionEntryFn>> {
|
||||||
|
unsafe {
|
||||||
|
let path = format!("/proc/self/fd/{fd}");
|
||||||
|
let handle = dl::dlopen(&path, libc::RTLD_NOW)?;
|
||||||
|
let symbol = std::ffi::CString::new("zygisk_companion_entry")?;
|
||||||
|
let entry = libc::dlsym(handle, symbol.as_ptr());
|
||||||
|
if entry.is_null() {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
let fnptr = std::mem::transmute::<*mut c_void, ZygiskCompanionEntryFn>(entry);
|
||||||
|
Ok(Some(fnptr))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,27 @@
|
|||||||
use const_format::concatcp;
|
use const_format::concatcp;
|
||||||
|
use log::LevelFilter;
|
||||||
use num_enum::TryFromPrimitive;
|
use num_enum::TryFromPrimitive;
|
||||||
|
|
||||||
|
pub const VERSION_NAME: &str = env!("VERSION_NAME");
|
||||||
|
pub const VERSION_CODE: &str = env!("VERSION_CODE");
|
||||||
|
pub const VERSION_FULL: &str = concatcp!(VERSION_NAME, " (", VERSION_CODE, ")");
|
||||||
|
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
pub const MAX_LOG_LEVEL: LevelFilter = LevelFilter::Trace;
|
||||||
|
#[cfg(not(debug_assertions))]
|
||||||
|
pub const MAX_LOG_LEVEL: LevelFilter = LevelFilter::Info;
|
||||||
|
|
||||||
|
#[cfg(target_pointer_width = "64")]
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! lp_select {
|
||||||
|
($lp32:expr, $lp64:expr) => { $lp64 };
|
||||||
|
}
|
||||||
|
#[cfg(target_pointer_width = "32")]
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! lp_select {
|
||||||
|
($lp32:expr, $lp64:expr) => { $lp32 };
|
||||||
|
}
|
||||||
|
|
||||||
pub const PROP_NATIVE_BRIDGE: &str = "ro.dalvik.vm.native.bridge";
|
pub const PROP_NATIVE_BRIDGE: &str = "ro.dalvik.vm.native.bridge";
|
||||||
|
|
||||||
pub const SOCKET_PLACEHOLDER: &str = "socket_placeholder";
|
pub const SOCKET_PLACEHOLDER: &str = "socket_placeholder";
|
||||||
|
|||||||
@@ -1,57 +1,53 @@
|
|||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
mod companion;
|
||||||
mod constants;
|
mod constants;
|
||||||
mod dl;
|
mod dl;
|
||||||
mod utils;
|
mod utils;
|
||||||
mod watchdog;
|
mod watchdog;
|
||||||
mod zygisk;
|
mod zygiskd;
|
||||||
|
|
||||||
use anyhow::{bail, Result};
|
use clap::{Subcommand, Parser};
|
||||||
use log::LevelFilter;
|
|
||||||
use nix::libc;
|
#[derive(Parser, Debug)]
|
||||||
|
#[command(author, version = constants::VERSION_FULL, about, long_about = None)]
|
||||||
|
struct Args {
|
||||||
|
#[command(subcommand)]
|
||||||
|
command: Commands,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Subcommand, Debug)]
|
||||||
|
enum Commands {
|
||||||
|
/// Start zygisk watchdog
|
||||||
|
Watchdog,
|
||||||
|
/// Start zygisk daemon
|
||||||
|
Daemon,
|
||||||
|
/// Start zygisk companion
|
||||||
|
Companion { fd: i32 },
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
static MAX_LOG_LEVEL: LevelFilter = LevelFilter::Trace;
|
|
||||||
#[cfg(not(debug_assertions))]
|
|
||||||
static MAX_LOG_LEVEL: LevelFilter = LevelFilter::Info;
|
|
||||||
|
|
||||||
fn init_android_logger(tag: &str) {
|
fn init_android_logger(tag: &str) {
|
||||||
android_logger::init_once(
|
android_logger::init_once(
|
||||||
android_logger::Config::default()
|
android_logger::Config::default()
|
||||||
.with_max_level(MAX_LOG_LEVEL)
|
.with_max_level(constants::MAX_LOG_LEVEL)
|
||||||
.with_tag(tag),
|
.with_tag(tag),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn entry() -> Result<()> {
|
|
||||||
let process = std::env::args().next().unwrap();
|
|
||||||
let process = process.split('/').last().unwrap();
|
|
||||||
init_android_logger(process);
|
|
||||||
match process {
|
|
||||||
"zygiskwd" => {
|
|
||||||
log::info!("Start zygisksu watchdog");
|
|
||||||
watchdog::check_permission()?;
|
|
||||||
watchdog::ensure_single_instance()?;
|
|
||||||
watchdog::spawn_daemon()?;
|
|
||||||
}
|
|
||||||
"zygiskd32" => {
|
|
||||||
log::info!("Start zygiskd32");
|
|
||||||
unsafe { libc::prctl(libc::PR_SET_PDEATHSIG, libc::SIGKILL); }
|
|
||||||
zygisk::start(false)?;
|
|
||||||
loop {}
|
|
||||||
}
|
|
||||||
"zygiskd64" => {
|
|
||||||
log::info!("Start zygiskd64");
|
|
||||||
unsafe { libc::prctl(libc::PR_SET_PDEATHSIG, libc::SIGKILL); }
|
|
||||||
zygisk::start(true)?;
|
|
||||||
}
|
|
||||||
_ => bail!("Unexpected process name: {process}")
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
if let Err(e) = entry() {
|
let process = std::env::args().next().unwrap();
|
||||||
|
let nice_name = process.split('/').last().unwrap();
|
||||||
|
init_android_logger(nice_name);
|
||||||
|
|
||||||
|
let cli = Args::parse();
|
||||||
|
let result = match cli.command {
|
||||||
|
Commands::Watchdog => watchdog::entry(),
|
||||||
|
Commands::Daemon => zygiskd::entry(lp_select!(false, true)),
|
||||||
|
Commands::Companion { fd } => companion::entry(fd),
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Err(e) = &result {
|
||||||
log::error!("Crashed: {}\n{}", e, e.backtrace());
|
log::error!("Crashed: {}\n{}", e, e.backtrace());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,14 @@ use std::{fs, thread};
|
|||||||
|
|
||||||
static mut LOCK_FILE: Option<fs::File> = None;
|
static mut LOCK_FILE: Option<fs::File> = None;
|
||||||
|
|
||||||
pub fn check_permission() -> Result<()> {
|
pub fn entry() -> Result<()> {
|
||||||
|
log::info!("Start zygisksu watchdog");
|
||||||
|
check_permission()?;
|
||||||
|
ensure_single_instance()?;
|
||||||
|
spawn_daemon()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_permission() -> Result<()> {
|
||||||
log::info!("Check permission");
|
log::info!("Check permission");
|
||||||
let uid = getuid();
|
let uid = getuid();
|
||||||
if uid.as_raw() != 0 {
|
if uid.as_raw() != 0 {
|
||||||
@@ -31,7 +38,7 @@ pub fn check_permission() -> Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ensure_single_instance() -> Result<()> {
|
fn ensure_single_instance() -> Result<()> {
|
||||||
log::info!("Ensure single instance");
|
log::info!("Ensure single instance");
|
||||||
let metadata = fs::metadata(constants::PATH_ZYGISKSU_DIR);
|
let metadata = fs::metadata(constants::PATH_ZYGISKSU_DIR);
|
||||||
if metadata.is_err() || !metadata.unwrap().is_dir() {
|
if metadata.is_err() || !metadata.unwrap().is_dir() {
|
||||||
@@ -50,9 +57,9 @@ pub fn ensure_single_instance() -> Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spawn_daemon() -> Result<()> {
|
fn spawn_daemon() -> Result<()> {
|
||||||
let daemon32 = Command::new(constants::PATH_ZYGISKD32).spawn()?;
|
let daemon32 = Command::new(constants::PATH_ZYGISKD32).arg("daemon").spawn();
|
||||||
let daemon64 = Command::new(constants::PATH_ZYGISKD64).spawn()?;
|
let daemon64 = Command::new(constants::PATH_ZYGISKD64).arg("daemon").spawn();
|
||||||
let (sender, receiver) = mpsc::channel();
|
let (sender, receiver) = mpsc::channel();
|
||||||
let spawn = |mut daemon: Child| {
|
let spawn = |mut daemon: Child| {
|
||||||
let sender = sender.clone();
|
let sender = sender.clone();
|
||||||
@@ -63,8 +70,8 @@ pub fn spawn_daemon() -> Result<()> {
|
|||||||
sender.send(()).unwrap();
|
sender.send(()).unwrap();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
spawn(daemon32);
|
if let Ok(it) = daemon32 { spawn(it) }
|
||||||
spawn(daemon64);
|
if let Ok(it) = daemon64 { spawn(it) }
|
||||||
let _ = receiver.recv();
|
let _ = receiver.recv();
|
||||||
bail!("Daemon process died");
|
bail!("Daemon process died");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,30 +1,29 @@
|
|||||||
use crate::constants::DaemonSocketAction;
|
use crate::constants::DaemonSocketAction;
|
||||||
use crate::utils::{restore_native_bridge, UnixStreamExt};
|
use crate::utils::{restore_native_bridge, UnixStreamExt};
|
||||||
use crate::{constants, dl, utils};
|
use crate::{constants, utils};
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
use memfd::Memfd;
|
use memfd::Memfd;
|
||||||
use nix::{
|
use nix::{
|
||||||
libc::{self, dlsym},
|
fcntl::{fcntl, FcntlArg, FdFlag},
|
||||||
unistd::getppid,
|
libc::self,
|
||||||
};
|
};
|
||||||
use passfd::FdPassingExt;
|
use passfd::FdPassingExt;
|
||||||
use std::sync::Arc;
|
use std::sync::{Arc, Mutex};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::ffi::{c_char, c_void};
|
use std::ffi::c_char;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::os::unix::{
|
use std::os::unix::{
|
||||||
net::{UnixListener, UnixStream},
|
net::{UnixListener, UnixStream},
|
||||||
prelude::AsRawFd,
|
prelude::AsRawFd,
|
||||||
};
|
};
|
||||||
|
use std::os::unix::process::CommandExt;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
|
||||||
type ZygiskCompanionEntryFn = unsafe extern "C" fn(i32);
|
|
||||||
|
|
||||||
struct Module {
|
struct Module {
|
||||||
name: String,
|
name: String,
|
||||||
memfd: Memfd,
|
memfd: Memfd,
|
||||||
companion_entry: Option<ZygiskCompanionEntryFn>,
|
companion: Mutex<Option<UnixStream>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Context {
|
struct Context {
|
||||||
@@ -32,8 +31,9 @@ struct Context {
|
|||||||
modules: Vec<Module>,
|
modules: Vec<Module>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start(is64: bool) -> Result<()> {
|
pub fn entry(is64: bool) -> Result<()> {
|
||||||
check_parent()?;
|
unsafe { libc::prctl(libc::PR_SET_PDEATHSIG, libc::SIGKILL) };
|
||||||
|
|
||||||
let arch = get_arch(is64)?;
|
let arch = get_arch(is64)?;
|
||||||
log::debug!("Daemon architecture: {arch}");
|
log::debug!("Daemon architecture: {arch}");
|
||||||
|
|
||||||
@@ -63,15 +63,6 @@ pub fn start(is64: bool) -> Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_parent() -> Result<()> {
|
|
||||||
let parent = fs::read_to_string(format!("/proc/{}/cmdline", getppid().as_raw()))?;
|
|
||||||
let parent = parent.split('/').last().unwrap().trim_end_matches('\0');
|
|
||||||
if parent != "zygiskwd" {
|
|
||||||
bail!("Daemon is not started by watchdog: {parent}");
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_arch(is64: bool) -> Result<&'static str> {
|
fn get_arch(is64: bool) -> Result<&'static str> {
|
||||||
let output = Command::new("getprop").arg("ro.product.cpu.abi").output()?;
|
let output = Command::new("getprop").arg("ro.product.cpu.abi").output()?;
|
||||||
let system_arch = String::from_utf8(output.stdout)?;
|
let system_arch = String::from_utf8(output.stdout)?;
|
||||||
@@ -111,18 +102,16 @@ fn load_modules(arch: &str) -> Result<Vec<Module>> {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let companion_entry = match preload_module(&memfd) {
|
let companion = match spawn_companion(&name, &memfd) {
|
||||||
Ok(entry) => entry,
|
Ok(companion) => companion,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::warn!(" Failed to preload `{name}`: {e}");
|
log::warn!(" Failed to spawn companion for `{name}`: {e}");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let module = Module {
|
|
||||||
name,
|
let companion = Mutex::new(companion);
|
||||||
memfd,
|
let module = Module { name, memfd, companion };
|
||||||
companion_entry,
|
|
||||||
};
|
|
||||||
modules.push(module);
|
modules.push(module);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,20 +137,6 @@ fn create_memfd(name: &str, so_path: &PathBuf) -> Result<Memfd> {
|
|||||||
Ok(memfd)
|
Ok(memfd)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn preload_module(memfd: &Memfd) -> Result<Option<ZygiskCompanionEntryFn>> {
|
|
||||||
unsafe {
|
|
||||||
let path = format!("/proc/self/fd/{}", memfd.as_raw_fd());
|
|
||||||
let handle = dl::dlopen(&path, libc::RTLD_NOW)?;
|
|
||||||
let symbol = std::ffi::CString::new("zygisk_companion_entry")?;
|
|
||||||
let entry = dlsym(handle, symbol.as_ptr());
|
|
||||||
if entry.is_null() {
|
|
||||||
return Ok(None);
|
|
||||||
}
|
|
||||||
let fnptr = std::mem::transmute::<*mut c_void, ZygiskCompanionEntryFn>(entry);
|
|
||||||
Ok(Some(fnptr))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn create_daemon_socket(is64: bool) -> Result<UnixListener> {
|
fn create_daemon_socket(is64: bool) -> Result<UnixListener> {
|
||||||
utils::set_socket_create_context("u:r:zygote:s0")?;
|
utils::set_socket_create_context("u:r:zygote:s0")?;
|
||||||
let suffix = if is64 { "zygiskd64" } else { "zygiskd32" };
|
let suffix = if is64 { "zygiskd64" } else { "zygiskd32" };
|
||||||
@@ -171,6 +146,29 @@ fn create_daemon_socket(is64: bool) -> Result<UnixListener> {
|
|||||||
Ok(listener)
|
Ok(listener)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn spawn_companion(name: &str, memfd: &Memfd) -> 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);
|
||||||
|
|
||||||
|
daemon.write_string(name)?;
|
||||||
|
daemon.send_fd(memfd.as_raw_fd())?;
|
||||||
|
match daemon.read_u8()? {
|
||||||
|
0 => Ok(None),
|
||||||
|
1 => Ok(Some(daemon)),
|
||||||
|
_ => bail!("Invalid companion response"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_daemon_action(mut stream: UnixStream, context: &Context) -> Result<()> {
|
fn handle_daemon_action(mut stream: UnixStream, context: &Context) -> Result<()> {
|
||||||
let action = stream.read_u8()?;
|
let action = stream.read_u8()?;
|
||||||
let action = DaemonSocketAction::try_from(action)?;
|
let action = DaemonSocketAction::try_from(action)?;
|
||||||
@@ -207,13 +205,15 @@ 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];
|
||||||
log::debug!("New companion request from module {}", module.name);
|
let mut companion = module.companion.lock().unwrap();
|
||||||
|
match companion.as_ref() {
|
||||||
// FIXME: Spawn a new process
|
Some(sock) => {
|
||||||
match module.companion_entry {
|
if let Err(_) = sock.send_fd(stream.as_raw_fd()) {
|
||||||
Some(entry) => {
|
log::error!("Companion of module `{}` crashed", module.name);
|
||||||
stream.write_u8(1)?;
|
companion.take();
|
||||||
unsafe { entry(stream.as_raw_fd()); }
|
stream.write_u8(0)?;
|
||||||
|
}
|
||||||
|
// Ok: Send by companion
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
stream.write_u8(0)?;
|
stream.write_u8(0)?;
|
||||||
Reference in New Issue
Block a user