From: Tom Ryan <ryan36005@gmail.com>
To: io-uring@vger.kernel.org
Cc: axboe@kernel.dk, gregkh@linuxfoundation.org, kbusch@kernel.org,
csander@purestorage.com, Tom Ryan <ryan36005@gmail.com>
Subject: [PATCH liburing] test/sqe-mixed-boundary: validate physical SQE index for 128-byte ops
Date: Mon, 9 Mar 2026 22:20:03 -0700 [thread overview]
Message-ID: <20260310052003.72871-2-ryan36005@gmail.com> (raw)
In-Reply-To: <20260310052003.72871-1-ryan36005@gmail.com>
Add a test for the kernel fix that replaces the cached_sq_head alignment
check with physical SQE index validation in io_init_req() for SQE_MIXED
128-byte operations.
test_valid_position: verifies that a NOP128 at a valid physical slot
(identity-mapped via sq_array) succeeds.
test_oob_boundary: verifies that a NOP128 remapped via sq_array to the
last physical SQE slot is rejected with -EINVAL, preventing a 64-byte
OOB read past the SQE array.
Signed-off-by: Tom Ryan <ryan36005@gmail.com>
---
test/Makefile | 1 +
test/sqe-mixed-boundary.c | 182 ++++++++++++++++++++++++++++++++++++++
2 files changed, 183 insertions(+)
create mode 100644 test/sqe-mixed-boundary.c
diff --git a/test/Makefile b/test/Makefile
index 7b94a1f..a10d44c 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -253,6 +253,7 @@ test_srcs := \
sq-poll-share.c \
sqpoll-sleep.c \
sq-space_left.c \
+ sqe-mixed-boundary.c \
sqe-mixed-nop.c \
sqe-mixed-bad-wrap.c \
sqe-mixed-uring_cmd.c \
diff --git a/test/sqe-mixed-boundary.c b/test/sqe-mixed-boundary.c
new file mode 100644
index 0000000..f2e6b47
--- /dev/null
+++ b/test/sqe-mixed-boundary.c
@@ -0,0 +1,182 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Description: test SQE_MIXED physical SQE boundary validation with sq_array
+ *
+ * Verify that 128-byte operations are correctly rejected when sq_array
+ * remaps them to the last physical SQE slot, preventing a 64-byte OOB
+ * read past the SQE array.
+ */
+#include <stdio.h>
+#include <string.h>
+
+#include "liburing.h"
+#include "helpers.h"
+#include "test.h"
+
+#define NENTRIES 64
+
+/*
+ * Positive test: NOP128 at a valid physical position should succeed.
+ */
+static int test_valid_position(void)
+{
+ struct io_uring ring;
+ struct io_uring_cqe *cqe;
+ struct io_uring_sqe *sqe;
+ int ret;
+
+ ret = io_uring_queue_init(NENTRIES, &ring, IORING_SETUP_SQE_MIXED);
+ if (ret) {
+ if (ret == -EINVAL)
+ return T_EXIT_SKIP;
+ fprintf(stderr, "ring init: %d\n", ret);
+ return T_EXIT_FAIL;
+ }
+
+ sqe = io_uring_get_sqe(&ring);
+ io_uring_prep_nop(sqe);
+ sqe->user_data = 1;
+
+ sqe = io_uring_get_sqe128(&ring);
+ if (!sqe) {
+ fprintf(stderr, "get_sqe128 failed\n");
+ goto fail;
+ }
+ io_uring_prep_nop128(sqe);
+ sqe->user_data = 2;
+
+ ret = io_uring_submit(&ring);
+ if (ret < 0) {
+ fprintf(stderr, "submit: %d\n", ret);
+ goto fail;
+ }
+
+ ret = io_uring_wait_cqe(&ring, &cqe);
+ if (ret) {
+ fprintf(stderr, "wait_cqe: %d\n", ret);
+ goto fail;
+ }
+ io_uring_cqe_seen(&ring, cqe);
+
+ ret = io_uring_wait_cqe(&ring, &cqe);
+ if (ret) {
+ fprintf(stderr, "wait_cqe: %d\n", ret);
+ goto fail;
+ }
+ if (cqe->user_data == 2 && cqe->res != 0) {
+ fprintf(stderr, "NOP128 at valid position failed: %d\n",
+ cqe->res);
+ io_uring_cqe_seen(&ring, cqe);
+ goto fail;
+ }
+ io_uring_cqe_seen(&ring, cqe);
+
+ io_uring_queue_exit(&ring);
+ return T_EXIT_PASS;
+fail:
+ io_uring_queue_exit(&ring);
+ return T_EXIT_FAIL;
+}
+
+/*
+ * Negative test: NOP128 at the last physical SQE slot via sq_array remap
+ * must be rejected. Without the kernel fix, this triggers a 64-byte OOB
+ * read in io_uring_cmd_sqe_copy().
+ */
+static int test_oob_boundary(void)
+{
+ struct io_uring ring;
+ struct io_uring_cqe *cqe;
+ struct io_uring_sqe *sqe;
+ unsigned mask;
+ int ret, i, found;
+
+ ret = io_uring_queue_init(NENTRIES, &ring, IORING_SETUP_SQE_MIXED);
+ if (ret) {
+ if (ret == -EINVAL)
+ return T_EXIT_SKIP;
+ fprintf(stderr, "ring init: %d\n", ret);
+ return T_EXIT_FAIL;
+ }
+
+ mask = *ring.sq.kring_entries - 1;
+
+ /* Advance internal tail: NOP (1) + NOP128 (2) = 3 slots */
+ sqe = io_uring_get_sqe(&ring);
+ io_uring_prep_nop(sqe);
+ sqe->user_data = 1;
+
+ sqe = io_uring_get_sqe128(&ring);
+ if (!sqe) {
+ fprintf(stderr, "get_sqe128 failed\n");
+ goto fail;
+ }
+
+ /*
+ * Override: remap logical position 1 to last physical slot.
+ * Prep NOP128 there instead of the position get_sqe128 returned.
+ */
+ ring.sq.array[1] = mask;
+ memset(&ring.sq.sqes[mask], 0, sizeof(struct io_uring_sqe));
+ io_uring_prep_nop128(&ring.sq.sqes[mask]);
+ ring.sq.sqes[mask].user_data = 2;
+
+ ret = io_uring_submit(&ring);
+ if (ret < 0) {
+ fprintf(stderr, "submit: %d\n", ret);
+ goto fail;
+ }
+
+ found = 0;
+ for (i = 0; i < 3; i++) {
+ ret = io_uring_wait_cqe(&ring, &cqe);
+ if (ret)
+ break;
+ if (cqe->user_data == 2) {
+ if (cqe->res != -EINVAL) {
+ fprintf(stderr,
+ "NOP128 at last slot: expected -EINVAL, got %d\n",
+ cqe->res);
+ io_uring_cqe_seen(&ring, cqe);
+ goto fail;
+ }
+ found = 1;
+ }
+ io_uring_cqe_seen(&ring, cqe);
+ }
+
+ if (!found) {
+ fprintf(stderr, "no CQE for NOP128 boundary test\n");
+ goto fail;
+ }
+
+ io_uring_queue_exit(&ring);
+ return T_EXIT_PASS;
+fail:
+ io_uring_queue_exit(&ring);
+ return T_EXIT_FAIL;
+}
+
+int main(int argc, char *argv[])
+{
+ int ret;
+
+ if (argc > 1)
+ return T_EXIT_SKIP;
+
+ ret = test_valid_position();
+ if (ret == T_EXIT_SKIP)
+ return T_EXIT_SKIP;
+ if (ret) {
+ fprintf(stderr, "test_valid_position failed\n");
+ return T_EXIT_FAIL;
+ }
+
+ ret = test_oob_boundary();
+ if (ret) {
+ fprintf(stderr, "test_oob_boundary failed\n");
+ return ret;
+ }
+
+ return T_EXIT_PASS;
+}
--
2.50.1 (Apple Git-155)
next prev parent reply other threads:[~2026-03-10 5:20 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-09 21:20 io_uring: OOB read in SQE_MIXED mode via sq_array physical index bypass Tom Ryan
2026-03-09 21:29 ` Keith Busch
2026-03-09 21:45 ` Caleb Sander Mateos
2026-03-09 21:54 ` Keith Busch
2026-03-10 5:20 ` [PATCH v2] io_uring: fix physical SQE bounds check for SQE_MIXED 128-byte ops Tom Ryan
2026-03-10 5:20 ` Tom Ryan [this message]
2026-03-10 13:01 ` [PATCH liburing] test/sqe-mixed-boundary: validate physical SQE index for " Jens Axboe
2026-03-10 14:44 ` [PATCH v2] io_uring: fix physical SQE bounds check for SQE_MIXED " Jens Axboe
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260310052003.72871-2-ryan36005@gmail.com \
--to=ryan36005@gmail.com \
--cc=axboe@kernel.dk \
--cc=csander@purestorage.com \
--cc=gregkh@linuxfoundation.org \
--cc=io-uring@vger.kernel.org \
--cc=kbusch@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.