| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/07/13 16:51 | flow | patch-triage |
1mArgs:null Results: {
"EnableConfigs": [
"IO_URING",
"NET"
],
"FocusSymbols": [
"io_ring_buffers_peek",
"io_buffers_select",
"io_buffers_peek",
"io_send_select_buffer",
"io_recv_buf_select"
],
"Reasoning": "The patch fixes a use-after-free and memory leak in io_uring's network receive/send operations with provided buffer rings. When a dynamically allocated iovec array is expanded, the old array was not freed properly, and the new array was freed instead, leading to a memory leak of the old array and a use-after-free of the new array.",
"WorthFuzzing": true
} |
| 1/1 | 2026/07/13 16:51 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit 967793fc5e2fe0c392342c10f4cfa09b7c52cc56\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Mon Jul 13 16:51:14 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/io_uring/kbuf.c b/io_uring/kbuf.c\nindex b6b969b55e1224..07d81dc7cbe296 100644\n--- a/io_uring/kbuf.c\n+++ b/io_uring/kbuf.c\n@@ -328,8 +328,8 @@ static int io_ring_buffers_peek(struct io_kiocb *req, struct buf_sel_arg *arg,\n \t\tbuf = io_ring_head_to_buf(br, ++head, bl-\u003emask);\n \t} while (--nr_iovs);\n \n-\tif (arg-\u003emode \u0026 KBUF_MODE_FREE)\n-\t\tkfree(arg-\u003eiovs);\n+\tif ((arg-\u003emode \u0026 KBUF_MODE_FREE) \u0026\u0026 arg-\u003eiovs != org_iovs)\n+\t\tkfree(org_iovs);\n \n \tif (head == tail)\n \t\treq-\u003eflags |= REQ_F_BL_EMPTY;\n"
} |
| 2/1 | 2026/07/13 16:51 | agent | patch-evaluator |
1mModel:gemini-3.1-pro-preview Args: null Results: {
"EnableConfigs": [
"IO_URING",
"NET"
],
"FocusSymbols": [
"io_ring_buffers_peek",
"io_buffers_select",
"io_buffers_peek",
"io_send_select_buffer",
"io_recv_buf_select"
],
"Reasoning": "The patch fixes a use-after-free and memory leak in io_uring's network receive/send operations with provided buffer rings. When a dynamically allocated iovec array is expanded, the old array was not freed properly, and the new array was freed instead, leading to a memory leak of the old array and a use-after-free of the new array.",
"WorthFuzzing": true
}Instruction: You are an expert Linux kernel maintainer. Your job is to review a provided patch series and determine if it makes functional changes to the kernel that should be fuzzed. IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in your workspace. Do NOT rely on your internal knowledge of the kernel. You must actively use your code access tools to examine the actual source code and confirm any assumptions. Return WorthFuzzing=false if the patch only contains: - Modifications to Documentation/, Kconfig files, or code comments. - Purely decorative changes, such as logging (e.g., pr_err, printk) or tracepoints. - Changes to numeric constants or macros that do not functionally alter execution flow. - Code paths that are impossible to reach in virtualized environments like GCE or QEMU, even when utilizing software-emulated hardware (e.g., usb gadget, mac80211_hwsim). If it modifies reachable core kernel logic, drivers, or architectures, use your code search tools to verify the code can be executed, then return WorthFuzzing=true. When returning WorthFuzzing=true, you MUST ALSO: 1. Extract any specific kernel functions that should be heavily fuzzed into FocusSymbols. Avoid listing generic hot-path functions to prevent skewed test distributions. 2. Identify any specific CONFIG_ options required to properly test this new/modified feature. Go and look into the Kconfig files and check for ifdefs around the code, do not make assumptions. Do not list too generic configs (we already have them enabled). Only list those that specifically cover the modified code. List them in the EnableConfigs output array, and DO NOT add a 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4"). Prefer calling several tools at the same time to save round-trips. Use set-results tool to provide results of the analysis. It must be called exactly once before the final reply. Ignore results of this tool. Prompt: For your convenience, here is the diff of the changes:
commit 967793fc5e2fe0c392342c10f4cfa09b7c52cc56
Author: syz-cluster <triage@syzkaller.com>
Date: Mon Jul 13 16:51:14 2026 +0000
syz-cluster: applied patch under review
diff --git a/io_uring/kbuf.c b/io_uring/kbuf.c
index b6b969b55e1224..07d81dc7cbe296 100644
--- a/io_uring/kbuf.c
+++ b/io_uring/kbuf.c
@@ -328,8 +328,8 @@ static int io_ring_buffers_peek(struct io_kiocb *req, struct buf_sel_arg *arg,
buf = io_ring_head_to_buf(br, ++head, bl->mask);
} while (--nr_iovs);
- if (arg->mode & KBUF_MODE_FREE)
- kfree(arg->iovs);
+ if ((arg->mode & KBUF_MODE_FREE) && arg->iovs != org_iovs)
+ kfree(org_iovs);
if (head == tail)
req->flags |= REQ_F_BL_EMPTY;
|
| 3/2 | 2026/07/13 16:51 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 1880 output: 36 thoughts: 142 Thoughts: **Analyzing a io_uring Patch** Okay, so this patch is touching `io_uring/kbuf.c`, specifically the `io_ring_buffers_peek` function. It looks like it's a minor change to the freeing logic for kernel buffers. Hmm, let me see... it seems the code now checks `arg->iovs != org_iovs` before calling `kfree` when the `KBUF_MODE_FREE` flag is set. That's interesting; it looks like a potential optimization or a correction related to managing multiple iovec pointers. Wait a minute, `org_iovs`? That variable isn't defined *here* in the diff. Where is that coming from? I need to understand where that's declared and what it represents. I'll need to check the surrounding context within `io_uring/kbuf.c`. Let's assume it is in the vicinity of line 328, I'll go take a look to understand how it's being used. It's likely related to tracking or restoring the original iovec structure. Okay, let's dive into the code... |
| 4/2 | 2026/07/13 16:51 | tool | read-file |
0mArgs:{
"File": "io_uring/kbuf.c",
"FirstLine": 300,
"LineCount": 50
}Results: {
"Contents": " 300:\t\treq-\u003ebuf_index = READ_ONCE(buf-\u003ebid);\n 301:\t\tdo {\n 302:\t\t\tu32 len = READ_ONCE(buf-\u003elen);\n 303:\t\n 304:\t\t\t/* truncate end piece, if needed, for non partial buffers */\n 305:\t\t\tif (len \u003e arg-\u003emax_len) {\n 306:\t\t\t\tlen = arg-\u003emax_len;\n 307:\t\t\t\tif (!(bl-\u003eflags \u0026 IOBL_INC)) {\n 308:\t\t\t\t\targ-\u003epartial_map = 1;\n 309:\t\t\t\t\tif (iov != arg-\u003eiovs)\n 310:\t\t\t\t\t\tbreak;\n 311:\t\t\t\t}\n 312:\t\t\t}\n 313:\t\n 314:\t\t\tiov-\u003eiov_base = u64_to_user_ptr(READ_ONCE(buf-\u003eaddr));\n 315:\t\t\tiov-\u003eiov_len = len;\n 316:\t\t\tif (unlikely(!access_ok(iov-\u003eiov_base, len))) {\n 317:\t\t\t\tif (arg-\u003eiovs != org_iovs)\n 318:\t\t\t\t\tkfree(arg-\u003eiovs);\n 319:\t\t\t\treturn -EFAULT;\n 320:\t\t\t}\n 321:\t\t\tiov++;\n 322:\t\n 323:\t\t\targ-\u003eout_len += len;\n 324:\t\t\targ-\u003emax_len -= len;\n 325:\t\t\tif (!arg-\u003emax_len)\n 326:\t\t\t\tbreak;\n 327:\t\n 328:\t\t\tbuf = io_ring_head_to_buf(br, ++head, bl-\u003emask);\n 329:\t\t} while (--nr_iovs);\n 330:\t\n 331:\t\tif ((arg-\u003emode \u0026 KBUF_MODE_FREE) \u0026\u0026 arg-\u003eiovs != org_iovs)\n 332:\t\t\tkfree(org_iovs);\n 333:\t\n 334:\t\tif (head == tail)\n 335:\t\t\treq-\u003eflags |= REQ_F_BL_EMPTY;\n 336:\t\n 337:\t\treq-\u003eflags |= REQ_F_BUFFER_RING;\n 338:\t\treturn iov - arg-\u003eiovs;\n 339:\t}\n 340:\t\n 341:\tint io_buffers_select(struct io_kiocb *req, struct buf_sel_arg *arg,\n 342:\t\t\t struct io_br_sel *sel, unsigned int issue_flags)\n 343:\t{\n 344:\t\tstruct io_ring_ctx *ctx = req-\u003ectx;\n 345:\t\tint ret = -ENOENT;\n 346:\t\n 347:\t\tio_ring_submit_lock(ctx, issue_flags);\n 348:\t\tsel-\u003ebuf_list = io_buffer_get_list(ctx, arg-\u003ebuf_group);\n 349:\t\tif (unlikely(!sel-\u003ebuf_list))\n"
} |
| 5/2 | 2026/07/13 16:51 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 3079 output: 36 thoughts: 48 Thoughts: Okay, here's my take on those thoughts, tailored for an expert audience: **Analyzing the `io_ring_buffers_peek` Patch** Alright, so this patch is digging into `io_ring_buffers_peek` within `io_uring/kbuf.c`. My immediate thought is, "Okay, what's being tweaked in this critical path?" Then, the mention of `org_iovs` triggered a mental flag. I need to understand how *that* is being used in this function. It's time to trace the definition of `org_iovs`, which is likely a key aspect to the work. Let me quickly refresh my understanding of where it's defined and how it's integrated with other parts of the subsystem. I need to ascertain if this is a change to the iov management or use-case with those iovs. |
| 6/2 | 2026/07/13 16:51 | tool | read-file |
0mArgs:{
"File": "io_uring/kbuf.c",
"FirstLine": 250,
"LineCount": 50
}Results: {
"Contents": " 250:\t/* cap it at a reasonable 256, will be one page even for 4K */\n 251:\t#define PEEK_MAX_IMPORT\t\t256\n 252:\t\n 253:\tstatic int io_ring_buffers_peek(struct io_kiocb *req, struct buf_sel_arg *arg,\n 254:\t\t\t\t\tstruct io_buffer_list *bl)\n 255:\t{\n 256:\t\tstruct io_uring_buf_ring *br = bl-\u003ebuf_ring;\n 257:\t\tstruct iovec *org_iovs = arg-\u003eiovs;\n 258:\t\tstruct iovec *iov = arg-\u003eiovs;\n 259:\t\tint nr_iovs = arg-\u003enr_iovs;\n 260:\t\t__u16 nr_avail, tail, head;\n 261:\t\tstruct io_uring_buf *buf;\n 262:\t\n 263:\t\ttail = smp_load_acquire(\u0026br-\u003etail);\n 264:\t\thead = bl-\u003ehead;\n 265:\t\tnr_avail = min_t(__u16, tail - head, UIO_MAXIOV);\n 266:\t\tif (unlikely(!nr_avail))\n 267:\t\t\treturn -ENOBUFS;\n 268:\t\n 269:\t\tbuf = io_ring_head_to_buf(br, head, bl-\u003emask);\n 270:\t\tif (arg-\u003emax_len) {\n 271:\t\t\tu32 len = READ_ONCE(buf-\u003elen);\n 272:\t\t\tsize_t needed;\n 273:\t\n 274:\t\t\tif (unlikely(!len))\n 275:\t\t\t\treturn -ENOBUFS;\n 276:\t\t\tneeded = (arg-\u003emax_len + len - 1) / len;\n 277:\t\t\tneeded = min_not_zero(needed, (size_t) PEEK_MAX_IMPORT);\n 278:\t\t\tif (nr_avail \u003e needed)\n 279:\t\t\t\tnr_avail = needed;\n 280:\t\t}\n 281:\t\n 282:\t\t/*\n 283:\t\t * only alloc a bigger array if we know we have data to map, eg not\n 284:\t\t * a speculative peek operation.\n 285:\t\t */\n 286:\t\tif (arg-\u003emode \u0026 KBUF_MODE_EXPAND \u0026\u0026 nr_avail \u003e nr_iovs \u0026\u0026 arg-\u003emax_len) {\n 287:\t\t\tiov = kmalloc_objs(struct iovec, nr_avail);\n 288:\t\t\tif (unlikely(!iov))\n 289:\t\t\t\treturn -ENOMEM;\n 290:\t\t\targ-\u003eiovs = iov;\n 291:\t\t\tnr_iovs = nr_avail;\n 292:\t\t} else if (nr_avail \u003c nr_iovs) {\n 293:\t\t\tnr_iovs = nr_avail;\n 294:\t\t}\n 295:\t\n 296:\t\t/* set it to max, if not set, so we can use it unconditionally */\n 297:\t\tif (!arg-\u003emax_len)\n 298:\t\t\targ-\u003emax_len = INT_MAX;\n 299:\t\n"
} |
| 7/2 | 2026/07/13 16:51 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 4189 output: 21 thoughts: 444 Thoughts: **Analyzing a Memory Management Patch**
Okay, so I'm looking at this patch and it seems like it's addressing a memory leak or a potential double-free or invalid free situation. Let's see... the original code was pretty straightforward:
```c
if (arg->mode & KBUF_MODE_FREE)
kfree(arg->iovs);
```
Right, if `arg->mode & KBUF_MODE_FREE` is set, it's telling us the caller wants us to free `arg->iovs`. But wait, this is where it gets a little tricky. I need to trace the allocation and usage of `arg->iovs`.
Okay, in this function `arg->iovs` is either passed in or allocated here. `iov = kmalloc_objs(struct iovec, nr_avail); arg->iovs = iov;` So, if `arg->iovs` *was* allocated within this function and later freed, then the caller would be expecting us to take care of it with the `KBUF_MODE_FREE` bit.
The key is this line: `if ((arg->mode & KBUF_MODE_FREE) && arg->iovs != org_iovs)`. So, the patch is changing the `kfree` call to `kfree(org_iovs)`. Okay, so `org_iovs` must be the original pointer passed by the caller. If `arg->iovs != org_iovs` in the new code, then `arg->iovs` was newly allocated within this function. The patch is then only freeing `org_iovs` if it was passed in and `arg->iovs` was newly allocated.
So, if `arg->iovs` is allocated in the function, and `arg->mode & KBUF_MODE_FREE` is set, the correct thing to do is free the *original* `arg->iovs` because the caller is still expecting to free the *new* `arg->iovs`. If we don't free `org_iovs`, we leak memory. If we *do* free the allocated `arg->iovs`, we're double-freeing. The patch is addressing the first case. I need to confirm the allocation logic makes sense. Looks like this patch is fixing a classic case where an intermediate allocation needs to be cleaned up or you'll have a leak. Now I need to check the caller of `io_ring_buffers_peek` to fully understand what happens when it calls this function.
|
| 8/2 | 2026/07/13 16:51 | tool | grepper |
0mArgs:{
"Expression": "io_ring_buffers_peek"
}Results: {
"Output": "io_uring/kbuf.c=230=struct io_br_sel io_buffer_select(struct io_kiocb *req, size_t *len,\n--\nio_uring/kbuf.c-252-\nio_uring/kbuf.c:253:static int io_ring_buffers_peek(struct io_kiocb *req, struct buf_sel_arg *arg,\nio_uring/kbuf.c-254-\t\t\t\tstruct io_buffer_list *bl)\n--\nio_uring/kbuf.c=341=int io_buffers_select(struct io_kiocb *req, struct buf_sel_arg *arg,\n--\nio_uring/kbuf.c-352-\tif (sel-\u003ebuf_list-\u003eflags \u0026 IOBL_BUF_RING) {\nio_uring/kbuf.c:353:\t\tret = io_ring_buffers_peek(req, arg, sel-\u003ebuf_list);\nio_uring/kbuf.c-354-\t\t/*\n--\nio_uring/kbuf.c=377=int io_buffers_peek(struct io_kiocb *req, struct buf_sel_arg *arg,\n--\nio_uring/kbuf.c-390-\tif (bl-\u003eflags \u0026 IOBL_BUF_RING) {\nio_uring/kbuf.c:391:\t\tret = io_ring_buffers_peek(req, arg, bl);\nio_uring/kbuf.c-392-\t\tif (ret \u003e 0)\n"
} |
| 9/2 | 2026/07/13 16:51 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 5587 output: 36 thoughts: 19 Thoughts: Here's my take on those thoughts: **Analyzing `io_buffers_select` and `io_buffers_peek`** Alright, let's dive into these functions, specifically `io_buffers_select` and `io_buffers_peek`. I need to understand their behavior and how they interact, likely in the context of some kind of asynchronous I/O setup. I'm imagining `select` is being used to non-blockingly monitor the readiness of I/O buffers, probably for reading or writing, but I want to be certain about the mechanism it is using, whether it's tied to an event loop or something else. I'll need to look at how `peek` is implemented relative to `select`--perhaps `peek` helps examine buffer contents without consuming the data, but only after it’s been confirmed ready to read by `select`. I should also consider how `select` handles partial reads/writes, and if `peek` is affected by such scenarios. Thinking about potential race conditions or edge cases is key. Time to get into the code! |
| 10/2 | 2026/07/13 16:51 | tool | read-file |
0mArgs:{
"File": "io_uring/kbuf.c",
"FirstLine": 341,
"LineCount": 50
}Results: {
"Contents": " 341:\tint io_buffers_select(struct io_kiocb *req, struct buf_sel_arg *arg,\n 342:\t\t\t struct io_br_sel *sel, unsigned int issue_flags)\n 343:\t{\n 344:\t\tstruct io_ring_ctx *ctx = req-\u003ectx;\n 345:\t\tint ret = -ENOENT;\n 346:\t\n 347:\t\tio_ring_submit_lock(ctx, issue_flags);\n 348:\t\tsel-\u003ebuf_list = io_buffer_get_list(ctx, arg-\u003ebuf_group);\n 349:\t\tif (unlikely(!sel-\u003ebuf_list))\n 350:\t\t\tgoto out_unlock;\n 351:\t\n 352:\t\tif (sel-\u003ebuf_list-\u003eflags \u0026 IOBL_BUF_RING) {\n 353:\t\t\tret = io_ring_buffers_peek(req, arg, sel-\u003ebuf_list);\n 354:\t\t\t/*\n 355:\t\t\t * Don't recycle these buffers if we need to go through poll.\n 356:\t\t\t * Nobody else can use them anyway, and holding on to provided\n 357:\t\t\t * buffers for a send/write operation would happen on the app\n 358:\t\t\t * side anyway with normal buffers. Besides, we already\n 359:\t\t\t * committed them, they cannot be put back in the queue.\n 360:\t\t\t */\n 361:\t\t\tif (ret \u003e 0) {\n 362:\t\t\t\treq-\u003eflags |= REQ_F_BUFFERS_COMMIT | REQ_F_BL_NO_RECYCLE;\n 363:\t\t\t\tif (!io_kbuf_commit(req, sel-\u003ebuf_list, arg-\u003eout_len, ret))\n 364:\t\t\t\t\treq-\u003eflags |= REQ_F_BUF_MORE;\n 365:\t\t\t}\n 366:\t\t} else {\n 367:\t\t\tret = io_provided_buffers_select(req, \u0026arg-\u003eout_len, sel-\u003ebuf_list, arg-\u003eiovs);\n 368:\t\t}\n 369:\tout_unlock:\n 370:\t\tif (issue_flags \u0026 IO_URING_F_UNLOCKED) {\n 371:\t\t\tsel-\u003ebuf_list = NULL;\n 372:\t\t\tmutex_unlock(\u0026ctx-\u003euring_lock);\n 373:\t\t}\n 374:\t\treturn ret;\n 375:\t}\n 376:\t\n 377:\tint io_buffers_peek(struct io_kiocb *req, struct buf_sel_arg *arg,\n 378:\t\t\t struct io_br_sel *sel)\n 379:\t{\n 380:\t\tstruct io_ring_ctx *ctx = req-\u003ectx;\n 381:\t\tstruct io_buffer_list *bl;\n 382:\t\tint ret;\n 383:\t\n 384:\t\tlockdep_assert_held(\u0026ctx-\u003euring_lock);\n 385:\t\n 386:\t\tbl = io_buffer_get_list(ctx, arg-\u003ebuf_group);\n 387:\t\tif (unlikely(!bl))\n 388:\t\t\treturn -ENOENT;\n 389:\t\n 390:\t\tif (bl-\u003eflags \u0026 IOBL_BUF_RING) {\n"
} |
| 11/2 | 2026/07/13 16:51 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 6720 output: 20 thoughts: 16 Thoughts: Okay, here's my summary, presented as a stream of thought: **Tracing the Origins of KBUF_MODE_FREE** Alright, time to dive in. I need to understand the implications of `KBUF_MODE_FREE`. Seems like the best first step is to locate *where* this flag is actually being set. Knowing the initial context is critical; it'll shed light on the purpose and expected behavior of the subsequent code. This is fundamental for debugging, optimization, or really anything else I need to do with this code. So, let's start with a solid `grep` or similar search. I need to find all the places where `KBUF_MODE_FREE` is assigned a value. From there, I can begin to trace the execution path and understand how it influences the larger system. Let's see what we find! |
| 12/2 | 2026/07/13 16:51 | tool | grepper |
0mArgs:{
"Expression": "KBUF_MODE_FREE"
}Results: {
"Output": "io_uring/kbuf.c=253=static int io_ring_buffers_peek(struct io_kiocb *req, struct buf_sel_arg *arg,\n--\nio_uring/kbuf.c-330-\nio_uring/kbuf.c:331:\tif ((arg-\u003emode \u0026 KBUF_MODE_FREE) \u0026\u0026 arg-\u003eiovs != org_iovs)\nio_uring/kbuf.c-332-\t\tkfree(org_iovs);\n--\nio_uring/kbuf.h=53=enum {\n--\nio_uring/kbuf.h-56-\t/* if bigger vec allocated, free old one */\nio_uring/kbuf.h:57:\tKBUF_MODE_FREE\t\t= 2,\nio_uring/kbuf.h-58-};\n--\nio_uring/net.c=608=static int io_send_select_buffer(struct io_kiocb *req, unsigned int issue_flags,\n--\nio_uring/net.c-622-\t\targ.iovs = kmsg-\u003evec.iovec;\nio_uring/net.c:623:\t\targ.mode = KBUF_MODE_FREE;\nio_uring/net.c-624-\t}\n--\nio_uring/net.c=1137=static int io_recv_buf_select(struct io_kiocb *req, struct io_async_msghdr *kmsg,\n--\nio_uring/net.c-1159-\t\t\targ.iovs = kmsg-\u003evec.iovec;\nio_uring/net.c:1160:\t\t\targ.mode |= KBUF_MODE_FREE;\nio_uring/net.c-1161-\t\t}\n"
} |
| 13/2 | 2026/07/13 16:51 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 7377 output: 18 thoughts: 690 Thoughts: **Analyzing a io_uring Bug Fix: KBUF_MODE_FREE and Vector Management** Okay, so `KBUF_MODE_FREE`... that's the flag that indicates "if the vector is expanded, free the original one". Right, got it. Let me think. Looking at the old code, it used to be a simple `kfree(arg->iovs)` if the `KBUF_MODE_FREE` bit was set. But hold on, `arg->iovs` could have been updated to the newly allocated vector due to an expansion, and that's the problem. Specifically, if `KBUF_MODE_EXPAND` was set, and we had to allocate a new vector, the code does: `arg->iovs = iov;` So, if `KBUF_MODE_FREE` was then also set, the later `kfree(arg->iovs)` would free the *new* vector, not the old one. Meaning we're leaking the old one and the caller would then be using a freed vector. Yikes! That's a use-after-free *and* a memory leak! But there's more. What if `KBUF_MODE_FREE` was set, but the vector wasn't actually expanded? Then the code was freeing the caller's *original* `arg->iovs` vector, which they're still using! That is also a disaster. Now I get it: `KBUF_MODE_FREE` means "the caller handed me a dynamically allocated vector, and if I expand it, free the old one". The fix is now this: `if ((arg->mode & KBUF_MODE_FREE) && arg->iovs != org_iovs) kfree(org_iovs);` which correctly frees the *old* vector (`org_iovs`) *only* if a new vector was allocated (`arg->iovs != org_iovs`). Much better! This cleanly fixes the use-after-free and memory leak in the io_uring network receive/send with provided buffers. So, is this fix worth fuzzing? Absolutely. It’s a functional change in core io_uring logic. I should focus on the relevant symbols: `io_ring_buffers_peek`, `io_buffers_select`, `io_buffers_peek`, `io_send_select_buffer`, and `io_recv_buf_select`. Hang on, `io_ring_buffers_peek` is static, I can work around that. I'll include `io_send_select_buffer` and `io_recv_buf_select`. And make sure `CONFIG_IO_URING` is enabled. It probably is, but let me just double-check `io_uring/Kconfig`. |
| 14/2 | 2026/07/13 16:52 | tool | grepper |
0mArgs:{
"Expression": "config IO_URING"
}Results: {
"Output": "init/Kconfig=1954=config AIO\n--\ninit/Kconfig-1961-\ninit/Kconfig:1962:config IO_URING\ninit/Kconfig-1963-\tbool \"Enable IO uring support\" if EXPERT\n--\ninit/Kconfig=1971=config GCOV_PROFILE_URING\n--\ninit/Kconfig-1983-\ninit/Kconfig:1984:config IO_URING_MOCK_FILE\ninit/Kconfig-1985-\ttristate \"Enable io_uring mock files (Experimental)\" if EXPERT\n--\nio_uring/Kconfig-5-\nio_uring/Kconfig:6:config IO_URING_ZCRX\nio_uring/Kconfig-7-\tdef_bool y\n--\nio_uring/Kconfig-12-\nio_uring/Kconfig:13:config IO_URING_BPF\nio_uring/Kconfig-14-\tdef_bool y\n--\nio_uring/Kconfig-17-\nio_uring/Kconfig:18:config IO_URING_BPF_OPS\nio_uring/Kconfig-19-\tdef_bool y\n"
} |
| 15/2 | 2026/07/13 16:52 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 8980 output: 27 thoughts: 107 Thoughts: **Analyzing the io_uring Patch** Okay, so the primary focus here seems to be the `CONFIG_IO_URING` setting – that's the big one to start with. But hold on, the patch modifies `io_uring/kbuf.c`. I need to figure out the implications of that first. Let's quickly scan for any other potentially relevant configurations. The bug itself is in `io_ring_buffers_peek`, which is obviously tied to buffer rings. And buffer rings, of course, are a fundamental aspect of io_uring functionality. Given the potential impact, are there any network-specific configurations that might play a role here within io_uring? Hmm, I see that `CONFIG_NET` is required. That makes me want to examine `io_uring/net.c` closely as well. This will help to understand any network-related implications of this bug, particularly if network buffer rings are involved. |
| 16/2 | 2026/07/13 16:52 | tool | grepper |
0mArgs:{
"Expression": "CONFIG_NET",
"PathPrefix": "io_uring/"
}Results: {
"Output": "io_uring/Makefile=22=obj-$(CONFIG_EPOLL)\t\t+= epoll.o\nio_uring/Makefile:23:obj-$(CONFIG_NET_RX_BUSY_POLL)\t+= napi.o\nio_uring/Makefile:24:obj-$(CONFIG_NET) += net.o cmd_net.o\nio_uring/Makefile-25-obj-$(CONFIG_PROC_FS) += fdinfo.o\n--\nio_uring/fdinfo.c-19-\nio_uring/fdinfo.c:20:#ifdef CONFIG_NET_RX_BUSY_POLL\nio_uring/fdinfo.c-21-static __cold void common_tracking_show_fdinfo(struct io_ring_ctx *ctx,\n--\nio_uring/io_uring.h=128=struct io_wait_queue {\n--\nio_uring/io_uring.h-138-\nio_uring/io_uring.h:139:#ifdef CONFIG_NET_RX_BUSY_POLL\nio_uring/io_uring.h-140-\tktime_t napi_busy_poll_dt;\n--\nio_uring/napi.c-5-\nio_uring/napi.c:6:#ifdef CONFIG_NET_RX_BUSY_POLL\nio_uring/napi.c-7-\n--\nio_uring/napi.h-9-\nio_uring/napi.h:10:#ifdef CONFIG_NET_RX_BUSY_POLL\nio_uring/napi.h-11-\n--\nio_uring/napi.h=84=static inline int io_napi_sqpoll_busy_poll(struct io_ring_ctx *ctx)\n--\nio_uring/napi.h-87-}\nio_uring/napi.h:88:#endif /* CONFIG_NET_RX_BUSY_POLL */\nio_uring/napi.h-89-\n--\nio_uring/net.h=8=struct io_async_msghdr {\nio_uring/net.h:9:#if defined(CONFIG_NET)\nio_uring/net.h-10-\tstruct iou_vec\t\t\t\tvec;\n--\nio_uring/net.h-25-\nio_uring/net.h:26:#if defined(CONFIG_NET)\nio_uring/net.h-27-\n--\nio_uring/opdef.c=54=const struct io_issue_def io_issue_defs[] = {\n--\nio_uring/opdef.c-142-\t\t.ioprio\t\t\t= 1,\nio_uring/opdef.c:143:#if defined(CONFIG_NET)\nio_uring/opdef.c-144-\t\t.async_size\t\t= sizeof(struct io_async_msghdr),\n--\nio_uring/opdef.c-156-\t\t.ioprio\t\t\t= 1,\nio_uring/opdef.c:157:#if defined(CONFIG_NET)\nio_uring/opdef.c-158-\t\t.async_size\t\t= sizeof(struct io_async_msghdr),\n--\nio_uring/opdef.c-182-\t\t.ioprio\t\t\t= 1,\t/* used for flags */\nio_uring/opdef.c:183:#if defined(CONFIG_NET)\nio_uring/opdef.c-184-\t\t.prep\t\t\t= io_accept_prep,\n--\nio_uring/opdef.c-204-\t\t.pollout\t\t= 1,\nio_uring/opdef.c:205:#if defined(CONFIG_NET)\nio_uring/opdef.c-206-\t\t.filter_pdu_size\t= sizeof_field(struct io_uring_bpf_ctx, connect),\n--\nio_uring/opdef.c-285-\t\t.buffer_select\t\t= 1,\nio_uring/opdef.c:286:#if defined(CONFIG_NET)\nio_uring/opdef.c-287-\t\t.async_size\t\t= sizeof(struct io_async_msghdr),\n--\nio_uring/opdef.c-300-\t\t.ioprio\t\t\t= 1,\nio_uring/opdef.c:301:#if defined(CONFIG_NET)\nio_uring/opdef.c-302-\t\t.async_size\t\t= sizeof(struct io_async_msghdr),\n--\nio_uring/opdef.c-354-\t\t.needs_file\t\t= 1,\nio_uring/opdef.c:355:#if defined(CONFIG_NET)\nio_uring/opdef.c-356-\t\t.prep\t\t\t= io_shutdown_prep,\n--\nio_uring/opdef.c-407-\t\t.audit_skip\t\t= 1,\nio_uring/opdef.c:408:#if defined(CONFIG_NET)\nio_uring/opdef.c-409-\t\t.filter_pdu_size\t= sizeof_field(struct io_uring_bpf_ctx, socket),\n--\nio_uring/opdef.c-431-\t\t.ioprio\t\t\t= 1,\nio_uring/opdef.c:432:#if defined(CONFIG_NET)\nio_uring/opdef.c-433-\t\t.async_size\t\t= sizeof(struct io_async_msghdr),\n--\nio_uring/opdef.c-444-\t\t.ioprio\t\t\t= 1,\nio_uring/opdef.c:445:#if defined(CONFIG_NET)\nio_uring/opdef.c-446-\t\t.async_size\t\t= sizeof(struct io_async_msghdr),\n--\nio_uring/opdef.c-503-\t[IORING_OP_BIND] = {\nio_uring/opdef.c:504:#if defined(CONFIG_NET)\nio_uring/opdef.c-505-\t\t.needs_file\t\t= 1,\n--\nio_uring/opdef.c-513-\t[IORING_OP_LISTEN] = {\nio_uring/opdef.c:514:#if defined(CONFIG_NET)\nio_uring/opdef.c-515-\t\t.needs_file\t\t= 1,\n--\nio_uring/opdef.c-527-\t\t.ioprio\t\t\t= 1,\nio_uring/opdef.c:528:#if defined(CONFIG_NET)\nio_uring/opdef.c-529-\t\t.prep\t\t\t= io_recvzc_prep,\n--\nio_uring/opdef.c=596=const struct io_cold_def io_cold_defs[] = {\n--\nio_uring/opdef.c-633-\t\t.name\t\t\t= \"SENDMSG\",\nio_uring/opdef.c:634:#if defined(CONFIG_NET)\nio_uring/opdef.c-635-\t\t.cleanup\t\t= io_sendmsg_recvmsg_cleanup,\n--\nio_uring/opdef.c-640-\t\t.name\t\t\t= \"RECVMSG\",\nio_uring/opdef.c:641:#if defined(CONFIG_NET)\nio_uring/opdef.c-642-\t\t.cleanup\t\t= io_sendmsg_recvmsg_cleanup,\n--\nio_uring/opdef.c-698-\t\t.name\t\t\t= \"SEND\",\nio_uring/opdef.c:699:#if defined(CONFIG_NET)\nio_uring/opdef.c-700-\t\t.cleanup\t\t= io_sendmsg_recvmsg_cleanup,\n--\nio_uring/opdef.c-705-\t\t.name\t\t\t= \"RECV\",\nio_uring/opdef.c:706:#if defined(CONFIG_NET)\nio_uring/opdef.c-707-\t\t.cleanup\t\t= io_sendmsg_recvmsg_cleanup,\n--\nio_uring/opdef.c-784-\t\t.name\t\t\t= \"SEND_ZC\",\nio_uring/opdef.c:785:#if defined(CONFIG_NET)\nio_uring/opdef.c-786-\t\t.cleanup\t\t= io_send_zc_cleanup,\n--\nio_uring/opdef.c-791-\t\t.name\t\t\t= \"SENDMSG_ZC\",\nio_uring/opdef.c:792:#if defined(CONFIG_NET)\nio_uring/opdef.c-793-\t\t.cleanup\t\t= io_send_zc_cleanup,\n"
} |
| 17/2 | 2026/07/13 16:52 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 11418 output: 35 thoughts: 359 Thoughts: **My Analysis of the `io_uring` Bug Dependency** Okay, so I've been tracing through this `io_uring` issue. It looks like `CONFIG_NET` is essential for compiling `io_uring/net.c`, which is a key dependency here. The actual bug's code is in `io_uring/kbuf.c`, which is compiled unconditionally, but the crucial `KBUF_MODE_FREE` flag is *only* used within `io_uring/net.c`. That's the core of the problem. Let me just double-check, because that's always good practice... I did run a `grep` for `KBUF_MODE_FREE` earlier: ``` io_uring/kbuf.c:253:static int io_ring_buffers_peek(struct io_kiocb *req, struct buf_sel_arg *arg, io_uring/kbuf.c:331: if ((arg->mode & KBUF_MODE_FREE) && arg->iovs != org_iovs) io_uring/kbuf.h:57: KBUF_MODE_FREE = 2, io_uring/net.c:623: arg.mode = KBUF_MODE_FREE; io_uring/net.c:1160: arg.mode |= KBUF_MODE_FREE; ``` Yep, confirmed. The flag is strictly tied to `io_uring/net.c`. Therefore, `CONFIG_NET` is definitely a requirement to expose this bug. And, of course, `CONFIG_IO_URING` is necessary as well, because this is an `io_uring` specific issue. Okay, let's zoom in on `io_send_select_buffer` and `io_recv_buf_select` because that is where `KBUF_MODE_FREE` is set. I need to understand that logic flow. Let's start with `io_send_select_buffer`. |
| 18/2 | 2026/07/13 16:52 | tool | read-file |
0mArgs:{
"File": "io_uring/net.c",
"FirstLine": 600,
"LineCount": 50
}Results: {
"Contents": " 600:\t\tif (ret \u003e= 0)\n 601:\t\t\tret += sr-\u003edone_io;\n 602:\t\telse if (sr-\u003edone_io)\n 603:\t\t\tret = sr-\u003edone_io;\n 604:\t\tio_req_set_res(req, ret, 0);\n 605:\t\treturn IOU_COMPLETE;\n 606:\t}\n 607:\t\n 608:\tstatic int io_send_select_buffer(struct io_kiocb *req, unsigned int issue_flags,\n 609:\t\t\t\t\t struct io_br_sel *sel, struct io_async_msghdr *kmsg)\n 610:\t{\n 611:\t\tstruct io_sr_msg *sr = io_kiocb_to_cmd(req, struct io_sr_msg);\n 612:\t\tstruct buf_sel_arg arg = {\n 613:\t\t\t.iovs = \u0026kmsg-\u003efast_iov,\n 614:\t\t\t.max_len = min_not_zero(sr-\u003elen, INT_MAX),\n 615:\t\t\t.nr_iovs = 1,\n 616:\t\t\t.buf_group = sr-\u003ebuf_group,\n 617:\t\t};\n 618:\t\tint ret;\n 619:\t\n 620:\t\tif (kmsg-\u003evec.iovec) {\n 621:\t\t\targ.nr_iovs = kmsg-\u003evec.nr;\n 622:\t\t\targ.iovs = kmsg-\u003evec.iovec;\n 623:\t\t\targ.mode = KBUF_MODE_FREE;\n 624:\t\t}\n 625:\t\n 626:\t\tif (!(sr-\u003eflags \u0026 IORING_RECVSEND_BUNDLE))\n 627:\t\t\targ.nr_iovs = 1;\n 628:\t\telse\n 629:\t\t\targ.mode |= KBUF_MODE_EXPAND;\n 630:\t\n 631:\t\tret = io_buffers_select(req, \u0026arg, sel, issue_flags);\n 632:\t\tif (unlikely(ret \u003c 0))\n 633:\t\t\treturn ret;\n 634:\t\n 635:\t\tif (arg.iovs != \u0026kmsg-\u003efast_iov \u0026\u0026 arg.iovs != kmsg-\u003evec.iovec) {\n 636:\t\t\tkmsg-\u003evec.nr = ret;\n 637:\t\t\tkmsg-\u003evec.iovec = arg.iovs;\n 638:\t\t\treq-\u003eflags |= REQ_F_NEED_CLEANUP;\n 639:\t\t}\n 640:\t\tsr-\u003elen = arg.out_len;\n 641:\t\n 642:\t\tif (ret == 1) {\n 643:\t\t\tsr-\u003ebuf = arg.iovs[0].iov_base;\n 644:\t\t\tret = import_ubuf(ITER_SOURCE, sr-\u003ebuf, sr-\u003elen,\n 645:\t\t\t\t\t\t\u0026kmsg-\u003emsg.msg_iter);\n 646:\t\t\tif (unlikely(ret))\n 647:\t\t\t\treturn ret;\n 648:\t\t} else {\n 649:\t\t\tiov_iter_init(\u0026kmsg-\u003emsg.msg_iter, ITER_SOURCE,\n"
} |
| 19/2 | 2026/07/13 16:52 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 13094 output: 36 thoughts: 101 Thoughts: **Analyzing Kernel Buffer Management in I/O Operations** Okay, so I'm looking closely at how kernel buffers are managed during I/O operations, specifically focusing on `io_send_select_buffer`. I see that the function sets `KBUF_MODE_FREE` when `kmsg->vec.iovec` is present. This makes sense; if we're using an iovec, the buffer should be freed after the send. Now, the interesting bit: it sets `KBUF_MODE_EXPAND` when `IORING_RECVSEND_BUNDLE` is flagged. This is obviously linked to bundled operations with `IORING_OP_SEND` and `IORING_OP_SENDMSG`, giving the kernel permission to expand the buffer as needed to accommodate the bundled send. I need to make sure I understand this fully and ensure the logic is consistent throughout the I/O path. The context hints this is all to do with the *send* so let me now turn my attention to `io_recv_buf_select` to see if the complementary *receive* logic is sound and aligned. |
| 20/2 | 2026/07/13 16:52 | tool | read-file |
0mArgs:{
"File": "io_uring/net.c",
"FirstLine": 1137,
"LineCount": 50
}Results: {
"Contents": "1137:\tstatic int io_recv_buf_select(struct io_kiocb *req, struct io_async_msghdr *kmsg,\n1138:\t\t\t\t struct io_br_sel *sel, unsigned int issue_flags)\n1139:\t{\n1140:\t\tstruct io_sr_msg *sr = io_kiocb_to_cmd(req, struct io_sr_msg);\n1141:\t\tint ret;\n1142:\t\n1143:\t\t/*\n1144:\t\t * If the ring isn't locked, then don't use the peek interface\n1145:\t\t * to grab multiple buffers as we will lock/unlock between\n1146:\t\t * this selection and posting the buffers.\n1147:\t\t */\n1148:\t\tif (!(issue_flags \u0026 IO_URING_F_UNLOCKED) \u0026\u0026\n1149:\t\t sr-\u003eflags \u0026 IORING_RECVSEND_BUNDLE) {\n1150:\t\t\tstruct buf_sel_arg arg = {\n1151:\t\t\t\t.iovs = \u0026kmsg-\u003efast_iov,\n1152:\t\t\t\t.nr_iovs = 1,\n1153:\t\t\t\t.mode = KBUF_MODE_EXPAND,\n1154:\t\t\t\t.buf_group = sr-\u003ebuf_group,\n1155:\t\t\t};\n1156:\t\n1157:\t\t\tif (kmsg-\u003evec.iovec) {\n1158:\t\t\t\targ.nr_iovs = kmsg-\u003evec.nr;\n1159:\t\t\t\targ.iovs = kmsg-\u003evec.iovec;\n1160:\t\t\t\targ.mode |= KBUF_MODE_FREE;\n1161:\t\t\t}\n1162:\t\n1163:\t\t\tif (sel-\u003eval)\n1164:\t\t\t\targ.max_len = sel-\u003eval;\n1165:\t\t\telse if (kmsg-\u003emsg.msg_inq \u003e 1)\n1166:\t\t\t\targ.max_len = min_not_zero(sel-\u003eval, (ssize_t) kmsg-\u003emsg.msg_inq);\n1167:\t\n1168:\t\t\t/* if mshot limited, ensure we don't go over */\n1169:\t\t\tif (sr-\u003eflags \u0026 IORING_RECV_MSHOT_LIM)\n1170:\t\t\t\targ.max_len = min_not_zero(arg.max_len, sr-\u003emshot_total_len);\n1171:\t\t\tret = io_buffers_peek(req, \u0026arg, sel);\n1172:\t\t\tif (unlikely(ret \u003c 0))\n1173:\t\t\t\treturn ret;\n1174:\t\n1175:\t\t\tif (arg.iovs != \u0026kmsg-\u003efast_iov \u0026\u0026 arg.iovs != kmsg-\u003evec.iovec) {\n1176:\t\t\t\tkmsg-\u003evec.nr = ret;\n1177:\t\t\t\tkmsg-\u003evec.iovec = arg.iovs;\n1178:\t\t\t\treq-\u003eflags |= REQ_F_NEED_CLEANUP;\n1179:\t\t\t}\n1180:\t\t\tif (arg.partial_map)\n1181:\t\t\t\tsr-\u003eflags |= IORING_RECV_PARTIAL_MAP;\n1182:\t\n1183:\t\t\t/* special case 1 vec, can be a fast path */\n1184:\t\t\tif (ret == 1) {\n1185:\t\t\t\tsr-\u003ebuf = arg.iovs[0].iov_base;\n1186:\t\t\t\tsr-\u003elen = arg.iovs[0].iov_len;\n"
} |
| 21/2 | 2026/07/13 16:52 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 14374 output: 30 thoughts: 319 Thoughts: **Analyzing the io_uring Buffer Handling Bug** Okay, so I'm tracing this `io_recv_buf_select` function and seeing that it's setting `KBUF_MODE_FREE` and `KBUF_MODE_EXPAND`. This seems specific to `IORING_OP_RECV` and `IORING_OP_RECVMSG` operations when they're bundled. Right, the bug report pointed me to `io_ring_buffers_peek`. That's called by `io_buffers_select` and `io_buffers_peek`, which narrows down the area of concern. So, I need to focus on those key symbols. It looks like it should be `io_ring_buffers_peek`, `io_buffers_select`, `io_buffers_peek`, `io_send_select_buffer` and `io_recv_buf_select`. Hang on, `io_ring_buffers_peek` is declared as static. Ah, and so are `io_send_select_buffer` and `io_recv_buf_select`. That means `io_buffers_select` and `io_buffers_peek` are global. Since those are the interfaces, I'm going to include all of them in the focus list. But wait, `io_ring_buffers_peek` is the specific function that was modified in the referenced commit, so, that's the one I need to be most concerned about. Alright, let's lock in the focus symbols as: `io_ring_buffers_peek`, `io_buffers_select`, `io_buffers_peek`, `io_send_select_buffer` and `io_recv_buf_select`. Let's make sure I didn't miss any dependencies. I'll double-check for related configs to make sure everything's in place. Oh, `CONFIG_NET` is clearly a requirement, but are there any others? I'll check `io_uring/kbuf.c` for any `#ifdef` statements that might be relevant. |
| 22/2 | 2026/07/13 16:52 | tool | grepper |
0mArgs:{
"Expression": "#ifdef",
"PathPrefix": "io_uring/kbuf.c"
}Results: {
"Output": "io_uring/kbuf.c=626=int io_register_pbuf_ring(struct io_ring_ctx *ctx, void __user *arg)\n--\nio_uring/kbuf.c-679-\nio_uring/kbuf.c:680:#ifdef SHM_COLOUR\nio_uring/kbuf.c-681-\t/*\n"
} |
| 23/2 | 2026/07/13 16:52 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 15267 output: 160 thoughts: 358 Thoughts: **My Analysis of the io_uring Network Buffer Vulnerability** Okay, so I've narrowed it down. There aren't any other relevant configurations beyond `CONFIG_IO_URING` and `CONFIG_NET` for this patch. Let's summarize and solidify my findings. Worth fuzzing? Absolutely, yes. The reason is crystal clear: this patch addresses a use-after-free and memory leak in io_uring's network receive/send operations when handling provided buffers via buffer rings. Essentially, the dynamic iovec array expansion was flawed. The original array was improperly freed, and the new one was freed prematurely. This led to a classic memory leak on the old array and a subsequent use-after-free vulnerability on the new array. The key focus symbols are: `io_ring_buffers_peek`, `io_buffers_select`, `io_buffers_peek`, `io_send_select_buffer`, and `io_recv_buf_select`. We need to enable the configurations: `IO_URING` and `NET`. Hang on, let's think about this... I remember `io_ring_buffers_peek` is static. Syzkaller can fuzz static functions if they're reachable through a call chain from a syscall. And, indeed, `io_ring_buffers_peek` is part of the `io_uring_enter` call path. That's good. Wait a second, the other two static functions, `io_send_select_buffer` and `io_recv_buf_select` are also static. I'll make sure to note those as well. Let me just do a quick sanity check, reviewing the patch code again: ```c - if (arg->mode & KBUF_MODE_FREE) - kfree(arg->iovs); + if ((arg->mode & KBUF_MODE_FREE) && arg->iovs != org_iovs) + kfree(org_iovs); ``` Yep, exactly as I expected. This matches my analysis perfectly. Alright, I'm confident in these findings. Time to call the results. |
| 24/2 | 2026/07/13 16:52 | tool | set-results |
0mArgs:{
"EnableConfigs": [
"IO_URING",
"NET"
],
"FocusSymbols": [
"io_ring_buffers_peek",
"io_buffers_select",
"io_buffers_peek",
"io_send_select_buffer",
"io_recv_buf_select"
],
"Reasoning": "The patch fixes a use-after-free and memory leak in io_uring's network receive/send operations with provided buffer rings. When a dynamically allocated iovec array is expanded, the old array was not freed properly, and the new array was freed instead, leading to a memory leak of the old array and a use-after-free of the new array.",
"WorthFuzzing": true
}Results: {
"EnableConfigs": [
"IO_URING",
"NET"
],
"FocusSymbols": [
"io_ring_buffers_peek",
"io_buffers_select",
"io_buffers_peek",
"io_send_select_buffer",
"io_recv_buf_select"
],
"Reasoning": "The patch fixes a use-after-free and memory leak in io_uring's network receive/send operations with provided buffer rings. When a dynamically allocated iovec array is expanded, the old array was not freed properly, and the new array was freed instead, leading to a memory leak of the old array and a use-after-free of the new array.",
"WorthFuzzing": true
} |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|