Re: [PATCH v2] io_uring/fdinfo: ignore IORING_CQE_F_32 in last CQ array slot
From: Jann Horn
Date: Mon Sep 21 2026 - 12:51:21 EST
On Mon, Sep 21, 2026 at 6:45 PM Jens Axboe <axboe@xxxxxxxxx> wrote:
> On 9/11/26 12:03 PM, Jens Axboe wrote:
> > On Fri, 11 Sep 2026 19:56:13 +0200, Jann Horn wrote:
> >> A cqe32 entry spans two CQ array slots, so the last CQ array slot can't
> >> contain a cqe32 entry. If the CQ tail points at the last CQ array slot and
> >> the kernel wants to write a cqe32 entry, it uses io_fill_nop_cqe() to pad
> >> the last CQ array slot with a dummy entry and make the tail wrap around.
> >>
> >> However, malicious userspace can directly set IORING_CQE_F_32 on the last
> >> CQ array slot, causing __io_uring_show_fdinfo() to read the second cqe32
> >> half from beyond the CQ array. Change __io_uring_show_fdinfo() to
> >> explicitly ignore the IORING_CQE_F_32 flag in this case.
> >>
> >> [...]
> >
> > Applied, thanks!
> >
> > [1/1] io_uring/fdinfo: ignore IORING_CQE_F_32 in last CQ array slot
> > commit: ab394388d05977f369e8e8d1beceae47fc3c5e72
>
> Back at it, and wanted to move this to 7.4, as there's no point
> expediting it for 7.3. While doing so, I took another look. And
> cq_head is the raw ring counter, not a masked index. Hence I think:
>
> bool is_last_cqarray_slot = (cq_head == cq_mask);
>
> this is incorrect, as it won't work past the very first run around the
> ring. I fixed it up as:
>
> bool is_last_cqarray_slot = (cq_head & cq_mask) == cq_mask;
>
> Just a heads up! Let me know if you disagree or want to send a v3
> instead.
Ah, bleh, of course, my bad. Thanks for catching that!