From f5e0a418c92447d2731a3e03e85e22cb4cba57d9 Mon Sep 17 00:00:00 2001 From: 5ec1cff Date: Fri, 3 Nov 2023 11:41:28 +0800 Subject: [PATCH] WIP --- loader/src/common/daemon.cpp | 11 ++- loader/src/{injector => common}/files.cpp | 0 loader/src/{injector => common}/misc.cpp | 0 loader/src/include/daemon.h | 3 + loader/src/{injector => include}/files.hpp | 0 loader/src/{injector => include}/misc.hpp | 0 loader/src/ptracer/main.cpp | 58 +++++++++-- loader/src/ptracer/main.hpp | 5 +- loader/src/ptracer/monitor.cpp | 73 +++++++++++--- loader/src/ptracer/ptracer.cpp | 48 ++++++---- loader/src/ptracer/utils.cpp | 31 ++++++ loader/src/ptracer/utils.hpp | 6 +- module/src/service.sh | 6 ++ zygiskd/Cargo.toml | 2 +- zygiskd/src/constants.rs | 10 +- zygiskd/src/utils.rs | 4 +- zygiskd/src/watchdog.rs | 106 +++++++++++++++++++-- zygiskd/src/zygiskd.rs | 6 ++ 18 files changed, 314 insertions(+), 55 deletions(-) rename loader/src/{injector => common}/files.cpp (100%) rename loader/src/{injector => common}/misc.cpp (100%) rename loader/src/{injector => include}/files.hpp (100%) rename loader/src/{injector => include}/misc.hpp (100%) diff --git a/loader/src/common/daemon.cpp b/loader/src/common/daemon.cpp index cc25fd0..437d65e 100644 --- a/loader/src/common/daemon.cpp +++ b/loader/src/common/daemon.cpp @@ -93,7 +93,7 @@ namespace zygiskd { } int GetModuleDir(size_t index) { - int fd = Connect(1); + UniqueFd fd = Connect(1); if (fd == -1) { PLOGE("GetModuleDir"); return -1; @@ -102,4 +102,13 @@ namespace zygiskd { socket_utils::write_usize(fd, index); return socket_utils::recv_fd(fd); } + + void ZygoteRestart() { + UniqueFd fd = Connect(1); + if (fd == -1) { + PLOGE("Could not notify ZygoteRestart"); + return; + } + socket_utils::write_u8(fd, (uint8_t) SocketAction::ZygoteRestart); + } } diff --git a/loader/src/injector/files.cpp b/loader/src/common/files.cpp similarity index 100% rename from loader/src/injector/files.cpp rename to loader/src/common/files.cpp diff --git a/loader/src/injector/misc.cpp b/loader/src/common/misc.cpp similarity index 100% rename from loader/src/injector/misc.cpp rename to loader/src/common/misc.cpp diff --git a/loader/src/include/daemon.h b/loader/src/include/daemon.h index 2a177f3..97b9a12 100644 --- a/loader/src/include/daemon.h +++ b/loader/src/include/daemon.h @@ -58,6 +58,7 @@ namespace zygiskd { ReadModules, RequestCompanionSocket, GetModuleDir, + ZygoteRestart, }; bool PingHeartbeat(); @@ -71,4 +72,6 @@ namespace zygiskd { int ConnectCompanion(size_t index); int GetModuleDir(size_t index); + + void ZygoteRestart(); } diff --git a/loader/src/injector/files.hpp b/loader/src/include/files.hpp similarity index 100% rename from loader/src/injector/files.hpp rename to loader/src/include/files.hpp diff --git a/loader/src/injector/misc.hpp b/loader/src/include/misc.hpp similarity index 100% rename from loader/src/injector/misc.hpp rename to loader/src/include/misc.hpp diff --git a/loader/src/ptracer/main.cpp b/loader/src/ptracer/main.cpp index 4cad52c..99bd1c3 100644 --- a/loader/src/ptracer/main.cpp +++ b/loader/src/ptracer/main.cpp @@ -2,21 +2,61 @@ #include #include #include +#include +#include +#include #include "main.hpp" #include "utils.hpp" +#include "daemon.h" using namespace std::string_view_literals; int main(int argc, char **argv) { - if (argc >= 2 && argv[1] == "prop_monitor"sv) { - if (access("/system/lib" LP_SELECT("", "64"), R_OK) == 0) prop_monitor_main(); - } else if (argc >= 3 && argv[1] == "trace-zygote"sv) { - auto pid = strtol(argv[2], nullptr, 0); - trace_zygote_main(pid); - } else { - if (argc >= 2) LOGE("unknown command %s", argv[1]); - else LOGE("no command specified"); + if (access("/system/lib" LP_SELECT("", "64"), R_OK) != 0) return 1; + auto lock_fd = open("/dev/zygisk/lock" LP_SELECT("32", "64"), O_CLOEXEC | O_CREAT, O_RDONLY); + if (lock_fd == -1) { + PLOGE("create lock file"); + return 1; } - return 0; + struct flock lock{ + .l_type = F_RDLCK, + .l_whence = SEEK_SET, + .l_start = 0, + .l_len = 0 + }; + if (fcntl(lock_fd, F_SETLK, &lock) == -1) { + PLOGE("set file lock"); + close(lock_fd); + return 1; + } + LOGI("zygote monitor started"); + struct timespec last_launch_time { .tv_sec = 0, .tv_nsec = 0 }, ts; + int launch_count = 0; + bool first = true; + while (true) { + auto pid = wait_for_zygote(); + if (pid == -1) break; + LOGI("inject zygote %d", pid); + if (first) first = false; + else { + LOGI("notify zygisk companion restart"); + zygiskd::ZygoteRestart(); + } + clock_gettime(CLOCK_MONOTONIC, &ts); + auto delta = ts.tv_sec - last_launch_time.tv_sec; + if (delta > 30) launch_count++; + else launch_count = 0; + if (launch_count >= 5) { + LOGE("zygote crash too much times, stop"); + break; + } + memcpy(&last_launch_time, &ts, sizeof(struct timespec)); + if (!trace_zygote(pid)) { + break; + } + } + __system_property_set("ctl.sigstop_off", "zygote"); + __system_property_set("ctl.sigstop_off", "zygote_secondary"); + return 1; } diff --git a/loader/src/ptracer/main.hpp b/loader/src/ptracer/main.hpp index 087d29c..fa3dd33 100644 --- a/loader/src/ptracer/main.hpp +++ b/loader/src/ptracer/main.hpp @@ -1,4 +1,5 @@ #pragma once -void prop_monitor_main(); -void trace_zygote_main(int pid); +int wait_for_zygote(); +bool trace_zygote(int pid); +int find_zygote(); diff --git a/loader/src/ptracer/monitor.cpp b/loader/src/ptracer/monitor.cpp index ad19109..2fd28cd 100644 --- a/loader/src/ptracer/monitor.cpp +++ b/loader/src/ptracer/monitor.cpp @@ -1,37 +1,86 @@ #include #include +#include #include "main.hpp" #include "utils.hpp" +#include "files.hpp" +#include "misc.hpp" -void prop_monitor_main() { - LOGI("prop monitor started"); - // if service is not running, pid = "" - auto name = "init.svc_debug_pid." LP_SELECT("zygote_secondary", "zygote"); // argv[1]; - LOGI("start monitoring %s", name); +using namespace std::string_view_literals; + +int find_zygote() { + LOGD("find zygote"); + auto sockets = ScanUnixSockets(); + auto dir = xopen_dir("/proc"); + for (dirent *entry; (entry = readdir(dir.get()));) { + auto pid = parse_int(entry->d_name); + char comm[18]; + char state; + if (pid == -1 || pid == 1) continue; + auto stat_file = xopen_file((std::string("/proc/") + std::to_string(pid) + "/stat").c_str(), "r"); + if (stat_file == nullptr) continue; + if (fscanf(stat_file.get(), "%*d %17s %c", comm, &state) != 2 + || comm != "(init)"sv + || state != 'T') { + continue; + } + LOGD("%d is stopped init", pid); + auto fd_dir = xopen_dir((std::string("/proc/") + std::to_string(pid) + "/fd").c_str()); + if (fd_dir == nullptr) continue; + for (dirent *fd_entry; (fd_entry = readdir(fd_dir.get()));) { + if (fd_entry->d_name == "."sv || fd_entry->d_name == ".."sv) continue; + struct stat st{}; + if (stat((std::string("/proc/") + std::to_string(pid) + "/fd/" + fd_entry->d_name).c_str(), &st) == -1) { + PLOGE("stat /proc/%d/fd/%s", pid, fd_entry->d_name); + continue; + } + if ((st.st_mode & S_IFSOCK) == 0) continue; + auto it = sockets.find(st.st_ino); + if (it != sockets.end() && it->second == LP_SELECT("/dev/socket/zygote_secondary", "/dev/socket/zygote")) { + LOGD("%d is zygote", pid); + return pid; + } + } + } + return -1; +} + +int wait_for_zygote() { + auto name = "init.svc." LP_SELECT("zygote_secondary", "zygote"); auto prop = __system_property_find(name); if (prop == nullptr) { - __system_property_set(name, ""); + __system_property_set(name, "stopped"); prop = __system_property_find(name); if (prop == nullptr) { LOGE("failed to create prop"); exit(1); } } + std::string last_state = "running"; char val[PROP_VALUE_MAX]; uint32_t new_serial = 0; while (true) { __system_property_wait(prop, new_serial, &new_serial, nullptr); __system_property_get(name, val); LOGD("%s(%u): %s\n", name, new_serial, val); - auto pid = strtol(val, nullptr, 0); - if (pid != 0) { - LOGD("start ptrace %ld", pid); - if (fork_dont_care() == 0) { - execl("/proc/self/exe", "zygisk-ptracer", "trace-zygote", val, nullptr); - PLOGE("failed to exec"); + if (val != last_state && val == "running"sv) { + LOGI("zygote is running, find zygote"); + int pid = -1; + for (int i = 0; i < 5; i++) { + pid = find_zygote(); + if (pid != -1) break; + else { + LOGW("could not find zygote, wait 1s"); + sleep(1); + } + } + if (pid == -1) { + LOGE("failed to find zygote"); exit(1); } + return pid; } + last_state = val; } } diff --git a/loader/src/ptracer/ptracer.cpp b/loader/src/ptracer/ptracer.cpp index 3692099..4b74fd8 100644 --- a/loader/src/ptracer/ptracer.cpp +++ b/loader/src/ptracer/ptracer.cpp @@ -152,49 +152,65 @@ bool inject_on_main(int pid, const char *lib_path) { #define STOPPED_WITH(sig, event) (WIFSTOPPED(status) && WSTOPSIG(status) == (sig) && (status >> 16) == (event)) -void trace_zygote_main(int pid) { +bool trace_zygote(int pid) { +#define WAIT_OR_DIE if (wait_pid(pid, &status, __WALL) != pid) return false; +#define CONT_OR_DIE \ + if (ptrace(PTRACE_CONT, pid, 0, 0) == -1) { \ + PLOGE("cont"); \ + return false; \ + } int status; LOGI("tracing %d (tracer %d)", pid, getpid()); if (ptrace(PTRACE_SEIZE, pid, 0, PTRACE_O_TRACEEXEC) == -1) { PLOGE("seize"); - return; + return false; } - wait_pid(pid, &status, __WALL); + struct finally { + int pid; + ~finally() { + ptrace(PTRACE_DETACH, pid, 0, 0); + } + } _{pid}; + WAIT_OR_DIE if (STOPPED_WITH(SIGSTOP, PTRACE_EVENT_STOP)) { // if SIGSTOP is delivered before we seized it LOGD("process is already stopped"); - kill(pid, SIGCONT); - ptrace(PTRACE_CONT, pid, 0, 0); - wait_pid(pid, &status, __WALL); + if (kill(pid, SIGCONT)) { + PLOGE("kill"); + return false; + } + CONT_OR_DIE + WAIT_OR_DIE if (STOPPED_WITH(SIGTRAP, PTRACE_EVENT_STOP)) { - ptrace(PTRACE_CONT, pid, 0, 0); - wait_pid(pid, &status, __WALL); + CONT_OR_DIE + WAIT_OR_DIE if (STOPPED_WITH(SIGCONT, 0)) { LOGD("received SIGCONT"); ptrace(PTRACE_CONT, pid, 0, 0); } } else { LOGE("unknown state %s, not SIGTRAP + EVENT_STOP", parse_status(status).c_str()); + return false; } } else if (STOPPED_WITH(SIGSTOP, 0)) { // if SIGSTOP is delivered after we seized it LOGD("process received SIGSTOP, suppress"); - ptrace(PTRACE_CONT, pid, 0, 0); + CONT_OR_DIE } else { LOGE("unknown state %s, neither EVENT_STOP nor SIGSTOP", parse_status(status).c_str()); - exit(1); + return false; } - wait_pid(pid, &status, __WALL); + WAIT_OR_DIE // enter the app_process if (STOPPED_WITH(SIGTRAP, PTRACE_EVENT_EXEC)) { - LOGD("app_process exec-ed"); + LOGI("app_process exec-ed"); if (!inject_on_main(pid, "/dev/zygisk/lib" LP_SELECT("", "64") "/libzygisk.so")) { LOGE("failed to inject"); - exit(1); + return false; } } else { - LOGE("unknown status %d", status); - exit(1); + LOGE("unknown status %s", parse_status(status).c_str()); + return false; } - ptrace(PTRACE_DETACH, pid, 0, 0); + return true; } diff --git a/loader/src/ptracer/utils.cpp b/loader/src/ptracer/utils.cpp index 4d7912c..b2f665f 100644 --- a/loader/src/ptracer/utils.cpp +++ b/loader/src/ptracer/utils.cpp @@ -62,6 +62,37 @@ std::vector MapInfo::Scan(const std::string& pid) { return info; } +// https://cs.android.com/android/platform/superproject/main/+/main:external/toybox/toys/net/netstat.c;l=200;drc=657f94698c7fc7d4f9838cbcf3b4b78e38939d5c +std::map ScanUnixSockets() { + constexpr static auto kSocketEntry = 1; + LOGD("scanning unix sockets"); + std::map info; + auto sockets = std::unique_ptr{fopen("/proc/net/unix", "r"), &fclose}; + char *line = nullptr; + size_t len = 0; + // skip header + getline(&line, &len, sockets.get()); + if (sockets) { + ssize_t read; + while ((read = getline(&line, &len, sockets.get())) > 0) { + line[read - 1] = '\0'; + ino_t ino; + char *path = nullptr; + // Num RefCount Protocol Flags Type St Inode Path + if (sscanf(line, "%*p: %*lx %*lx %*lx %*lx %*lx %lu%m[^\n]", &ino, &path) < kSocketEntry) { + continue; + } + if (path != nullptr) { + LOGD("%ld -> %s", ino, path + 1); + info.emplace(ino, path + 1); + free(path); + } + } + free(line); + } + return info; +} + ssize_t write_proc(int pid, uintptr_t *remote_addr, const void *buf, size_t len) { LOGD("write to remote addr %p size %zu", remote_addr, len); struct iovec local{ diff --git a/loader/src/ptracer/utils.hpp b/loader/src/ptracer/utils.hpp index 09a4c45..dfe3df2 100644 --- a/loader/src/ptracer/utils.hpp +++ b/loader/src/ptracer/utils.hpp @@ -1,6 +1,7 @@ #pragma once #include #include +#include #include "daemon.h" @@ -37,7 +38,7 @@ struct MapInfo { /// \brief Scans /proc/self/maps and returns a list of \ref MapInfo entries. /// This is useful to find out the inode of the library to hook. /// \return A list of \ref MapInfo entries. - [[maybe_unused, gnu::visibility("default")]] static std::vector Scan(const std::string& pid = "self"); + static std::vector Scan(const std::string& pid = "self"); }; #if defined(__x86_64__) @@ -112,3 +113,6 @@ inline const char* sigabbrev_np(int sig) { if (sig > 0 && sig < NSIG) return sys_signame[sig]; return "(unknown)"; } + +std::map ScanUnixSockets(); + diff --git a/module/src/service.sh b/module/src/service.sh index 012a291..b21aba5 100644 --- a/module/src/service.sh +++ b/module/src/service.sh @@ -6,6 +6,12 @@ MODDIR=${0%/*} if [ "$ZYGISK_ENABLED" ]; then exit 0 fi +# temporary fix for AVD 30 +if [ -f /dev/zygisk/wd ]; then + log -p i -t "zygisk-sh" "prevent from instance duplicated" + exit +fi +touch /dev/zygisk/wd cd "$MODDIR" diff --git a/zygiskd/Cargo.toml b/zygiskd/Cargo.toml index 98003e9..b947d4f 100644 --- a/zygiskd/Cargo.toml +++ b/zygiskd/Cargo.toml @@ -20,7 +20,7 @@ num_enum = "0.5" passfd = "0.1" proc-maps = "0.3" -rustix = { version = "0.38", features = [ "fs", "process", "mount", "net", "thread"] } +rustix = { version = "0.38", features = [ "fs", "process", "mount", "net", "thread" ] } tokio = { version = "1.28", features = ["full"] } [profile.release] diff --git a/zygiskd/src/constants.rs b/zygiskd/src/constants.rs index 43e4536..cfde478 100644 --- a/zygiskd/src/constants.rs +++ b/zygiskd/src/constants.rs @@ -16,19 +16,20 @@ pub const MAX_LOG_LEVEL: LevelFilter = LevelFilter::Trace; pub const MAX_LOG_LEVEL: LevelFilter = LevelFilter::Info; pub const PROP_CTL_RESTART: &str = "ctl.restart"; +pub const PROP_CTL_SIGSTOP_OFF: &str = "ctl.sigstop_off"; -pub const PATH_PCL: &str = "/system/etc/preloaded-classes"; -pub const PATH_ZYGISK_LIB: &str = concatcp!(lp_select!("/system/lib", "/system/lib64"), "/libzygisk.so"); pub const PATH_WORK_DIR: &str = "/dev/zygisk"; // TODO: Replace with /debug_ramdisk/zygisk pub const PATH_PROP_OVERLAY: &str = concatcp!(PATH_WORK_DIR, "/module.prop"); pub const PATH_CP_SOCKET: &str = concatcp!(PATH_WORK_DIR, lp_select!("/cp32.sock", "/cp64.sock")); +pub const PATH_PT_LOCK32: &str = concatcp!(PATH_WORK_DIR, "/lock32"); +pub const PATH_PT_LOCK64: &str = concatcp!(PATH_WORK_DIR, "/lock64"); pub const PATH_MODULES_DIR: &str = ".."; pub const PATH_MODULE_PROP: &str = "module.prop"; pub const PATH_CP_BIN32: &str = "bin/zygisk-cp32"; pub const PATH_CP_BIN64: &str = "bin/zygisk-cp64"; -pub const PATH_PTRACE_BIN32: &str = "bin/zygisk-ptrace32"; -pub const PATH_PTRACE_BIN64: &str = "bin/zygisk-ptrace64"; +pub const PATH_PT_BIN32: &str = "bin/zygisk-ptracer32"; +pub const PATH_PT_BIN64: &str = "bin/zygisk-ptracer64"; pub const STATUS_LOADED: &str = "😋 Zygisk Next is loaded"; @@ -47,6 +48,7 @@ pub enum DaemonSocketAction { ReadModules, RequestCompanionSocket, GetModuleDir, + ZygoteRestarted, } // Zygisk process flags diff --git a/zygiskd/src/utils.rs b/zygiskd/src/utils.rs index 481d36f..577df8b 100644 --- a/zygiskd/src/utils.rs +++ b/zygiskd/src/utils.rs @@ -1,6 +1,6 @@ use anyhow::Result; use std::{fs, io::{Read, Write}, os::unix::net::UnixStream}; -use std::ffi::{c_char, CStr, CString}; +use std::ffi::{c_char, c_void, CStr, CString}; use std::os::fd::AsFd; use std::os::unix::net::UnixListener; use std::process::Command; @@ -177,4 +177,6 @@ extern "C" { fn __android_log_print(prio: i32, tag: *const c_char, fmt: *const c_char, ...) -> i32; fn __system_property_get(name: *const c_char, value: *mut c_char) -> u32; fn __system_property_set(name: *const c_char, value: *const c_char) -> u32; + fn __system_property_find(name: *const c_char) -> *const c_void; + fn __system_property_wait(info: *const c_void, old_serial: u32, new_serial: *u32, timeout: *const libc::timespec) -> bool; } diff --git a/zygiskd/src/watchdog.rs b/zygiskd/src/watchdog.rs index 2dabfbb..fa7ab8c 100644 --- a/zygiskd/src/watchdog.rs +++ b/zygiskd/src/watchdog.rs @@ -3,13 +3,18 @@ use anyhow::{bail, Result}; use std::fs; use std::future::Future; use std::io::{BufRead, BufReader, Write}; +use std::os::fd::AsRawFd; +use std::path::Path; use std::pin::Pin; use futures::stream::FuturesUnordered; -use futures::StreamExt; +use futures::{FutureExt, pin_mut, select, StreamExt}; +use futures::future::Fuse; use log::{debug, error, info}; use rustix::mount::mount_bind; use rustix::process::{getgid, getuid, kill_process, Pid, Signal}; use tokio::process::{Child, Command}; +use tokio::task; +use tokio::task::JoinHandle; use crate::utils::LateInit; static PROP_SECTIONS: LateInit<[String; 2]> = LateInit::new(); @@ -105,16 +110,72 @@ fn check_and_set_hint() -> Result { Ok(false) } +fn wait_for_ptrace(is_32bit: bool) -> Option>> { + let lock_path = if is_32bit { + if !Path::new(constants::PATH_PT_BIN32).is_file() { + return None + } + constants::PATH_PT_LOCK32 + } else { + if !Path::new(constants::PATH_PT_BIN64).is_file() { + return None + } + constants::PATH_PT_LOCK64 + }; + info!("wait for ptrace 32={}", is_32bit); + Some(task::spawn_blocking(move || -> Result<()> { + let file = match fs::OpenOptions::new().write(true).open(lock_path) { + Ok(f) => f, + Err(e) => { + bail!("failed to open lock: {}", e) + } + }; + unsafe { + let lock = libc::flock { + l_type: libc::F_WRLCK as libc::c_short, + l_whence: libc::SEEK_SET as libc::c_short, + l_start: 0, + l_len: 0, + l_pid: 0, + }; + loop { + if libc::fcntl(file.as_raw_fd(), libc::F_SETLKW, &lock) == 0 { + bail!("file lock obtained") + } else { + let errno = *libc::__errno(); + match errno { + libc::EINTR => continue, + _ => { + bail!("failed to wait on lock: {}", errno) + } + } + } + } + } + })) +} + async fn spawn_daemon() -> Result<()> { let mut lives = 5; + let lock32 = match wait_for_ptrace(true) { + Some(f) => f.fuse(), + None => Fuse::terminated() + }; + let lock64 = match wait_for_ptrace(false) { + Some(f) => f.fuse(), + None => Fuse::terminated() + }; + pin_mut!(lock32, lock64); loop { let mut futures = FuturesUnordered::>>>>::new(); let mut child_ids = vec![]; let daemon32 = Command::new(constants::PATH_CP_BIN32).arg("daemon").spawn(); let daemon64 = Command::new(constants::PATH_CP_BIN64).arg("daemon").spawn(); async fn spawn_daemon(mut daemon: Child) -> Result<()> { + let id = daemon.id().unwrap(); let result = daemon.wait().await?; - log::error!("Daemon process {} died: {}", daemon.id().unwrap(), result); + // FIXME: we must not get id here + log::error!("Daemon process {} died: {}", id, result); Ok(()) } if let Ok(it) = daemon32 { @@ -126,8 +187,35 @@ async fn spawn_daemon() -> Result<()> { futures.push(Box::pin(spawn_daemon(it))); } - if let Err(e) = futures.next().await.unwrap() { - error!("{}", e); + let mut stop = false; + + select! { + l32 = lock32 => { + if let Ok(Err(it)) = l32 { + error!("wait on lock 32: {}", it); + } + error!("wait on lock 32"); + stop = true; + }, + l64 = lock64 => { + if let Ok(Err(it)) = l64 { + error!("wait on lock 64: {}", it); + } + error!("wait on lock 64"); + stop = true; + }, + res = futures.select_next_some() => { + if let Err(it) = res { + error!("wait on daemon: {}", it); + } + lives -= 1; + if lives == 0 { + error!("Too many crashes, abort"); + stop = true; + } + error!("wait on daemon"); + }, + complete => panic!("completed unexpectedly") } for child in child_ids { @@ -135,12 +223,14 @@ async fn spawn_daemon() -> Result<()> { let _ = kill_process(Pid::from_raw(child as i32).unwrap(), Signal::Kill); } - lives -= 1; - if lives == 0 { - bail!("Too many crashes, abort"); + if stop { + utils::set_property(constants::PROP_CTL_SIGSTOP_OFF, "zygote")?; + utils::set_property(constants::PROP_CTL_SIGSTOP_OFF, "zygote_secondary")?; } - error!("Restarting zygote..."); utils::set_property(constants::PROP_CTL_RESTART, "zygote")?; + if stop { + bail!("Injecting failed or crashed too much times, Resetting ..."); + } } } diff --git a/zygiskd/src/zygiskd.rs b/zygiskd/src/zygiskd.rs index 2df1ef3..0167afb 100644 --- a/zygiskd/src/zygiskd.rs +++ b/zygiskd/src/zygiskd.rs @@ -13,6 +13,8 @@ use std::os::unix::{ prelude::AsRawFd, }; use std::path::PathBuf; +use std::process::exit; +use log::info; use rustix::fs::fstat; use rustix::process::{set_parent_process_death_signal, Signal}; @@ -223,6 +225,10 @@ fn handle_daemon_action(mut stream: UnixStream, context: &Context) -> Result<()> let dir = fs::File::open(dir)?; stream.send_fd(dir.as_raw_fd())?; } + DaemonSocketAction::ZygoteRestarted => { + info!("zygote restarted, exit"); + exit(0); + } } Ok(()) }