diff --git a/io_uring/kbuf.c b/io_uring/kbuf.c index 7a1c65f631c2..b9f4720ca22f 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;