Commit 6f02c6b1 authored by Tom Ryan's avatar Tom Ryan Committed by Jens Axboe
Browse files

io_uring: fix physical SQE bounds check for SQE_MIXED 128-byte ops



When IORING_SETUP_SQE_MIXED is used without IORING_SETUP_NO_SQARRAY,
the boundary check for 128-byte SQE operations in io_init_req()
validated the logical SQ head position rather than the physical SQE
index.

The existing check:

  !(ctx->cached_sq_head & (ctx->sq_entries - 1))

ensures the logical position isn't at the end of the ring, which is
correct for NO_SQARRAY rings where physical == logical. However, when
sq_array is present, an unprivileged user can remap any logical
position to an arbitrary physical index via sq_array. Setting
sq_array[N] = sq_entries - 1 places a 128-byte operation at the last
physical SQE slot, causing the 128-byte memcpy in
io_uring_cmd_sqe_copy() to read 64 bytes past the end of the SQE
array.

Replace the cached_sq_head alignment check with a direct validation
of the physical SQE index, which correctly handles both sq_array and
NO_SQARRAY cases.

Fixes: 1cba30bf ("io_uring: add support for IORING_SETUP_SQE_MIXED")
Signed-off-by: default avatarTom Ryan <ryan36005@gmail.com>
Link: https://patch.msgid.link/20260310052003.72871-1-ryan36005@gmail.com


Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 177c6943
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1745,7 +1745,7 @@ static int io_init_req(struct io_ring_ctx *ctx, struct io_kiocb *req,
		 * well as 2 contiguous entries.
		 */
		if (!(ctx->flags & IORING_SETUP_SQE_MIXED) || *left < 2 ||
		    !(ctx->cached_sq_head & (ctx->sq_entries - 1)))
		    (unsigned)(sqe - ctx->sq_sqes) >= ctx->sq_entries - 1)
			return io_init_fail_req(req, -EINVAL);
		/*
		 * A 128b operation on a mixed SQ uses two entries, so we have