Re: [PATCH v1] io_uring: fix dangling iovec after provided-buffer bundle grow failure

Jens Axboe <[email protected]>
Newsgroups org.kernel.vger.io-uring,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.