]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
block: fix sanity checks in blk_rq_map_user_bvec
authorXinyu Zhang <xizhang@purestorage.com>
Wed, 23 Oct 2024 21:15:19 +0000 (15:15 -0600)
committerJens Axboe <axboe@kernel.dk>
Wed, 23 Oct 2024 23:02:48 +0000 (17:02 -0600)
blk_rq_map_user_bvec contains a check bytes + bv->bv_len > nr_iter which
causes unnecessary failures in NVMe passthrough I/O, reproducible as
follows:

- register a 2 page, page-aligned buffer against a ring
- use that buffer to do a 1 page io_uring NVMe passthrough read

The second (i = 1) iteration of the loop in blk_rq_map_user_bvec will
then have nr_iter == 1 page, bytes == 1 page, bv->bv_len == 1 page, so
the check bytes + bv->bv_len > nr_iter will succeed, causing the I/O to
fail. This failure is unnecessary, as when the check succeeds, it means
we've checked the entire buffer that will be used by the request - i.e.
blk_rq_map_user_bvec should complete successfully. Therefore, terminate
the loop early and return successfully when the check bytes + bv->bv_len
> nr_iter succeeds.

While we're at it, also remove the check that all segments in the bvec
are single-page. While this seems to be true for all users of the
function, it doesn't appear to be required anywhere downstream.

CC: stable@vger.kernel.org
Signed-off-by: Xinyu Zhang <xizhang@purestorage.com>
Co-developed-by: Uday Shankar <ushankar@purestorage.com>
Signed-off-by: Uday Shankar <ushankar@purestorage.com>
Fixes: 37987547932c ("block: extend functionality to map bvec iterator")
Link: https://lore.kernel.org/r/20241023211519.4177873-1-ushankar@purestorage.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
block/blk-map.c

index 0e1167b239342f71b76b54d8593435eb771bb83f..6ef2ec1f7d78bb4ffaa24934a364d321926273a5 100644 (file)
@@ -600,9 +600,7 @@ static int blk_rq_map_user_bvec(struct request *rq, const struct iov_iter *iter)
                if (nsegs >= nr_segs || bytes > UINT_MAX - bv->bv_len)
                        goto put_bio;
                if (bytes + bv->bv_len > nr_iter)
-                       goto put_bio;
-               if (bv->bv_offset + bv->bv_len > PAGE_SIZE)
-                       goto put_bio;
+                       break;
 
                nsegs++;
                bytes += bv->bv_len;