Re: [PATCH] io_uring: fix missing submitter_task ownership check in bpf_io_reg()
From: Ali Raza
Date: Thu Apr 23 2026 - 04:43:13 EST
On 4/22/26 10:20 PM, Gabriel Krisman Bertazi wrote:
> How is this a protection? I thought ctx->submitter_task is about
> IORING_SETUP_SINGLE_ISSUER. there is no permission or capability over
> it against other processes.
You are correct. submitter_task is a SINGLE_ISSUER mechanism, not a
cross-process security boundary. The "parallel path" framing in the
commit message was inaccurate.
The code confirms it - submitter_task is only assigned under
IORING_SETUP_SINGLE_ISSUER, either at ring creation [1]:
if (ctx->flags & IORING_SETUP_SINGLE_ISSUER
&& !(ctx->flags & IORING_SETUP_R_DISABLED))
ctx->submitter_task = get_task_struct(current);
or deferred to IORING_REGISTER_ENABLE_RINGS [2]:
if (ctx->flags & IORING_SETUP_SINGLE_ISSUER) {
ctx->submitter_task = get_task_struct(current);
The check at [3] I cited returns -EEXIST to prevent a second process from
registering on a SINGLE_ISSUER ring - it has the effect of blocking
cross-process access but that is not its purpose.
The commit message's Requires: line was also incomplete:
IORING_SETUP_R_DISABLED is a prerequisite but was omitted. Without
R_DISABLED, submitter_task is assigned to the ring creator immediately
at [1], so the attacker who creates the ring already satisfies
submitter_task == current - no timing window exists and the attack is
impossible regardless of whether the check is present.
> I'd argue this is a non-issue. If you have CAP_PERFMON, you are able to
> mess with the process in many ways beyond this. Otherwise, how a
> process would be able to get the fd in the first place?
On CAP_PERFMON I'd push back slightly: it is narrow (BPF program loading,
perf monitoring) and does not grant ptrace, arbitrary file write, or
process control. The BPF struct_ops path is specifically what
CAP_PERFMON enables here, not a general process manipulation capability.
But the fd acquisition question is the real barrier, and on that point
you, Jens, and Pavel are all correct. As Pavel noted, any application
that accepts a ring fd from an untrusted source and calls ENABLE_RINGS on
it is already catastrophically broken - the BPF vector is just one of
many things an attacker could do in that scenario. There is no realistic
path to get a privileged process into that state without it already being
compromised by other means.
The fix itself closes a genuine asymmetry - bpf_io_reg() is the only
registration path without this guard. I can resubmit with an elaborated
commit message, if Pavel thinks it's worth applying.
[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/io_uring/io_uring.c?id=bea8d77e45a8b77f2beca1affc9aa7ed28f39b17#n3053
[2] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/io_uring/register.c?id=bea8d77e45a8b77f2beca1affc9aa7ed28f39b17#n282
[3] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/io_uring/register.c?id=bea8d77e45a8b77f2beca1affc9aa7ed28f39b17#n733
Ali Raza