From eee000d538b5b2061240c8d9026a715368ff1791 Mon Sep 17 00:00:00 2001 From: JingMatrix Date: Mon, 27 Jul 2026 14:25:44 +0200 Subject: [PATCH] Restore the INET group patch on the manager's original gid array The parasitic manager lives inside com.android.shell, and uid 2000 has no INTERNET permission before Android 12, so we grant it ourselves: the zygisk module appends the INET group to the gid array in preAppSpecialize. That is enough for setgroups(), but not for everything. As soon as nativeForkAndSpecialize returns, Zygote#forkAndSpecialize runs NetworkUtils.setAllowNetworkingForProcess(containsInetGid(gids)); against the array it passed in, which is not the one we substituted, so it concludes that we have no network access. The flag it sets lives in libnetd_client and gates the process from the inside: with it off, dns_open_proxy() and socket() return EPERM whatever groups we really belong to. getaddrinfo then falls back to local resolution, fails as EAI_NODATA with errno EPERM, and libcore turns that into "Permission denied (missing INTERNET permission?)". The unchecked SecurityException kills the OkHttp dispatcher thread and the manager with it. LSPosed patched the caller's array too, ever since the commit that introduced the parasitic manager, and I dropped that one line while rewriting the module for the new zygisk architecture. Nothing broke on Android 12 and later because com.android.shell gained INTERNET there, so the gid array already carries the group and our patching is redundant. On Android 11 and below it is the only thing that works. Fixes #636 --- zygisk/src/main/cpp/module.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/zygisk/src/main/cpp/module.cpp b/zygisk/src/main/cpp/module.cpp index 1692239a0..7753b3d1b 100644 --- a/zygisk/src/main/cpp/module.cpp +++ b/zygisk/src/main/cpp/module.cpp @@ -260,6 +260,20 @@ void VectorModule::preAppSpecialize(zygisk::AppSpecializeArgs *args) { jint inet_gid = GID_INET; env_->SetIntArrayRegion(new_gids, original_gids_count, 1, &inet_gid); + // The new array is only seen by the native specialization, which calls setgroups(). + // Once it returns, Zygote#forkAndSpecialize keeps using the array it passed in: + // + // NetworkUtils.setAllowNetworkingForProcess(containsInetGid(gids)); + // + // That flag lives in libnetd_client and gates the whole process: without it, + // socket() and dns_open_proxy() fail with EPERM no matter which groups we really + // belong to. So overwrite the first entry of the original array as well, to make + // containsInetGid() see the INET group. Dropping this slot is harmless: the array + // has no further use once specialization is done. + if (original_gids_count > 0) { + env_->SetIntArrayRegion(args->gids, 0, 1, &inet_gid); + } + args->nice_name = env_->NewStringUTF(INJECTED_PACKAGE_NAME); args->gids = new_gids; }