[PATCH for-next] io_uring/kbuf: validate ring provided buffer addresses with access_ok()

Jens Axboe <[email protected]>
Newsgroups org.kernel.vger.io-uring
Message-ID <[email protected]>
Ring-mapped provided buffers store buffer addresses in a shared memory
ring that userspace populates. When io_uring reads buf->addr from this
ring, it converts it to a user pointer via u64_to_user_ptr() without
any access_ok() validation. This is OK as the iov_iter copy accessors
validate the address when it's being used, but it's also different
than any other address import where it's always validated.

Validate the provided ring buffers at import time, unifying them with
the other access methods.

Fixes: c7fb19428d67 ("io_uring: add support for ring mapped supplied buffers")
Signed-off-by: Jens Axboe <[email protected]>

---

diff --git a/io_uring/kbuf.c b/io_uring/kbuf.c
index 7a1c65f631c2..a34db556a75c 100644
--- a/io_uring/kbuf.c
+++ b/io_uring/kbuf.c
@@ -250,6 +250,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 +312,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;

-- 
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.