Skip to content

seccomp: block KSU magic-reboot fd install and neutralize GRANT_ROOT … - #262

Merged
ravindu644 merged 2 commits into
ravindu644:anlandfrom
superturtlee:fixescape
Aug 2, 2026
Merged

seccomp: block KSU magic-reboot fd install and neutralize GRANT_ROOT …#262
ravindu644 merged 2 commits into
ravindu644:anlandfrom
superturtlee:fixescape

Conversation

@superturtlee

Copy link
Copy Markdown
Contributor

…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.

…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
ravindu644 changed the base branch from anland to dev August 2, 2026 08:27
@ravindu644
ravindu644 changed the base branch from dev to anland August 2, 2026 08:28
@ravindu644
ravindu644 merged commit 41dd1cb into ravindu644:anland Aug 2, 2026
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants