A previous commit changed the logic around how SQ entries are iterated, and as a result, had a few bugs. One is that it fully trusts the SQ head and tail, which are user exposed. Another is that it fails to increment the SQ head if the SQ index is out of range. Fix both of those up, reverting to the previous logic of how to iterate SQ entries. Fixes: 1cba30bf9fdd ("io_uring: add support for IORING_SETUP_SQE_MIXED") Reported-by: syzbot+10a9b495f54a17b607a6@syzkaller.appspotmail.com Tested-by: syzbot+10a9b495f54a17b607a6@syzkaller.appspotmail.com Signed-off-by: Jens Axboe --- diff --git a/io_uring/fdinfo.c b/io_uring/fdinfo.c index a3ce92183540..248006424cab 100644 --- a/io_uring/fdinfo.c +++ b/io_uring/fdinfo.c @@ -67,6 +67,7 @@ static void __io_uring_show_fdinfo(struct io_ring_ctx *ctx, struct seq_file *m) unsigned int cq_head = READ_ONCE(r->cq.head); unsigned int cq_tail = READ_ONCE(r->cq.tail); unsigned int sq_shift = 0; + unsigned int sq_entries; int sq_pid = -1, sq_cpu = -1; u64 sq_total_time = 0, sq_work_time = 0; unsigned int i; @@ -89,17 +90,18 @@ static void __io_uring_show_fdinfo(struct io_ring_ctx *ctx, struct seq_file *m) seq_printf(m, "CqTail:\t%u\n", cq_tail); seq_printf(m, "CachedCqTail:\t%u\n", data_race(ctx->cached_cq_tail)); seq_printf(m, "SQEs:\t%u\n", sq_tail - sq_head); - while (sq_head < sq_tail) { + sq_entries = min(sq_tail - sq_head, ctx->sq_entries); + for (i = 0; i < sq_entries; i++) { + unsigned int entry = i + sq_head; struct io_uring_sqe *sqe; unsigned int sq_idx; bool sqe128 = false; u8 opcode; if (ctx->flags & IORING_SETUP_NO_SQARRAY) - sq_idx = sq_head & sq_mask; + sq_idx = entry & sq_mask; else - sq_idx = READ_ONCE(ctx->sq_array[sq_head & sq_mask]); - + sq_idx = READ_ONCE(ctx->sq_array[entry & sq_mask]); if (sq_idx > sq_mask) continue; @@ -141,7 +143,6 @@ static void __io_uring_show_fdinfo(struct io_ring_ctx *ctx, struct seq_file *m) } } seq_printf(m, "\n"); - sq_head++; } seq_printf(m, "CQEs:\t%u\n", cq_tail - cq_head); while (cq_head < cq_tail) { -- Jens Axboe