The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* [PATCH v1] io_uring: fix dangling iovec after provided-buffer bundle grow failure
@ 2026-07-05 23:45 Hao-Yu Yang
  2026-07-06 16:19 ` Jens Axboe
  2026-07-06 16:20 ` Jens Axboe
  0 siblings, 2 replies; 10+ messages in thread
From: Hao-Yu Yang @ 2026-07-05 23:45 UTC (permalink / raw)
  To: linux-kernel; +Cc: axboe, io-uring, Hao-Yu Yang

When growing a provided-buffer bundle, the old cached iovec is freed
before the new buffers have all been validated. If validation fails, the
request still points at the freed iovec, which can be freed again during
completion cleanup.

BUG: KASAN: double-free in io_vec_free+0x2c/0x90
Freed by task 73:
 kfree+0x104/0x3b0
 io_vec_free+0x2c/0x90
 __io_submit_flush_completions+0xc03/0x1e40
 io_submit_sqes+0xdb5/0x2310

Allocated by task 73:
 io_ring_buffers_peek+0x559/0xc60
 io_buffers_select+0x1c1/0x460
 io_send+0x770/0x1050

Fix this by deferring the free of the old cached iovec until validation
has succeeded. On failure, free the newly allocated iovec and leave the
request pointing at the original one.

Fixes: 46800585ae04 ("io_uring/kbuf: validate ring provided buffer addresses with access_ok()")
Signed-off-by: Hao-Yu Yang <naup96721@gmail.com>
---
 io_uring/kbuf.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/io_uring/kbuf.c b/io_uring/kbuf.c
index 3cd29477fff2..4055173e0c48 100644
--- a/io_uring/kbuf.c
+++ b/io_uring/kbuf.c
@@ -256,6 +256,7 @@ static int io_ring_buffers_peek(struct io_kiocb *req, struct buf_sel_arg *arg,
 	struct io_uring_buf_ring *br = bl->buf_ring;
 	struct iovec *org_iovs = arg->iovs;
 	struct iovec *iov = arg->iovs;
+	struct iovec *old = NULL;
 	int nr_iovs = arg->nr_iovs;
 	__u16 nr_avail, tail, head;
 	struct io_uring_buf *buf;
@@ -288,7 +289,7 @@ static int io_ring_buffers_peek(struct io_kiocb *req, struct buf_sel_arg *arg,
 		if (unlikely(!iov))
 			return -ENOMEM;
 		if (arg->mode & KBUF_MODE_FREE)
-			kfree(arg->iovs);
+			old = arg->iovs;
 		arg->iovs = iov;
 		nr_iovs = nr_avail;
 	} else if (nr_avail < nr_iovs) {
@@ -318,6 +319,8 @@ static int io_ring_buffers_peek(struct io_kiocb *req, struct buf_sel_arg *arg,
 		if (unlikely(!access_ok(iov->iov_base, len))) {
 			if (arg->iovs != org_iovs)
 				kfree(arg->iovs);
+			/* hand the still-live cached vec back to the owner */
+			arg->iovs = org_iovs;
 			return -EFAULT;
 		}
 		iov++;
@@ -330,6 +333,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);
 
+	kfree(old);
+
 	if (head == tail)
 		req->flags |= REQ_F_BL_EMPTY;
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH v1] io_uring: fix dangling iovec after provided-buffer bundle grow failure
  2026-07-05 23:45 [PATCH v1] io_uring: fix dangling iovec after provided-buffer bundle grow failure Hao-Yu Yang
@ 2026-07-06 16:19 ` Jens Axboe
  2026-07-06 16:56   ` Hao-Yu Yang
  2026-07-06 16:20 ` Jens Axboe
  1 sibling, 1 reply; 10+ messages in thread
From: Jens Axboe @ 2026-07-06 16:19 UTC (permalink / raw)
  To: Hao-Yu Yang, linux-kernel; +Cc: io-uring

On 7/5/26 5:45 PM, Hao-Yu Yang wrote:
> diff --git a/io_uring/kbuf.c b/io_uring/kbuf.c
> index 3cd29477fff2..4055173e0c48 100644
> --- a/io_uring/kbuf.c
> +++ b/io_uring/kbuf.c
> @@ -256,6 +256,7 @@ static int io_ring_buffers_peek(struct io_kiocb *req, struct buf_sel_arg *arg,
>  	struct io_uring_buf_ring *br = bl->buf_ring;
>  	struct iovec *org_iovs = arg->iovs;
>  	struct iovec *iov = arg->iovs;
> +	struct iovec *old = NULL;
>  	int nr_iovs = arg->nr_iovs;
>  	__u16 nr_avail, tail, head;
>  	struct io_uring_buf *buf;
> @@ -288,7 +289,7 @@ static int io_ring_buffers_peek(struct io_kiocb *req, struct buf_sel_arg *arg,
>  		if (unlikely(!iov))
>  			return -ENOMEM;
>  		if (arg->mode & KBUF_MODE_FREE)
> -			kfree(arg->iovs);
> +			old = arg->iovs;
>  		arg->iovs = iov;
>  		nr_iovs = nr_avail;
>  	} else if (nr_avail < nr_iovs) {
> @@ -318,6 +319,8 @@ static int io_ring_buffers_peek(struct io_kiocb *req, struct buf_sel_arg *arg,
>  		if (unlikely(!access_ok(iov->iov_base, len))) {
>  			if (arg->iovs != org_iovs)
>  				kfree(arg->iovs);
> +			/* hand the still-live cached vec back to the owner */
> +			arg->iovs = org_iovs;
>  			return -EFAULT;
>  		}
>  		iov++;
> @@ -330,6 +333,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);
>  
> +	kfree(old);
> +
>  	if (head == tail)
>  		req->flags |= REQ_F_BL_EMPTY;

Can't we just do the below, that seems a lot simpler?

diff --git a/io_uring/kbuf.c b/io_uring/kbuf.c
index 3cd29477fff2..3bb24d20c890 100644
--- a/io_uring/kbuf.c
+++ b/io_uring/kbuf.c
@@ -287,8 +287,6 @@ static int io_ring_buffers_peek(struct io_kiocb *req, struct buf_sel_arg *arg,
 		iov = kmalloc_objs(struct iovec, nr_avail);
 		if (unlikely(!iov))
 			return -ENOMEM;
-		if (arg->mode & KBUF_MODE_FREE)
-			kfree(arg->iovs);
 		arg->iovs = iov;
 		nr_iovs = nr_avail;
 	} else if (nr_avail < nr_iovs) {
@@ -330,6 +328,9 @@ 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(org_iovs);
+
 	if (head == tail)
 		req->flags |= REQ_F_BL_EMPTY;
 


-- 
Jens Axboe

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH v1] io_uring: fix dangling iovec after provided-buffer bundle grow failure
  2026-07-05 23:45 [PATCH v1] io_uring: fix dangling iovec after provided-buffer bundle grow failure Hao-Yu Yang
  2026-07-06 16:19 ` Jens Axboe
@ 2026-07-06 16:20 ` Jens Axboe
  2026-07-06 17:01   ` Hao-Yu Yang
  1 sibling, 1 reply; 10+ messages in thread
From: Jens Axboe @ 2026-07-06 16:20 UTC (permalink / raw)
  To: Hao-Yu Yang, linux-kernel; +Cc: io-uring

On 7/5/26 5:45 PM, Hao-Yu Yang wrote:
> BUG: KASAN: double-free in io_vec_free+0x2c/0x90
> Freed by task 73:
>  kfree+0x104/0x3b0
>  io_vec_free+0x2c/0x90
>  __io_submit_flush_completions+0xc03/0x1e40
>  io_submit_sqes+0xdb5/0x2310
> 
> Allocated by task 73:
>  io_ring_buffers_peek+0x559/0xc60
>  io_buffers_select+0x1c1/0x460
>  io_send+0x770/0x1050

Please also send your reproducer, the above looks a bit synthesized
rather than a real trace... Is it actually from KASAN, or is it from
whatever LLM you're using?

-- 
Jens Axboe

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v1] io_uring: fix dangling iovec after provided-buffer bundle grow failure
  2026-07-06 16:19 ` Jens Axboe
@ 2026-07-06 16:56   ` Hao-Yu Yang
  0 siblings, 0 replies; 10+ messages in thread
From: Hao-Yu Yang @ 2026-07-06 16:56 UTC (permalink / raw)
  To: Jens Axboe; +Cc: linux-kernel, io-uring

Oh, this patch looks more clear. The original iovec is freed only after
 access_ok is verified, and the updated iovec for kmsg is returned to
the upper layer. In the error path, the original iovec object is not
freed, and the upper layer's iovec is not updated along that path.

If there are no other issues, I will send the second version of the
patch when I wake up.

Thanks for your review.

On Mon, Jul 06, 2026 at 10:19:10AM -0600, Jens Axboe wrote:
> On 7/5/26 5:45 PM, Hao-Yu Yang wrote:
> > diff --git a/io_uring/kbuf.c b/io_uring/kbuf.c
> > index 3cd29477fff2..4055173e0c48 100644
> > --- a/io_uring/kbuf.c
> > +++ b/io_uring/kbuf.c
> > @@ -256,6 +256,7 @@ static int io_ring_buffers_peek(struct io_kiocb *req, struct buf_sel_arg *arg,
> >  	struct io_uring_buf_ring *br = bl->buf_ring;
> >  	struct iovec *org_iovs = arg->iovs;
> >  	struct iovec *iov = arg->iovs;
> > +	struct iovec *old = NULL;
> >  	int nr_iovs = arg->nr_iovs;
> >  	__u16 nr_avail, tail, head;
> >  	struct io_uring_buf *buf;
> > @@ -288,7 +289,7 @@ static int io_ring_buffers_peek(struct io_kiocb *req, struct buf_sel_arg *arg,
> >  		if (unlikely(!iov))
> >  			return -ENOMEM;
> >  		if (arg->mode & KBUF_MODE_FREE)
> > -			kfree(arg->iovs);
> > +			old = arg->iovs;
> >  		arg->iovs = iov;
> >  		nr_iovs = nr_avail;
> >  	} else if (nr_avail < nr_iovs) {
> > @@ -318,6 +319,8 @@ static int io_ring_buffers_peek(struct io_kiocb *req, struct buf_sel_arg *arg,
> >  		if (unlikely(!access_ok(iov->iov_base, len))) {
> >  			if (arg->iovs != org_iovs)
> >  				kfree(arg->iovs);
> > +			/* hand the still-live cached vec back to the owner */
> > +			arg->iovs = org_iovs;
> >  			return -EFAULT;
> >  		}
> >  		iov++;
> > @@ -330,6 +333,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);
> >  
> > +	kfree(old);
> > +
> >  	if (head == tail)
> >  		req->flags |= REQ_F_BL_EMPTY;
> 
> Can't we just do the below, that seems a lot simpler?
> 
> diff --git a/io_uring/kbuf.c b/io_uring/kbuf.c
> index 3cd29477fff2..3bb24d20c890 100644
> --- a/io_uring/kbuf.c
> +++ b/io_uring/kbuf.c
> @@ -287,8 +287,6 @@ static int io_ring_buffers_peek(struct io_kiocb *req, struct buf_sel_arg *arg,
>  		iov = kmalloc_objs(struct iovec, nr_avail);
>  		if (unlikely(!iov))
>  			return -ENOMEM;
> -		if (arg->mode & KBUF_MODE_FREE)
> -			kfree(arg->iovs);
>  		arg->iovs = iov;
>  		nr_iovs = nr_avail;
>  	} else if (nr_avail < nr_iovs) {
> @@ -330,6 +328,9 @@ 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(org_iovs);
> +
>  	if (head == tail)
>  		req->flags |= REQ_F_BL_EMPTY;
>  
> 
> 
> -- 
> Jens Axboe

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v1] io_uring: fix dangling iovec after provided-buffer bundle grow failure
  2026-07-06 16:20 ` Jens Axboe
@ 2026-07-06 17:01   ` Hao-Yu Yang
  2026-07-06 17:13     ` Jens Axboe
  0 siblings, 1 reply; 10+ messages in thread
From: Hao-Yu Yang @ 2026-07-06 17:01 UTC (permalink / raw)
  To: Jens Axboe; +Cc: linux-kernel, io-uring

Sorry, i forgot to cc others mail

I discovered and wrote the PoC myself. Trigger way is
 send1: Submit an IORING_OP_SEND request with four valid
 provided buffers. The system will allocate and cache an
 iovec array (of size 4) for this request and store the
 pointer in kmsg->vec.iovec.

 send2: Submit a second send request with 8, and I set
 the fourth passed-in address to point to an invalid address.
 Now kmsg still hold old iovec, but old iovec object have
 been freed.

 So this will lead dangling pointer.

I also paste my full KASAN log

[    4.571640] BUG: KASAN: double-free in io_vec_free+0x2c/0x90
[    4.573757] Free of addr ffff888001ec6d80 by task e/73
[    4.575442]
[    4.576047] CPU: 0 UID: 1000 PID: 73 Comm: e Not tainted 7.2.0-rc1-g7404ce516372 #1 PREEMPT(lazy)
[    4.576064] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014
[    4.576087] Call Trace:
[    4.576114]  <TASK>
[    4.576116]  dump_stack_lvl+0x55/0x70
[    4.576219]  print_report+0xcb/0x5e0
[    4.576270]  ? io_vec_free+0x2c/0x90
[    4.576273]  ? io_vec_free+0x2c/0x90
[    4.576276]  kasan_report_invalid_free+0x94/0xc0
[    4.576280]  ? io_vec_free+0x2c/0x90
[    4.576283]  ? io_vec_free+0x2c/0x90
[    4.576286]  check_slab_allocation+0xe4/0x110
[    4.576289]  kfree+0x104/0x3b0
[    4.576308]  io_vec_free+0x2c/0x90
[    4.576312]  __io_submit_flush_completions+0xc03/0x1e40
[    4.576337]  ? io_issue_sqe+0x7d/0x14a0
[    4.576341]  io_submit_sqes+0xdb5/0x2310
[    4.576344]  ? __pfx_mutex_lock+0x10/0x10
[    4.576355]  __do_sys_io_uring_enter+0x701/0x11a0
[    4.576359]  ? __pfx___do_sys_io_uring_enter+0x10/0x10
[    4.576362]  ? fdget_pos+0x53/0x4c0
[    4.576410]  ? ksys_write+0xee/0x1c0
[    4.576427]  ? __pfx_ksys_write+0x10/0x10
[    4.576430]  do_syscall_64+0x102/0x5a0
[    4.576448]  entry_SYSCALL_64_after_hwframe+0x77/0x7f
[    4.576478] RIP: 0033:0x44895d
[    4.576502] Code: 28 c3 e8 06 20 00 00 66 0f 1f 44 00 00 f3 0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 8
[    4.576508] RSP: 002b:00007ffdfca0f868 EFLAGS: 00000246 ORIG_RAX: 00000000000001aa
[    4.576555] RAX: ffffffffffffffda RBX: 00007f615f4a1000 RCX: 000000000044895d
[    4.576558] RDX: 0000000000000001 RSI: 0000000000000001 RDI: 0000000000000005
[    4.576559] RBP: 00007f615f49e000 R08: 0000000000000000 R09: 0000000000000000
[    4.576561] R10: 0000000000000001 R11: 0000000000000246 R12: 0000000000000001
[    4.576573] R13: 00007ffdfca0fba8 R14: 00000000004c37d0 R15: 0000000000000001
[    4.576577]  </TASK>
[    4.576578]
[    4.625904] Allocated by task 73:
[    4.626662]  kasan_save_stack+0x24/0x50
[    4.627517]  kasan_save_track+0x14/0x30
[    4.628377]  __kasan_kmalloc+0x7f/0x90
[    4.629375]  __kmalloc_noprof+0x1b6/0x480
[    4.630133]  io_ring_buffers_peek+0x559/0xc60
[    4.631042]  io_buffers_select+0x1c1/0x460
[    4.632035]  io_send+0x770/0x1050
[    4.633444]  __io_issue_sqe+0xaf/0x730
[    4.634590]  io_issue_sqe+0x7d/0x14a0
[    4.636114]  io_submit_sqes+0x973/0x2310
[    4.637050]  __do_sys_io_uring_enter+0x701/0x11a0
[    4.638558]  do_syscall_64+0x102/0x5a0
[    4.639390]  entry_SYSCALL_64_after_hwframe+0x77/0x7f
[    4.640670]
[    4.641129] Freed by task 73:
[    4.641788]  kasan_save_stack+0x24/0x50
[    4.642456]  kasan_save_track+0x14/0x30
[    4.642983]  kasan_save_free_info+0x3b/0x60
[    4.643577]  __kasan_slab_free+0x43/0x70
[    4.644099]  kfree+0x127/0x3b0
[    4.645020]  io_ring_buffers_peek+0x71c/0xc60
[    4.646782]  io_buffers_select+0x1c1/0x460
[    4.648101]  io_send+0x770/0x1050
[    4.648861]  __io_issue_sqe+0xaf/0x730
[    4.649727]  io_issue_sqe+0x7d/0x14a0
[    4.650504]  io_submit_sqes+0x973/0x2310
[    4.651469]  __do_sys_io_uring_enter+0x701/0x11a0
[    4.652645]  do_syscall_64+0x102/0x5a0
[    4.653749]  entry_SYSCALL_64_after_hwframe+0x77/0x7f
[    4.655244]
[    4.655532] The buggy address belongs to the object at ffff888001ec6d80
[    4.655532]  which belongs to the cache kmalloc-64 of size 64
[    4.658285] The buggy address is located 0 bytes inside of
[    4.658285]  64-byte region [ffff888001ec6d80, ffff888001ec6dc0)
[    4.660820]
[    4.661276] The buggy address belongs to the physical page:
[    4.663970] page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x1ec6
[    4.666110] flags: 0x100000000000000(node=0|zone=1)
[    4.667589] page_type: f5(slab)
[    4.668475] raw: 0100000000000000 ffff8880010418c0 dead000000000100 dead000000000122
[    4.670353] raw: 0000000000000000 0000000000200020 00000000f5000000 0000000000000000
[    4.672192] page dumped because: kasan: bad access detected
[    4.673144]
[    4.673599] Memory state around the buggy address:
[    4.675006]  ffff888001ec6c80: fa fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
[    4.677516]  ffff888001ec6d00: fa fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
[    4.679495] >ffff888001ec6d80: fa fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
[    4.680794]                    ^
[    4.681362]  ffff888001ec6e00: 00 00 00 00 00 00 00 fc fc fc fc fc fc fc fc fc
[    4.682527]  ffff888001ec6e80: fa fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
[    4.684246] ==================================================================
[    4.685963] Kernel panic - not syncing: KASAN: panic_on_warn set ...
[    4.687476] CPU: 0 UID: 1000 PID: 73 Comm: e Not tainted 7.2.0-rc1-g7404ce516372 #1 PREEMPT(lazy)
[    4.689533] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014
[    4.691507] Call Trace:
[    4.692161]  <TASK>
[    4.692802]  vpanic+0x504/0x700
[    4.693724]  ? __pfx_vpanic+0x10/0x10
[    4.694559]  ? __pfx_vprintk_emit+0x10/0x10
[    4.696838]  ? io_vec_free+0x2c/0x90
[    4.697672]  panic+0xbd/0xc0
[    4.698335]  ? __pfx_panic+0x10/0x10
[    4.699117]  ? panic_on_this_cpu+0x15/0x30
[    4.700001]  check_panic_on_warn+0x61/0x80
[    4.700745]  end_report+0xba/0xe0
[    4.701371]  ? io_vec_free+0x2c/0x90
[    4.702265]  kasan_report_invalid_free+0xa4/0xc0
[    4.703239]  ? io_vec_free+0x2c/0x90
[    4.704064]  ? io_vec_free+0x2c/0x90
[    4.704818]  check_slab_allocation+0xe4/0x110
[    4.706513]  kfree+0x104/0x3b0
[    4.707744]  io_vec_free+0x2c/0x90
[    4.709009]  __io_submit_flush_completions+0xc03/0x1e40
[    4.709740]  ? io_issue_sqe+0x7d/0x14a0
[    4.710366]  io_submit_sqes+0xdb5/0x2310
[    4.711531]  ? __pfx_mutex_lock+0x10/0x10
[    4.712488]  __do_sys_io_uring_enter+0x701/0x11a0
[    4.713771]  ? __pfx___do_sys_io_uring_enter+0x10/0x10
[    4.715081]  ? fdget_pos+0x53/0x4c0
[    4.715804]  ? ksys_write+0xee/0x1c0
[    4.716247]  ? __pfx_ksys_write+0x10/0x10
[    4.717130]  do_syscall_64+0x102/0x5a0
[    4.717942]  entry_SYSCALL_64_after_hwframe+0x77/0x7f
[    4.718930] RIP: 0033:0x44895d
[    4.719488] Code: 28 c3 e8 06 20 00 00 66 0f 1f 44 00 00 f3 0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 8
[    4.723727] RSP: 002b:00007ffdfca0f868 EFLAGS: 00000246 ORIG_RAX: 00000000000001aa
[    4.726144] RAX: ffffffffffffffda RBX: 00007f615f4a1000 RCX: 000000000044895d
[    4.727793] RDX: 0000000000000001 RSI: 0000000000000001 RDI: 0000000000000005
[    4.729366] RBP: 00007f615f49e000 R08: 0000000000000000 R09: 0000000000000000
[    4.731044] R10: 0000000000000001 R11: 0000000000000246 R12: 0000000000000001
[    4.733021] R13: 00007ffdfca0fba8 R14: 00000000004c37d0 R15: 0000000000000001
[    4.734422]  </TASK>
[    4.735635] Kernel Offset: 0xb200000 from 0xffffffff81000000 (relocation range: 0xffffffff80000000-0xffffffffbfffffff)

On Mon, Jul 06, 2026 at 10:20:36AM -0600, Jens Axboe wrote:
> On 7/5/26 5:45 PM, Hao-Yu Yang wrote:
> > BUG: KASAN: double-free in io_vec_free+0x2c/0x90
> > Freed by task 73:
> >  kfree+0x104/0x3b0
> >  io_vec_free+0x2c/0x90
> >  __io_submit_flush_completions+0xc03/0x1e40
> >  io_submit_sqes+0xdb5/0x2310
> > 
> > Allocated by task 73:
> >  io_ring_buffers_peek+0x559/0xc60
> >  io_buffers_select+0x1c1/0x460
> >  io_send+0x770/0x1050
> 
> Please also send your reproducer, the above looks a bit synthesized
> rather than a real trace... Is it actually from KASAN, or is it from
> whatever LLM you're using?
> 
> -- 
> Jens Axboe

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v1] io_uring: fix dangling iovec after provided-buffer bundle grow failure
  2026-07-06 17:01   ` Hao-Yu Yang
@ 2026-07-06 17:13     ` Jens Axboe
  2026-07-06 17:34       ` Hao-Yu Yang
  0 siblings, 1 reply; 10+ messages in thread
From: Jens Axboe @ 2026-07-06 17:13 UTC (permalink / raw)
  To: Hao-Yu Yang; +Cc: linux-kernel, io-uring

On 7/6/26 11:01 AM, Hao-Yu Yang wrote:
> Sorry, i forgot to cc others mail
> 
> I discovered and wrote the PoC myself. Trigger way is
>  send1: Submit an IORING_OP_SEND request with four valid
>  provided buffers. The system will allocate and cache an
>  iovec array (of size 4) for this request and store the
>  pointer in kmsg->vec.iovec.
> 
>  send2: Submit a second send request with 8, and I set
>  the fourth passed-in address to point to an invalid address.
>  Now kmsg still hold old iovec, but old iovec object have
>  been freed.
> 
>  So this will lead dangling pointer.

Side note: please don't top post, linux mailing lists always reply
under the text for better readability. Top posting turns any kind
of threaded conversation into both a mess, and it's also wasteful.

Great thanks! Want to turn this into a liburing test case? Then we can
include it there as well, and it'd catch both UAF and memory leaks when
run.

-- 
Jens Axboe

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v1] io_uring: fix dangling iovec after provided-buffer bundle grow failure
  2026-07-06 17:13     ` Jens Axboe
@ 2026-07-06 17:34       ` Hao-Yu Yang
  2026-07-06 17:39         ` Jens Axboe
  0 siblings, 1 reply; 10+ messages in thread
From: Hao-Yu Yang @ 2026-07-06 17:34 UTC (permalink / raw)
  To: Jens Axboe; +Cc: linux-kernel, io-uring

On Mon, Jul 06, 2026 at 11:13:55AM -0600, Jens Axboe wrote:
> On 7/6/26 11:01 AM, Hao-Yu Yang wrote:
> > Sorry, i forgot to cc others mail
> > 
> > I discovered and wrote the PoC myself. Trigger way is
> >  send1: Submit an IORING_OP_SEND request with four valid
> >  provided buffers. The system will allocate and cache an
> >  iovec array (of size 4) for this request and store the
> >  pointer in kmsg->vec.iovec.
> > 
> >  send2: Submit a second send request with 8, and I set
> >  the fourth passed-in address to point to an invalid address.
> >  Now kmsg still hold old iovec, but old iovec object have
> >  been freed.
> > 
> >  So this will lead dangling pointer.
> 
> Side note: please don't top post, linux mailing lists always reply
> under the text for better readability. Top posting turns any kind
> of threaded conversation into both a mess, and it's also wasteful.
> 
> Great thanks! Want to turn this into a liburing test case? Then we can
> include it there as well, and it'd catch both UAF and memory leaks when
> run.
> 
> -- 
> Jens Axboe

How to turn this into a liburing test case? Should this be included in the v2 patch?

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v1] io_uring: fix dangling iovec after provided-buffer bundle grow failure
  2026-07-06 17:34       ` Hao-Yu Yang
@ 2026-07-06 17:39         ` Jens Axboe
  2026-07-06 17:46           ` Hao-Yu Yang
  0 siblings, 1 reply; 10+ messages in thread
From: Jens Axboe @ 2026-07-06 17:39 UTC (permalink / raw)
  To: Hao-Yu Yang; +Cc: linux-kernel, io-uring

On 7/6/26 11:34 AM, Hao-Yu Yang wrote:
> On Mon, Jul 06, 2026 at 11:13:55AM -0600, Jens Axboe wrote:
>> On 7/6/26 11:01 AM, Hao-Yu Yang wrote:
>>> Sorry, i forgot to cc others mail
>>>
>>> I discovered and wrote the PoC myself. Trigger way is
>>>  send1: Submit an IORING_OP_SEND request with four valid
>>>  provided buffers. The system will allocate and cache an
>>>  iovec array (of size 4) for this request and store the
>>>  pointer in kmsg->vec.iovec.
>>>
>>>  send2: Submit a second send request with 8, and I set
>>>  the fourth passed-in address to point to an invalid address.
>>>  Now kmsg still hold old iovec, but old iovec object have
>>>  been freed.
>>>
>>>  So this will lead dangling pointer.
>>
>> Side note: please don't top post, linux mailing lists always reply
>> under the text for better readability. Top posting turns any kind
>> of threaded conversation into both a mess, and it's also wasteful.
>>
>> Great thanks! Want to turn this into a liburing test case? Then we can
>> include it there as well, and it'd catch both UAF and memory leaks when
>> run.
>>
>> -- 
>> Jens Axboe
> 
> How to turn this into a liburing test case? Should this be included in
> the v2 patch?

Look at the tests in test/ in liburing. Or just send the reproducer and
I can get it turned into a test case.

Should be separate from a kernel patch, it's a patch for an entirely
different repository.


-- 
Jens Axboe

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v1] io_uring: fix dangling iovec after provided-buffer bundle grow failure
  2026-07-06 17:39         ` Jens Axboe
@ 2026-07-06 17:46           ` Hao-Yu Yang
  2026-07-06 18:06             ` Jens Axboe
  0 siblings, 1 reply; 10+ messages in thread
From: Hao-Yu Yang @ 2026-07-06 17:46 UTC (permalink / raw)
  To: Jens Axboe; +Cc: linux-kernel, io-uring

On Mon, Jul 06, 2026 at 11:39:14AM -0600, Jens Axboe wrote:
> On 7/6/26 11:34 AM, Hao-Yu Yang wrote:
> > On Mon, Jul 06, 2026 at 11:13:55AM -0600, Jens Axboe wrote:
> >> On 7/6/26 11:01 AM, Hao-Yu Yang wrote:
> >>> Sorry, i forgot to cc others mail
> >>>
> >>> I discovered and wrote the PoC myself. Trigger way is
> >>>  send1: Submit an IORING_OP_SEND request with four valid
> >>>  provided buffers. The system will allocate and cache an
> >>>  iovec array (of size 4) for this request and store the
> >>>  pointer in kmsg->vec.iovec.
> >>>
> >>>  send2: Submit a second send request with 8, and I set
> >>>  the fourth passed-in address to point to an invalid address.
> >>>  Now kmsg still hold old iovec, but old iovec object have
> >>>  been freed.
> >>>
> >>>  So this will lead dangling pointer.
> >>
> >> Side note: please don't top post, linux mailing lists always reply
> >> under the text for better readability. Top posting turns any kind
> >> of threaded conversation into both a mess, and it's also wasteful.
> >>
> >> Great thanks! Want to turn this into a liburing test case? Then we can
> >> include it there as well, and it'd catch both UAF and memory leaks when
> >> run.
> >>
> >> -- 
> >> Jens Axboe
> > 
> > How to turn this into a liburing test case? Should this be included in
> > the v2 patch?
> 
> Look at the tests in test/ in liburing. Or just send the reproducer and
> I can get it turned into a test case.
> 
> Should be separate from a kernel patch, it's a patch for an entirely
> different repository.
> 
> 
> -- 
> Jens Axboe

OK, I will send v2 patch first when i wake up. And I now my PoC to trigger this KASAN have became a exploit can use to priviledge escalation.
I think i should send this script to your email? (not included any public gmail?)

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v1] io_uring: fix dangling iovec after provided-buffer bundle grow failure
  2026-07-06 17:46           ` Hao-Yu Yang
@ 2026-07-06 18:06             ` Jens Axboe
  0 siblings, 0 replies; 10+ messages in thread
From: Jens Axboe @ 2026-07-06 18:06 UTC (permalink / raw)
  To: Hao-Yu Yang; +Cc: linux-kernel, io-uring

On 7/6/26 11:46 AM, Hao-Yu Yang wrote:
> On Mon, Jul 06, 2026 at 11:39:14AM -0600, Jens Axboe wrote:
>> On 7/6/26 11:34 AM, Hao-Yu Yang wrote:
>>> On Mon, Jul 06, 2026 at 11:13:55AM -0600, Jens Axboe wrote:
>>>> On 7/6/26 11:01 AM, Hao-Yu Yang wrote:
>>>>> Sorry, i forgot to cc others mail
>>>>>
>>>>> I discovered and wrote the PoC myself. Trigger way is
>>>>>  send1: Submit an IORING_OP_SEND request with four valid
>>>>>  provided buffers. The system will allocate and cache an
>>>>>  iovec array (of size 4) for this request and store the
>>>>>  pointer in kmsg->vec.iovec.
>>>>>
>>>>>  send2: Submit a second send request with 8, and I set
>>>>>  the fourth passed-in address to point to an invalid address.
>>>>>  Now kmsg still hold old iovec, but old iovec object have
>>>>>  been freed.
>>>>>
>>>>>  So this will lead dangling pointer.
>>>>
>>>> Side note: please don't top post, linux mailing lists always reply
>>>> under the text for better readability. Top posting turns any kind
>>>> of threaded conversation into both a mess, and it's also wasteful.
>>>>
>>>> Great thanks! Want to turn this into a liburing test case? Then we can
>>>> include it there as well, and it'd catch both UAF and memory leaks when
>>>> run.
>>>>
>>>> -- 
>>>> Jens Axboe
>>>
>>> How to turn this into a liburing test case? Should this be included in
>>> the v2 patch?
>>
>> Look at the tests in test/ in liburing. Or just send the reproducer and
>> I can get it turned into a test case.
>>
>> Should be separate from a kernel patch, it's a patch for an entirely
>> different repository.
>>
>>
>> -- 
>> Jens Axboe
> 
> OK, I will send v2 patch first when i wake up. And I now my PoC to
> trigger this KASAN have became a exploit can use to priviledge
> escalation. I think i should send this script to your email? (not
> included any public gmail?)

Like I said in my original reply, there's no security concerns here, as
the code in question is NOT IN A RELEASED kernel. It only exists in the
7.2-rc kernels, and the kernel documentation will tell you that unless
it's in a released kernel, it's not a security issue.

-- 
Jens Axboe

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2026-07-06 18:06 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-05 23:45 [PATCH v1] io_uring: fix dangling iovec after provided-buffer bundle grow failure Hao-Yu Yang
2026-07-06 16:19 ` Jens Axboe
2026-07-06 16:56   ` Hao-Yu Yang
2026-07-06 16:20 ` Jens Axboe
2026-07-06 17:01   ` Hao-Yu Yang
2026-07-06 17:13     ` Jens Axboe
2026-07-06 17:34       ` Hao-Yu Yang
2026-07-06 17:39         ` Jens Axboe
2026-07-06 17:46           ` Hao-Yu Yang
2026-07-06 18:06             ` Jens Axboe

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox