io_uring/zcrx: improve area validation
dmabuf backed area will be taking an offset instead of addresses, and io_buffer_validate() is not flexible enough to facilitate it. It also takes an iovec, which may truncate the u64 length zcrx takes. Add a new helper function for validation. Signed-off-by: Pavel Begunkov <asml.silence@gmail.com> Link: https://lore.kernel.org/r/0b3b735391a0a8f8971bf0121c19765131fddd3b.1746097431.git.asml.silence@gmail.com Signed-off-by: Jens Axboe <axboe@kernel.dk>pull/1250/head
parent
91db6edc57
commit
d760d3f59f
|
|
@ -80,10 +80,21 @@ static int io_account_mem(struct io_ring_ctx *ctx, unsigned long nr_pages)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int io_buffer_validate(struct iovec *iov)
|
||||
int io_validate_user_buf_range(u64 uaddr, u64 ulen)
|
||||
{
|
||||
unsigned long tmp, acct_len = iov->iov_len + (PAGE_SIZE - 1);
|
||||
unsigned long tmp, base = (unsigned long)uaddr;
|
||||
unsigned long acct_len = (unsigned long)PAGE_ALIGN(ulen);
|
||||
|
||||
/* arbitrary limit, but we need something */
|
||||
if (ulen > SZ_1G || !ulen)
|
||||
return -EFAULT;
|
||||
if (check_add_overflow(base, acct_len, &tmp))
|
||||
return -EOVERFLOW;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int io_buffer_validate(struct iovec *iov)
|
||||
{
|
||||
/*
|
||||
* Don't impose further limits on the size and buffer
|
||||
* constraints here, we'll -EINVAL later when IO is
|
||||
|
|
@ -91,17 +102,9 @@ int io_buffer_validate(struct iovec *iov)
|
|||
*/
|
||||
if (!iov->iov_base)
|
||||
return iov->iov_len ? -EFAULT : 0;
|
||||
if (!iov->iov_len)
|
||||
return -EFAULT;
|
||||
|
||||
/* arbitrary limit, but we need something */
|
||||
if (iov->iov_len > SZ_1G)
|
||||
return -EFAULT;
|
||||
|
||||
if (check_add_overflow((unsigned long)iov->iov_base, acct_len, &tmp))
|
||||
return -EOVERFLOW;
|
||||
|
||||
return 0;
|
||||
return io_validate_user_buf_range((unsigned long)iov->iov_base,
|
||||
iov->iov_len);
|
||||
}
|
||||
|
||||
static void io_release_ubuf(void *priv)
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ int io_register_rsrc_update(struct io_ring_ctx *ctx, void __user *arg,
|
|||
unsigned size, unsigned type);
|
||||
int io_register_rsrc(struct io_ring_ctx *ctx, void __user *arg,
|
||||
unsigned int size, unsigned int type);
|
||||
int io_buffer_validate(struct iovec *iov);
|
||||
int io_validate_user_buf_range(u64 uaddr, u64 ulen);
|
||||
|
||||
bool io_check_coalesce_buffer(struct page **page_array, int nr_pages,
|
||||
struct io_imu_folio_data *data);
|
||||
|
|
|
|||
|
|
@ -209,7 +209,6 @@ static int io_zcrx_create_area(struct io_zcrx_ifq *ifq,
|
|||
{
|
||||
struct io_zcrx_area *area;
|
||||
int i, ret, nr_pages, nr_iovs;
|
||||
struct iovec iov;
|
||||
|
||||
if (area_reg->flags || area_reg->rq_area_token)
|
||||
return -EINVAL;
|
||||
|
|
@ -218,11 +217,11 @@ static int io_zcrx_create_area(struct io_zcrx_ifq *ifq,
|
|||
if (area_reg->addr & ~PAGE_MASK || area_reg->len & ~PAGE_MASK)
|
||||
return -EINVAL;
|
||||
|
||||
iov.iov_base = u64_to_user_ptr(area_reg->addr);
|
||||
iov.iov_len = area_reg->len;
|
||||
ret = io_buffer_validate(&iov);
|
||||
ret = io_validate_user_buf_range(area_reg->addr, area_reg->len);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (!area_reg->addr)
|
||||
return -EFAULT;
|
||||
|
||||
ret = -ENOMEM;
|
||||
area = kzalloc(sizeof(*area), GFP_KERNEL);
|
||||
|
|
|
|||
Loading…
Reference in New Issue