diff --git a/loader/src/include/daemon.hpp b/loader/src/include/daemon.hpp index f88445f..9b10702 100644 --- a/loader/src/include/daemon.hpp +++ b/loader/src/include/daemon.hpp @@ -73,6 +73,8 @@ void Init(const char* path); std::string GetTmpPath(); +int Connect(uint8_t retry); + bool PingHeartbeat(); std::vector ReadModules(); diff --git a/loader/src/injector/hook.cpp b/loader/src/injector/hook.cpp index e828a6a..61b8698 100644 --- a/loader/src/injector/hook.cpp +++ b/loader/src/injector/hook.cpp @@ -106,10 +106,14 @@ DCL_HOOK_FUNC(static int, unshare, int flags) { if (g_ctx && (flags & CLONE_NEWNS) && !(g_ctx->flags & SERVER_FORK_AND_SPECIALIZE)) { bool should_unmount = !(g_ctx->info_flags & (PROCESS_IS_MANAGER | PROCESS_GRANTED_ROOT)) && g_ctx->flags & DO_REVERT_UNMOUNT; - if (!should_unmount && g_hook->zygote_unmounted) { + if (!should_unmount && g_hook->zygote_unmounted_times > 0) { ZygiskContext::update_mount_namespace(zygiskd::MountNamespace::Root); } - bool is_zygote_clean = g_hook->zygote_unmounted && g_hook->zygote_traces.size() == 0; + + // WARNING: we may miss traces (with low possibility) due to lack of unmounted times. + // However, checking via `check_zygote_traces` frequently is unnecessary for most users. + bool is_zygote_clean = + g_hook->zygote_unmounted_times > 0 && g_hook->zygote_traces.size() == 0; if (should_unmount && !is_zygote_clean) { ZygiskContext::update_mount_namespace(zygiskd::MountNamespace::Clean); } diff --git a/loader/src/injector/module.cpp b/loader/src/injector/module.cpp index fb0a8c0..c54474f 100644 --- a/loader/src/injector/module.cpp +++ b/loader/src/injector/module.cpp @@ -331,21 +331,24 @@ void ZygiskContext::run_modules_post() { void ZygiskContext::app_specialize_pre() { uid_t uid = args.app->uid; - // Correct uid for isolated services - if (uid >= AID_ISOLATED_START && uid <= AID_ISOLATED_END && args.app->app_data_dir) { + bool is_isolated_aid = uid >= AID_ISOLATED_START && uid <= AID_ISOLATED_END; + if (is_isolated_aid && args.app->app_data_dir) { const char *data_dir = nullptr; data_dir = env->GetStringUTFChars(args.app->app_data_dir, nullptr); if (data_dir != nullptr) { struct stat st; if (stat(data_dir, &st) != -1) { + // Correct uid for isolated services uid = st.st_uid; - LOGV("identify isolated service [uid:%d, data_dir:%s]", uid, data_dir); } + LOGV("Found isolated process [uid:%d, data_dir:%s]", uid, data_dir); env->ReleaseStringUTFChars(args.app->app_data_dir, data_dir); } } - if (info_flags == 0) info_flags = zygiskd::GetProcessFlags(uid); + bool skip_zygiskd = is_isolated_aid && zygiskd::Connect(1) == -1; + + if (!skip_zygiskd && info_flags == 0) info_flags = zygiskd::GetProcessFlags(uid); if ((info_flags & UNMOUNT_MASK) == UNMOUNT_MASK) { LOGI("[%s] is on the denylist", process); @@ -353,7 +356,7 @@ void ZygiskContext::app_specialize_pre() { } flags |= APP_SPECIALIZE; - run_modules_pre(); + if (!skip_zygiskd) run_modules_pre(); } void ZygiskContext::app_specialize_post() { @@ -447,10 +450,10 @@ void ZygiskContext::nativeForkAndSpecialize_pre() { LOGV("pre forkAndSpecialize [%s]", process); flags |= APP_FORK_AND_SPECIALIZE; - if (!g_hook->zygote_unmounted && g_hook->zygote_traces.size() == 0) { + if (g_hook->zygote_unmounted_times < 5 && g_hook->zygote_traces.size() == 0) { info_flags = zygiskd::GetProcessFlags(args.app->uid); - g_hook->zygote_traces = check_zygote_traces(info_flags); + g_hook->zygote_traces = check_zygote_traces(info_flags, g_hook->zygote_unmounted_times); if (!abort_zygote_unmount(g_hook->zygote_traces, info_flags)) { auto removal_predicate = [](const mount_info &trace) { @@ -467,7 +470,7 @@ void ZygiskContext::nativeForkAndSpecialize_pre() { g_hook->zygote_traces.end(), removal_predicate); g_hook->zygote_traces.erase(new_end, g_hook->zygote_traces.end()); - g_hook->zygote_unmounted = true; + g_hook->zygote_unmounted_times += 1; } } diff --git a/loader/src/injector/module.hpp b/loader/src/injector/module.hpp index cd33df0..0ec84e6 100644 --- a/loader/src/injector/module.hpp +++ b/loader/src/injector/module.hpp @@ -324,7 +324,7 @@ struct HookContext { bool should_spoof_maps = false; bool should_unmap = false; bool skip_hooking_unloader = false; - bool zygote_unmounted = false; + size_t zygote_unmounted_times = 0; jint MODIFIER_NATIVE = 0; jmethodID member_getModifiers = nullptr; std::vector cached_map_infos = {}; diff --git a/loader/src/injector/unmount.cpp b/loader/src/injector/unmount.cpp index 239b5b9..845b8be 100644 --- a/loader/src/injector/unmount.cpp +++ b/loader/src/injector/unmount.cpp @@ -92,7 +92,7 @@ std::vector parse_mount_info(const char* pid) { return result; } -std::vector check_zygote_traces(uint32_t info_flags) { +std::vector check_zygote_traces(uint32_t info_flags, size_t round) { std::vector traces; auto mount_infos = parse_mount_info("self"); @@ -150,7 +150,7 @@ std::vector check_zygote_traces(uint32_t info_flags) { std::sort(traces.begin(), traces.end(), [](const mount_info& a, const mount_info& b) { return a.id > b.id; }); - LOGV("found %zu mounting traces in zygote.", traces.size()); + LOGV("found %zu mounting traces in zygote [round: %zu].", traces.size(), round); return traces; } diff --git a/loader/src/injector/zygisk.hpp b/loader/src/injector/zygisk.hpp index 78ba69c..14e0d38 100644 --- a/loader/src/injector/zygisk.hpp +++ b/loader/src/injector/zygisk.hpp @@ -33,4 +33,4 @@ void spoof_zygote_fossil(char *search_from, char *search_to, const char *anchor) void send_seccomp_event_if_needed(); -std::vector check_zygote_traces(uint32_t info_flags); +std::vector check_zygote_traces(uint32_t info_flags, size_t round);