]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
ublk: don't mutate struct bio_vec in iteration
authorCaleb Sander Mateos <csander@purestorage.com>
Tue, 9 Dec 2025 03:14:23 +0000 (20:14 -0700)
committerJens Axboe <axboe@kernel.dk>
Tue, 9 Dec 2025 17:20:18 +0000 (10:20 -0700)
__bio_for_each_segment() uses the returned struct bio_vec's bv_len field
to advance the struct bvec_iter at the end of each loop iteration. So
it's incorrect to modify it during the loop. Don't assign to bv_len (or
bv_offset, for that matter) in ublk_copy_user_pages().

Signed-off-by: Caleb Sander Mateos <csander@purestorage.com>
Fixes: e87d66ab27ac ("ublk: use rq_for_each_segment() for user copy")
Reviewed-by: Ming Lei <ming.lei@redhat.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
drivers/block/ublk_drv.c

index 3ecaafacfd20388626627d65578b352a64200fe9..df9831783a13391e2acb8cfff3abdb20cd01dafc 100644 (file)
@@ -926,6 +926,7 @@ static size_t ublk_copy_user_pages(const struct request *req,
        size_t done = 0;
 
        rq_for_each_segment(bv, req, iter) {
+               unsigned len;
                void *bv_buf;
                size_t copied;
 
@@ -934,18 +935,17 @@ static size_t ublk_copy_user_pages(const struct request *req,
                        continue;
                }
 
-               bv.bv_offset += offset;
-               bv.bv_len -= offset;
-               bv_buf = bvec_kmap_local(&bv);
+               len = bv.bv_len - offset;
+               bv_buf = kmap_local_page(bv.bv_page) + bv.bv_offset + offset;
                if (dir == ITER_DEST)
-                       copied = copy_to_iter(bv_buf, bv.bv_len, uiter);
+                       copied = copy_to_iter(bv_buf, len, uiter);
                else
-                       copied = copy_from_iter(bv_buf, bv.bv_len, uiter);
+                       copied = copy_from_iter(bv_buf, len, uiter);
 
                kunmap_local(bv_buf);
 
                done += copied;
-               if (copied < bv.bv_len)
+               if (copied < len)
                        break;
 
                offset = 0;