Linux io-uring development
 help / color / mirror / Atom feed
* [PATCH io_uring] io_uring/msg_ring: reject CQE32 flag pass-through to normal rings
@ 2026-07-01  8:11 Melbin K Mathew
  2026-07-01 11:42 ` Jens Axboe
  0 siblings, 1 reply; 2+ messages in thread
From: Melbin K Mathew @ 2026-07-01  8:11 UTC (permalink / raw)
  To: axboe; +Cc: io-uring, linux-kernel, Melbin K Mathew

IORING_OP_MSG_RING with IORING_MSG_RING_FLAGS_PASS allows a sender to
pass completion flags through sqe->file_index. If the sender sets
IORING_CQE_F_32 in file_index, the target-side completion path treats
it as a 32-byte CQE and writes big_cqe[0] and big_cqe[1] into the CQ
ring regardless of whether the target ring was created with
IORING_SETUP_CQE32 or IORING_SETUP_CQE_MIXED.

On a normal 16-byte CQE ring, this writes 16 extra bytes (two u64
big_cqe fields) into the next CQE slot in the ring buffer. This was
confirmed by poisoning the adjacent slot with known values and observing
them being overwritten after the pass-through, while the CQ tail
advanced by only one slot.

Add a helper io_msg_ring_cqe_flags() that validates the flags before
they are forwarded, and use it in both the local and remote data paths.
Reject with -EINVAL when IORING_CQE_F_32 is passed to a ring that does
not support CQE32 or mixed CQE modes. In the remote path, this guard
runs before the target request allocation to avoid a leak on error.

Fixes: cbeb47a7b5f0 ("io_uring/msg_ring: Pass custom flags to the cqe")
Signed-off-by: Melbin K Mathew <mlbnkm1@gmail.com>
---
Notes:
    Testing on Linux 7.2-rc1 with KASAN and UBSAN enabled:

    Unpatched kernel: MSG_RING with IORING_MSG_RING_FLAGS_PASS and
    IORING_CQE_F_32 posts CQE_F_32 to a normal target ring. Target CQ
    tail advances by one while the adjacent unpublished CQ slot is
    overwritten (confirmed by poisoning the adjacent slot with known
    values and observing them zeroed after the pass-through).

    Patched kernel: sender receives -EINVAL. Target CQ tail does not
    advance. Adjacent poisoned slot remains intact.

    git apply --check: OK
    checkpatch --strict: 0 errors, 0 warnings, 0 checks
    make W=1 io_uring/msg_ring.o: clean

 io_uring/msg_ring.c | 34 +++++++++++++++++++++++++++-------
 1 file changed, 27 insertions(+), 7 deletions(-)

diff --git a/io_uring/msg_ring.c b/io_uring/msg_ring.c
index 3ff9098573..3067c93439 100644
--- a/io_uring/msg_ring.c
+++ b/io_uring/msg_ring.c
@@ -93,19 +93,38 @@ static void io_msg_remote_post(struct io_ring_ctx *ctx, struct io_kiocb *req,
 	io_req_task_work_add_remote(req, IOU_F_TWQ_LAZY_WAKE);
 }
 
+static int io_msg_ring_cqe_flags(struct io_ring_ctx *target_ctx,
+				 const struct io_msg *msg, u32 *flags)
+{
+	*flags = 0;
+
+	if (!(msg->flags & IORING_MSG_RING_FLAGS_PASS))
+		return 0;
+
+	*flags = msg->cqe_flags;
+	if ((*flags & IORING_CQE_F_32) &&
+	    !(target_ctx->flags & (IORING_SETUP_CQE32 |
+				   IORING_SETUP_CQE_MIXED)))
+		return -EINVAL;
+
+	return 0;
+}
+
 static int io_msg_data_remote(struct io_ring_ctx *target_ctx,
 			      struct io_msg *msg)
 {
 	struct io_kiocb *target;
-	u32 flags = 0;
+	u32 flags;
+	int ret;
 
-	target = kmem_cache_alloc(req_cachep, GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO)  ;
+	ret = io_msg_ring_cqe_flags(target_ctx, msg, &flags);
+	if (ret)
+		return ret;
+
+	target = kmem_cache_alloc(req_cachep, GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO);
 	if (unlikely(!target))
 		return -ENOMEM;
 
-	if (msg->flags & IORING_MSG_RING_FLAGS_PASS)
-		flags = msg->cqe_flags;
-
 	io_msg_remote_post(target_ctx, target, msg->len, flags, msg->user_data);
 	return 0;
 }
@@ -130,8 +149,9 @@ static int __io_msg_ring_data(struct io_ring_ctx *target_ctx,
 	if (io_msg_need_remote(target_ctx))
 		return io_msg_data_remote(target_ctx, msg);
 
-	if (msg->flags & IORING_MSG_RING_FLAGS_PASS)
-		flags = msg->cqe_flags;
+	ret = io_msg_ring_cqe_flags(target_ctx, msg, &flags);
+	if (ret)
+		return ret;
 
 	ret = -EOVERFLOW;
 	if (target_ctx->flags & IORING_SETUP_IOPOLL) {
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-07-01 11:42 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-01  8:11 [PATCH io_uring] io_uring/msg_ring: reject CQE32 flag pass-through to normal rings Melbin K Mathew
2026-07-01 11:42 ` Jens Axboe

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox