CVE-2026-72112
CVE-2026-72112 is a structural ownership violation in the io_uring/bpf-ops registration path, not a traditional memory safety bug. During registration, io_install_bpf() unconditionally overwrites ops->priv with the new context, but the teardown path (io_eject_bpf/bpf_io_unreg) traverses only through ops->priv to reach the context it cleans up. The first registered context becomes permanently orphaned: its ctx->loop_step still references the struct_ops trampoline that gets freed when the map is destroyed, but no teardown path reaches it. The trigger is straightforward—register the same ops map twice, pointing ring_fd at different contexts between calls, and the second registration silently orphans the first. The vulnerability is an asymmetric state management failure: ops->priv acts as an ownership sentinel in a code path that fundamentally supports multi-context operation. The proposed fix mirrors an existing guard in hid_bpf_reg() — reject registration when ops->priv is already set — which suggests this is a recognized class of re-registration vulnerability that the struct_ops link path simply missed. However, this fix patches a symptom: the underlying assumption that ops->priv marks a single, stable owner is structurally false for io_uring's asynchronous submission model, where ring contexts can be reconfigured and redirected. The attack surface is constrained by CAP_BPF + CAP_PERFMON requirements, but this isn't a strong security control in environments where BPF is legitimately used—the capability exists precisely because BPF is a high-privilege primitive. The exploit chain requires no races, no info leaks, no timing manipulation—just two sequential registration calls with different ring_fds. This architectural simplicity is the real concern: the fix is trivial and the pattern has recurred across bpf_timer, sock_map, and other struct_ops-adjacent paths. Reviewers should audit other io_uring/bpf-ops registration paths for the same missing state guard, as the class of flaw likely exists elsewhere in code that shipped after hid_bpf_reg() but before this audit.
Reviewed through automated stages and approved by a human before publication.