io_uring: don't assume uaddr alignment in io_vec_fill_bvec

There is no guaranteed alignment for user pointers. Don't use mask
trickery and adjust the offset by bv_offset.

Cc: stable@vger.kernel.org
Reported-by: David Hildenbrand <david@redhat.com>
Fixes: 9ef4cbbcb4 ("io_uring: add infra for importing vectored reg buffers")
Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
Link: https://lore.kernel.org/io-uring/19530391f5c361a026ac9b401ff8e123bde55d98.1750771718.git.asml.silence@gmail.com/
Signed-off-by: Jens Axboe <axboe@kernel.dk>
pull/1280/head
Pavel Begunkov 2025-06-24 14:40:35 +01:00 committed by Jens Axboe
parent 3a3c6d6157
commit e1d7727b73
1 changed files with 7 additions and 3 deletions

View File

@ -1339,7 +1339,6 @@ static int io_vec_fill_bvec(int ddir, struct iov_iter *iter,
{ {
unsigned long folio_size = 1 << imu->folio_shift; unsigned long folio_size = 1 << imu->folio_shift;
unsigned long folio_mask = folio_size - 1; unsigned long folio_mask = folio_size - 1;
u64 folio_addr = imu->ubuf & ~folio_mask;
struct bio_vec *res_bvec = vec->bvec; struct bio_vec *res_bvec = vec->bvec;
size_t total_len = 0; size_t total_len = 0;
unsigned bvec_idx = 0; unsigned bvec_idx = 0;
@ -1361,8 +1360,13 @@ static int io_vec_fill_bvec(int ddir, struct iov_iter *iter,
if (unlikely(check_add_overflow(total_len, iov_len, &total_len))) if (unlikely(check_add_overflow(total_len, iov_len, &total_len)))
return -EOVERFLOW; return -EOVERFLOW;
/* by using folio address it also accounts for bvec offset */ offset = buf_addr - imu->ubuf;
offset = buf_addr - folio_addr; /*
* Only the first bvec can have non zero bv_offset, account it
* here and work with full folios below.
*/
offset += imu->bvec[0].bv_offset;
src_bvec = imu->bvec + (offset >> imu->folio_shift); src_bvec = imu->bvec + (offset >> imu->folio_shift);
offset &= folio_mask; offset &= folio_mask;