From: Jens Axboe Date: Thu, 9 Apr 2026 17:22:43 +0000 (-0600) Subject: io_uring/kbuf: validate ring provided buffer addresses with access_ok() X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=46800585ae04863c623b1563b03d12e9381089f1;p=thirdparty%2Flinux.git io_uring/kbuf: validate ring provided buffer addresses with access_ok() Commit: 809b997a5ce9 ("x86-64/arm64/powerpc: clean up and rename __copy_from_user_flushcache") sanitized that any provided copy helper should separately validate destination and source addresses, but we should also ensure that anything that is retrieved from a buffer is validated upfront. For ring provided buffers, always include an access_ok() when grabbing a new buffer. Fixes: c7fb19428d67 ("io_uring: add support for ring mapped supplied buffers") Signed-off-by: Jens Axboe --- diff --git a/io_uring/kbuf.c b/io_uring/kbuf.c index 7a1c65f631c2b..b9f4720ca22fc 100644 --- a/io_uring/kbuf.c +++ b/io_uring/kbuf.c @@ -210,10 +210,14 @@ static struct io_br_sel io_ring_buffer_select(struct io_kiocb *req, size_t *len, buf_len = READ_ONCE(buf->len); if (*len == 0 || *len > buf_len) *len = buf_len; + sel.addr = u64_to_user_ptr(READ_ONCE(buf->addr)); + if (unlikely(!access_ok(sel.addr, *len))) { + sel.addr = NULL; + return sel; + } req->flags |= REQ_F_BUFFER_RING | REQ_F_BUFFERS_COMMIT; req->buf_index = READ_ONCE(buf->bid); sel.buf_list = bl; - sel.addr = u64_to_user_ptr(READ_ONCE(buf->addr)); if (io_should_commit(req, issue_flags)) { if (!io_kbuf_commit(req, sel.buf_list, *len, 1)) @@ -250,6 +254,7 @@ static int io_ring_buffers_peek(struct io_kiocb *req, struct buf_sel_arg *arg, struct io_buffer_list *bl) { struct io_uring_buf_ring *br = bl->buf_ring; + struct iovec *org_iovs = arg->iovs; struct iovec *iov = arg->iovs; int nr_iovs = arg->nr_iovs; __u16 nr_avail, tail, head; @@ -311,6 +316,11 @@ static int io_ring_buffers_peek(struct io_kiocb *req, struct buf_sel_arg *arg, iov->iov_base = u64_to_user_ptr(READ_ONCE(buf->addr)); iov->iov_len = len; + if (unlikely(!access_ok(iov->iov_base, len))) { + if (arg->iovs != org_iovs) + kfree(arg->iovs); + return -EFAULT; + } iov++; arg->out_len += len;