[Devel] [PATCH vz9] dm-ploop: fix slab-out-of-bounds in iov_iter_advance on multi-page bvecs

Konstantin Khorenko khorenko at virtuozzo.com
Tue Mar 17 13:35:33 MSK 2026


ploop_pio_nr_segs() used for_each_bvec() to count the number of
segments in a pio. for_each_bvec() iterates via bvec_iter_bvec()
which clamps each segment to a single page boundary, so a single
multi-page bvec entry would be counted as multiple page-sized
segments. This overcounted nr_segs was then passed to iov_iter_bvec()
in ploop_submit_rw_mapped().

iov_iter_bvec_advance() uses nr_segs as the bvec array bound
(end = bvec + i->nr_segs), iterating one full bvec entry per step.
With an inflated nr_segs it reads past the end of the bvec array,
causing the KASAN slab-out-of-bounds in iov_iter_advance().

Fix by replacing for_each_bvec() with a manual loop that counts
actual bvec array entries, advancing through whole bvec entries
(respecting each entry's full bv_len) instead of page-sized
sub-segments.

Fixes: 0a54bd2238a16 ("dm-ploop: Add ploop target driver")
https://virtuozzo.atlassian.net/browse/VSTOR-126957

Signed-off-by: Konstantin Khorenko <khorenko at virtuozzo.com>

Feature: dm-ploop: ploop target driver
---
 drivers/md/dm-ploop-map.c | 24 +++++++++++++++---------
 1 file changed, 15 insertions(+), 9 deletions(-)

diff --git a/drivers/md/dm-ploop-map.c b/drivers/md/dm-ploop-map.c
index 2739cc3f09028..f8361640cefc6 100644
--- a/drivers/md/dm-ploop-map.c
+++ b/drivers/md/dm-ploop-map.c
@@ -36,18 +36,24 @@ extern struct static_key_false ploop_standby_check;
 
 static unsigned int ploop_pio_nr_segs(struct pio *pio)
 {
-	struct bvec_iter bi = {
-		.bi_size = pio->bi_iter.bi_size,
-		.bi_bvec_done = pio->bi_iter.bi_bvec_done,
-		.bi_idx = pio->bi_iter.bi_idx,
-	};
 	unsigned int nr_segs = 0;
-	struct bio_vec bv;
+	unsigned int bytes = pio->bi_iter.bi_size;
+	unsigned int idx = pio->bi_iter.bi_idx;
+	unsigned int done = pio->bi_iter.bi_bvec_done;
+	unsigned int avail;
 
-	for_each_bvec(bv, pio->bi_io_vec, bi, bi)
-                nr_segs++;
+	while (bytes > 0) {
+		avail = pio->bi_io_vec[idx].bv_len - done;
+
+		if (avail > bytes)
+			avail = bytes;
+		bytes -= avail;
+		idx++;
+		done = 0;
+		nr_segs++;
+	}
 
-        return nr_segs;
+	return nr_segs;
 }
 
 static sector_t ploop_rq_pos(struct ploop *ploop, struct request *rq)
-- 
2.43.0



More information about the Devel mailing list