->cqe_cached and ->cqe_sentinel delimit the CQ entries which can be handed out without looking at the ring. io_get_cqe_overflow() only calls io_cqe_cache_refill() if that range is too small. Without IORING_SETUP_CQE_MIXED too small means empty. With it, a 32b CQE needs two entries, and one may be left. If the refill then fails, the entry stays in the cache, and the next 16b CQE gets it without any checks. That CQE overtakes the 32b one, which went to the overflow list. The test for IO_CHECK_CQ_OVERFLOW_BIT, which is there to prevent that, is part of the refill: CQ ring with 4 entries, head == 0 16b CQE, 32b CQE tail == 3, one entry cached 32b CQE no room, the CQE overflows 16b CQE written to entry 3, ahead of the 32b CQE Forget about the rest of the cache when it is refilled. Fixes: e26dca67fde1 ("io_uring: add support for IORING_SETUP_CQE_MIXED") Reported-by: Leonid Ovchinnikov Closes: https://lore.kernel.org/io-uring/CAECZYD5OMD9vMTzjteFMMP40Dn+SWKj9SFj=43U6uO3XMnxJbw@mail.gmail.com/ Assisted-by: LLM Signed-off-by: Josef Bacik --- io_uring/io_uring.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c index a5fd1845a1d5..01187f00943a 100644 --- a/io_uring/io_uring.c +++ b/io_uring/io_uring.c @@ -729,6 +729,13 @@ bool io_cqe_cache_refill(struct io_ring_ctx *ctx, bool overflow, bool cqe32) if (!overflow && (ctx->check_cq & BIT(IO_CHECK_CQ_OVERFLOW_BIT))) return false; + /* + * A single entry may be left if a 32b CQE is asked for. It must not be + * handed out later on if this fails, as the CQE is going to overflow. + */ + ctx->cqe_cached = NULL; + ctx->cqe_sentinel = NULL; + /* * Post dummy CQE if a 32b CQE is needed and there's only room for a * 16b CQE before the ring wraps. -- 2.55.0