Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Pavel Begunkov and committed by
Jens Axboe
d760d3f5 91db6edc

+19 -17
+15 -12
io_uring/rsrc.c
··· 80 80 return 0; 81 81 } 82 82 83 - int io_buffer_validate(struct iovec *iov) 83 + int io_validate_user_buf_range(u64 uaddr, u64 ulen) 84 84 { 85 - unsigned long tmp, acct_len = iov->iov_len + (PAGE_SIZE - 1); 85 + unsigned long tmp, base = (unsigned long)uaddr; 86 + unsigned long acct_len = (unsigned long)PAGE_ALIGN(ulen); 86 87 88 + /* arbitrary limit, but we need something */ 89 + if (ulen > SZ_1G || !ulen) 90 + return -EFAULT; 91 + if (check_add_overflow(base, acct_len, &tmp)) 92 + return -EOVERFLOW; 93 + return 0; 94 + } 95 + 96 + static int io_buffer_validate(struct iovec *iov) 97 + { 87 98 /* 88 99 * Don't impose further limits on the size and buffer 89 100 * constraints here, we'll -EINVAL later when IO is ··· 102 91 */ 103 92 if (!iov->iov_base) 104 93 return iov->iov_len ? -EFAULT : 0; 105 - if (!iov->iov_len) 106 - return -EFAULT; 107 94 108 - /* arbitrary limit, but we need something */ 109 - if (iov->iov_len > SZ_1G) 110 - return -EFAULT; 111 - 112 - if (check_add_overflow((unsigned long)iov->iov_base, acct_len, &tmp)) 113 - return -EOVERFLOW; 114 - 115 - return 0; 95 + return io_validate_user_buf_range((unsigned long)iov->iov_base, 96 + iov->iov_len); 116 97 } 117 98 118 99 static void io_release_ubuf(void *priv)
+1 -1
io_uring/rsrc.h
··· 83 83 unsigned size, unsigned type); 84 84 int io_register_rsrc(struct io_ring_ctx *ctx, void __user *arg, 85 85 unsigned int size, unsigned int type); 86 - int io_buffer_validate(struct iovec *iov); 86 + int io_validate_user_buf_range(u64 uaddr, u64 ulen); 87 87 88 88 bool io_check_coalesce_buffer(struct page **page_array, int nr_pages, 89 89 struct io_imu_folio_data *data);
+3 -4
io_uring/zcrx.c
··· 209 209 { 210 210 struct io_zcrx_area *area; 211 211 int i, ret, nr_pages, nr_iovs; 212 - struct iovec iov; 213 212 214 213 if (area_reg->flags || area_reg->rq_area_token) 215 214 return -EINVAL; ··· 217 218 if (area_reg->addr & ~PAGE_MASK || area_reg->len & ~PAGE_MASK) 218 219 return -EINVAL; 219 220 220 - iov.iov_base = u64_to_user_ptr(area_reg->addr); 221 - iov.iov_len = area_reg->len; 222 - ret = io_buffer_validate(&iov); 221 + ret = io_validate_user_buf_range(area_reg->addr, area_reg->len); 223 222 if (ret) 224 223 return ret; 224 + if (!area_reg->addr) 225 + return -EFAULT; 225 226 226 227 ret = -ENOMEM; 227 228 area = kzalloc(sizeof(*area), GFP_KERNEL);