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

Konstantin Khorenko khorenko at virtuozzo.com
Tue Mar 17 18:12:28 MSK 2026


The commit is pushed to "branch-rh10-6.12.0-55.52.1.4.x.vz10-ovz" and will appear at git at bitbucket.org:openvz/vzkernel.git
after rh10-6.12.0-55.52.1.4.10.vz10
------>
commit 104340fae40e2e2c5916c7bd13bcb42cd66860e6
Author: Konstantin Khorenko <khorenko at virtuozzo.com>
Date:   Tue Mar 17 11:24:34 2026 +0100

    dm-ploop: fix slab-out-of-bounds in iov_iter_advance on multi-page bvecs
    
    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: aceb22ce0b890 ("dm-ploop: Add ploop target driver")
    https://virtuozzo.atlassian.net/browse/VSTOR-126957
    
    Signed-off-by: Konstantin Khorenko <khorenko at virtuozzo.com>
    Reviewed-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
    
    Feature: dm-ploop: ploop target driver
---
 drivers/md/dm-ploop-map.c | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/drivers/md/dm-ploop-map.c b/drivers/md/dm-ploop-map.c
index 6fe62441471a1..3d35bd5fab0af 100644
--- a/drivers/md/dm-ploop-map.c
+++ b/drivers/md/dm-ploop-map.c
@@ -34,6 +34,19 @@ static void ploop_prq_endio(struct pio *pio, void *prq_ptr,
 
 extern struct static_key_false ploop_standby_check;
 
+/*
+ * Iterate over bvec entries without clamping to page boundaries.
+ * Unlike for_each_bvec() which uses bvec_iter_bvec() and splits
+ * multi-page entries into PAGE_SIZE chunks, this macro uses
+ * mp_bvec_iter_bvec() to walk actual bio_vec array entries.
+ */
+#define ploop_for_each_bvec(bv, bvec, iter, start)			\
+	for (iter = start;						\
+	     (iter.bi_size &&						\
+	      ((bv = mp_bvec_iter_bvec(bvec, iter)), 1) &&		\
+	      bv.bv_len);						\
+	     bvec_iter_advance(bvec, &iter, bv.bv_len))
+
 static unsigned int ploop_pio_nr_segs(struct pio *pio)
 {
 	struct bvec_iter bi = {
@@ -44,10 +57,10 @@ static unsigned int ploop_pio_nr_segs(struct pio *pio)
 	unsigned int nr_segs = 0;
 	struct bio_vec bv;
 
-	for_each_bvec(bv, pio->bi_io_vec, bi, bi)
-                nr_segs++;
+	ploop_for_each_bvec(bv, pio->bi_io_vec, bi, bi)
+		nr_segs++;
 
-        return nr_segs;
+	return nr_segs;
 }
 
 static sector_t ploop_rq_pos(struct ploop *ploop, struct request *rq)


More information about the Devel mailing list