From 1419174a6c483f731747811084cf7449769205a1 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 16 Oct 2024 07:17:27 -0600 Subject: [PATCH] test/regbuf-clone: test dummy ubuf cloning The 6.12-rc kernels had a bug where the cloning would attempt to grab a reference to a dummy ubuf that was assigned, which would crash the kernel. Add a test case for that. Signed-off-by: Jens Axboe --- test/regbuf-clone.c | 60 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/test/regbuf-clone.c b/test/regbuf-clone.c index 1ef2c8e25..59b99e186 100644 --- a/test/regbuf-clone.c +++ b/test/regbuf-clone.c @@ -15,6 +15,8 @@ #define NR_VECS 64 #define BUF_SIZE 8192 +static int no_buf_clone; + static int test(int reg_src, int reg_dst) { struct iovec vecs[NR_VECS]; @@ -54,6 +56,7 @@ static int test(int reg_src, int reg_dst) ret = io_uring_clone_buffers(&dst, &src); if (ret == -EINVAL) { /* no buffer copy support */ + no_buf_clone = true; return T_EXIT_SKIP; } else if (ret != -ENXIO) { fprintf(stderr, "empty copy: %d\n", ret); @@ -144,6 +147,53 @@ static int test(int reg_src, int reg_dst) return T_EXIT_PASS; } +static int test_dummy(void) +{ + struct iovec vec = { }; + struct io_uring src, dst; + int ret; + + ret = io_uring_queue_init(1, &src, 0); + if (ret) { + fprintf(stderr, "ring_init: %d\n", ret); + return T_EXIT_FAIL; + } + ret = io_uring_queue_init(1, &dst, 0); + if (ret) { + fprintf(stderr, "ring_init: %d\n", ret); + return T_EXIT_FAIL; + } + + ret = io_uring_register_buffers(&src, &vec, 1); + if (ret < 0) { + fprintf(stderr, "failed to register dummy buffer: %d\n", ret); + return T_EXIT_FAIL; + } + + ret = io_uring_clone_buffers(&dst, &src); + if (ret) { + fprintf(stderr, "clone dummy buf: %d\n", ret); + return T_EXIT_FAIL; + } + + ret = io_uring_unregister_buffers(&src); + if (ret) { + fprintf(stderr, "rsc unregister buffers: %d\n", ret); + return T_EXIT_FAIL; + } + + ret = io_uring_unregister_buffers(&dst); + if (ret) { + fprintf(stderr, "dst unregister buffers: %d\n", ret); + return T_EXIT_FAIL; + } + + io_uring_queue_exit(&src); + io_uring_queue_exit(&dst); + + return T_EXIT_PASS; +} + int main(int argc, char *argv[]) { int ret; @@ -158,6 +208,8 @@ int main(int argc, char *argv[]) fprintf(stderr, "test 0 0 failed\n"); return T_EXIT_FAIL; } + if (no_buf_clone) + return T_EXIT_SKIP; ret = test(0, 1); if (ret == T_EXIT_SKIP) { @@ -183,5 +235,13 @@ int main(int argc, char *argv[]) return T_EXIT_FAIL; } + ret = test_dummy(); + if (ret == T_EXIT_SKIP) { + return T_EXIT_SKIP; + } else if (ret != T_EXIT_PASS) { + fprintf(stderr, "test_dummy failed\n"); + return T_EXIT_FAIL; + } + return T_EXIT_PASS; }