Reviewed-by: Pavel Tikhomirov <[email protected]>
(for both v9 and v10 versions)
On 3/17/26 13:38, Konstantin Khorenko wrote:
> 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 <[email protected]>
>
> Feature: dm-ploop: ploop target driver
> ---
> v2 changes:
> - a new macros has been introduced similar to the qcow2_for_each_bvec
> to make the code closer to dm-qcow2 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 2739cc3f09028..26224fcc8095d 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 && \
alignment is a bit off to my taste
> + ((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)
--
Best regards, Pavel Tikhomirov
Senior Software Developer, Virtuozzo.
_______________________________________________
Devel mailing list
[email protected]
https://lists.openvz.org/mailman/listinfo/devel