From ecb31eed40d16c8b0adcef56383b6e326dc461db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=AE=8B=E9=A1=B5?= Date: Wed, 8 Nov 2023 16:34:38 +0800 Subject: [PATCH] Prevent Zygisk from closing new fds created by Zygote itself --- native/src/zygisk/hook.cpp | 47 ++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/native/src/zygisk/hook.cpp b/native/src/zygisk/hook.cpp index 5e9bfe90a..297c196a1 100644 --- a/native/src/zygisk/hook.cpp +++ b/native/src/zygisk/hook.cpp @@ -48,7 +48,6 @@ bool should_unmap_zygisk = false; // Current context HookContext *g_ctx; -bitset *g_allowed_fds = nullptr; const JNINativeInterface *old_functions = nullptr; JNINativeInterface *new_functions = nullptr; const NativeBridgeRuntimeCallbacks *runtime_callbacks = nullptr; @@ -71,6 +70,7 @@ struct HookContext { int pid; bitset flags; uint32_t info_flags; + bitset allowed_fds; vector exempted_fds; struct RegisterInfo { @@ -411,32 +411,30 @@ int sigmask(int how, int signum) { } void HookContext::fork_pre() { - if (g_allowed_fds == nullptr) { - default_new(g_allowed_fds); - - auto &allowed_fds = *g_allowed_fds; - // Record all open fds - auto dir = xopen_dir("/proc/self/fd"); - for (dirent *entry; (entry = xreaddir(dir.get()));) { - int fd = parse_int(entry->d_name); - if (fd < 0 || fd >= MAX_FD_SIZE) { - close(fd); - continue; - } - allowed_fds[fd] = true; - } - // The dirfd will be closed once out of scope - allowed_fds[dirfd(dir.get())] = false; - // logd_fd should be handled separately - if (int fd = zygisk_get_logd(); fd >= 0) { - allowed_fds[fd] = false; - } - } - // Do our own fork before loading any 3rd party code // First block SIGCHLD, unblock after original fork is done sigmask(SIG_BLOCK, SIGCHLD); pid = old_fork(); + + if (!is_child()) + return; + + // Record all open fds + auto dir = xopen_dir("/proc/self/fd"); + for (dirent *entry; (entry = xreaddir(dir.get()));) { + int fd = parse_int(entry->d_name); + if (fd < 0 || fd >= MAX_FD_SIZE) { + close(fd); + continue; + } + allowed_fds[fd] = true; + } + // The dirfd will be closed once out of scope + allowed_fds[dirfd(dir.get())] = false; + // logd_fd should be handled separately + if (int fd = zygisk_get_logd(); fd >= 0) { + allowed_fds[fd] = false; + } } void HookContext::fork_post() { @@ -447,11 +445,10 @@ void HookContext::fork_post() { void HookContext::sanitize_fds() { zygisk_close_logd(); - if (!is_child() || g_allowed_fds == nullptr) { + if (!is_child()) { return; } - auto &allowed_fds = *g_allowed_fds; if (can_exempt_fd() && !exempted_fds.empty()) { auto update_fd_array = [&](int old_len) -> jintArray { jintArray array = env->NewIntArray(static_cast(old_len + exempted_fds.size()));