From 9119bc80276b78b57cd4ed1219c22b3eafe43222 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 4 Oct 2026 18:46:17 +0000 Subject: [PATCH] zygisk: exempt the manager host from DENY_PROCESS_PTRACE on GrapheneOS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The parasitic manager could not launch on GrapheneOS even with the DCL workaround in place: tapping its notification (or the shortcut) aborted the host spawn with selinux_android_setcontext(2000, 0, "platform:privapp:targetSdkVersion=36:partition=system:complete", "org.matrix.vector.manager", grapheneos_flags: "100") failed -> zygote64 SIGABRT (crash-loop) grapheneos_flags is SELinuxFlags, printed in hex: 0x100 == 1<<8 == DENY_PROCESS_PTRACE. SELinuxFlags.get() starts from ALL_RESTRICTIONS and only clears DENY_PROCESS_PTRACE when AswDenyNativeDebug returns false, but that switch is immutably true for every system app — and the host, com.android.shell, is a system app. GrapheneDclHooker already forces the three DCL switches off for the host, which is why bits 0..7 are gone and the surviving flag is exactly 0x100. The manager is injected over ptrace (NeoZygisk/Zygisk), so with DENY_PROCESS_PTRACE armed the context transition for the host process fails and the spawn aborts. Add AswDenyNativeDebug to the set of switches forced off for the manager host (same getImmutableValue override, same host-only guard). That clears DENY_PROCESS_PTRACE for the host alone, so the parasitic manager specializes and the notification opens it — module only, no standalone manager APK required. Every other app keeps GrapheneOS's verdict. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01SNf36vn5z9zfgzzEF5LXRJ --- .../main/kotlin/org/matrix/vector/GrapheneDclHooker.kt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/zygisk/src/main/kotlin/org/matrix/vector/GrapheneDclHooker.kt b/zygisk/src/main/kotlin/org/matrix/vector/GrapheneDclHooker.kt index 28c38c754..61d93ecda 100644 --- a/zygisk/src/main/kotlin/org/matrix/vector/GrapheneDclHooker.kt +++ b/zygisk/src/main/kotlin/org/matrix/vector/GrapheneDclHooker.kt @@ -39,6 +39,16 @@ object GrapheneDclHooker { "android.ext.settings.app.AswRestrictMemoryDynCodeLoading", "android.ext.settings.app.AswRestrictStorageDynCodeLoading", "android.ext.settings.app.AswRestrictWebViewDynCodeLoading", + // DENY_PROCESS_PTRACE (SELinuxFlags bit 1<<8). SELinuxFlags.get() leaves it armed + // unless AswDenyNativeDebug returns false, and that switch is immutably true for every + // system app — including the manager's host, com.android.shell. The parasitic manager + // is injected over ptrace (NeoZygisk/Zygisk), so with this flag set the host's + // specialization aborts in selinux_android_setcontext2(): + // "selinux_android_setcontext(2000, 0, "platform:privapp:...", "", + // grapheneos_flags: "100") failed" -> zygote SIGABRT, crash-looping the manager. + // (The three DCL switches above already strip bits 0..7, which is why the surviving + // flag is exactly 0x100.) Exempting the host clears it so the spawn succeeds. + "android.ext.settings.app.AswDenyNativeDebug", ) @JvmStatic