seccomp: block KSU magic-reboot fd install and neutralize GRANT_ROOT … - #262
Merged
Conversation
…escape A Droidspaces container runs as real root (uid 0) in the init user namespace - the exact precondition for the KernelSU manager-uid- impersonation container escape. A process can obtain the KSU [ksu_driver] fd via the magic reboot() supercall, read the manager appid, setresuid() to it to satisfy is_manager(), then issue KSU_IOCTL_GRANT_ROOT, which installs a full-root credential (uid 0, all caps, u:r:ksu:s0) and calls disable_seccomp(), breaking out of the container. The direct uid-0 GRANT_ROOT path is guarded by is_ksu_domain(), but is_manager() short-circuits allowed_for_su() with no domain check, so the impersonation bypasses that guard. Add two complementary barriers, applied at every container/attach entry point (internal_boot + both setns attach paths) in the required order: 1. ds_ksu_neutralize_root_escape() runs BEFORE seccomp. It obtains the [ksu_driver] fd via reboot(0xDEADBEEF,0xCAFEBABE,0,&fd) and issues KSU_IOCTL_DISABLE_ESCAPE_TO_ROOT (only_root perm), setting TIF_KSU_DISABLE_ESCAPE_WITH_ROOT so escape_with_root_profile() aborts for the calling thread. Per-thread defense-in-depth. Silent no-op on non-KSU kernels (the magic reboot just returns -EINVAL, no fd). 2. ds_seccomp_apply_minimal() gains a BPF rule that denies reboot() with the KSU magic pair (EPERM). This is the load-bearing, tree-wide barrier: inherited across fork/exec, it prevents any descendant from ever obtaining the fd in the first place. Other reboot() calls are unaffected (already gated by CAP_SYS_BOOT; wrong magic returns -EINVAL in-kernel). Ordering is critical: (1) must precede (2), because the ioctl is delivered through the very fd the magic reboot installs and (2) blocks that magic reboot. The fd is closed immediately after the ioctl (it is O_CLOEXEC anyway) so it can never be reused by a descendant for GRANT_ROOT.
ravindu644
added a commit
that referenced
this pull request
Aug 2, 2026
…escape (#262) * seccomp: block KSU magic-reboot fd install and neutralize GRANT_ROOT escape A Droidspaces container runs as real root (uid 0) in the init user namespace - the exact precondition for the KernelSU manager-uid- impersonation container escape. A process can obtain the KSU [ksu_driver] fd via the magic reboot() supercall, read the manager appid, setresuid() to it to satisfy is_manager(), then issue KSU_IOCTL_GRANT_ROOT, which installs a full-root credential (uid 0, all caps, u:r:ksu:s0) and calls disable_seccomp(), breaking out of the container. The direct uid-0 GRANT_ROOT path is guarded by is_ksu_domain(), but is_manager() short-circuits allowed_for_su() with no domain check, so the impersonation bypasses that guard. Add two complementary barriers, applied at every container/attach entry point (internal_boot + both setns attach paths) in the required order: 1. ds_ksu_neutralize_root_escape() runs BEFORE seccomp. It obtains the [ksu_driver] fd via reboot(0xDEADBEEF,0xCAFEBABE,0,&fd) and issues KSU_IOCTL_DISABLE_ESCAPE_TO_ROOT (only_root perm), setting TIF_KSU_DISABLE_ESCAPE_WITH_ROOT so escape_with_root_profile() aborts for the calling thread. Per-thread defense-in-depth. Silent no-op on non-KSU kernels (the magic reboot just returns -EINVAL, no fd). 2. ds_seccomp_apply_minimal() gains a BPF rule that denies reboot() with the KSU magic pair (EPERM). This is the load-bearing, tree-wide barrier: inherited across fork/exec, it prevents any descendant from ever obtaining the fd in the first place. Other reboot() calls are unaffected (already gated by CAP_SYS_BOOT; wrong magic returns -EINVAL in-kernel). Ordering is critical: (1) must precede (2), because the ioctl is delivered through the very fd the magic reboot installs and (2) blocks that magic reboot. The fd is closed immediately after the ioctl (it is O_CLOEXEC anyway) so it can never be reused by a descendant for GRANT_ROOT. * Change log message for escape_with_root disable --------- Co-authored-by: Ravindu Deshan <Droidcasts@protonmail.com>
superturtlee
added a commit
to superturtlee/Droidspaces-OSS
that referenced
this pull request
Aug 7, 2026
…NT_ROOT escape (ravindu644#262)" This reverts commit 5228bf7.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
…escape
A Droidspaces container runs as real root (uid 0) in the init user namespace - the exact precondition for the KernelSU manager-uid- impersonation container escape. A process can obtain the KSU [ksu_driver] fd via the magic reboot() supercall, read the manager appid, setresuid() to it to satisfy is_manager(), then issue KSU_IOCTL_GRANT_ROOT, which installs a full-root credential (uid 0, all caps, u:r:ksu:s0) and calls disable_seccomp(), breaking out of the container. The direct uid-0 GRANT_ROOT path is guarded by is_ksu_domain(), but is_manager() short-circuits allowed_for_su() with no domain check, so the impersonation bypasses that guard.
Add two complementary barriers, applied at every container/attach entry point (internal_boot + both setns attach paths) in the required order:
ds_ksu_neutralize_root_escape() runs BEFORE seccomp. It obtains the [ksu_driver] fd via reboot(0xDEADBEEF,0xCAFEBABE,0,&fd) and issues KSU_IOCTL_DISABLE_ESCAPE_TO_ROOT (only_root perm), setting TIF_KSU_DISABLE_ESCAPE_WITH_ROOT so escape_with_root_profile() aborts for the calling thread. Per-thread defense-in-depth. Silent no-op on non-KSU kernels (the magic reboot just returns -EINVAL, no fd).
ds_seccomp_apply_minimal() gains a BPF rule that denies reboot() with the KSU magic pair (EPERM). This is the load-bearing, tree-wide barrier: inherited across fork/exec, it prevents any descendant from ever obtaining the fd in the first place. Other reboot() calls are unaffected (already gated by CAP_SYS_BOOT; wrong magic returns -EINVAL in-kernel).
Ordering is critical: (1) must precede (2), because the ioctl is delivered through the very fd the magic reboot installs and (2) blocks that magic reboot.
The fd is closed immediately after the ioctl (it is O_CLOEXEC anyway) so it can never be reused by a descendant for GRANT_ROOT.