summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavel Begunkov <asml.silence@gmail.com>2025-09-19 12:11:57 +0100
committerJens Axboe <axboe@kernel.dk>2025-09-19 07:06:43 -0600
commit7ea24326e72dad7cd326bedd8442c162ae23df9d (patch)
tree6e4c8de92490ec6f2c160e337e4bb0f317298c98
parent2408d1783204920880f929a7a3087c76f5a59c13 (diff)
io_uring/query: cap number of queries
If a query chain forms a cycle, it'll be looping in the kernel until the process is killed. It might be fine as any such mistake can be easily uncovered during testing, but it's still nicer to let it break out of the syscall if it executed too many queries. Suggested-by: Jens Axboe <axboe@kernel.dk> Signed-off-by: Pavel Begunkov <asml.silence@gmail.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
-rw-r--r--io_uring/query.c6
1 files changed, 5 insertions, 1 deletions
diff --git a/io_uring/query.c b/io_uring/query.c
index c2183daf5a46..645301bd2c82 100644
--- a/io_uring/query.c
+++ b/io_uring/query.c
@@ -6,6 +6,7 @@
#include "io_uring.h"
#define IO_MAX_QUERY_SIZE (sizeof(struct io_uring_query_opcode))
+#define IO_MAX_QUERY_ENTRIES 1000
static ssize_t io_query_ops(void *data)
{
@@ -74,7 +75,7 @@ int io_query(struct io_ring_ctx *ctx, void __user *arg, unsigned nr_args)
{
char entry_buffer[IO_MAX_QUERY_SIZE];
void __user *uhdr = arg;
- int ret;
+ int ret, nr = 0;
memset(entry_buffer, 0, sizeof(entry_buffer));
@@ -89,6 +90,9 @@ int io_query(struct io_ring_ctx *ctx, void __user *arg, unsigned nr_args)
return ret;
uhdr = u64_to_user_ptr(next_hdr);
+ /* Have some limit to avoid a potential cycle */
+ if (++nr >= IO_MAX_QUERY_ENTRIES)
+ return -ERANGE;
if (fatal_signal_pending(current))
return -EINTR;
cond_resched();