All of lore.kernel.org
 help / color / mirror / Atom feed
* [dm-devel] [PATCH] block: fix a crash when bio_for_each_folio_all iterates over an empty bio
@ 2023-04-17 19:11 ` Mikulas Patocka
  0 siblings, 0 replies; 12+ messages in thread
From: Mikulas Patocka @ 2023-04-17 19:11 UTC (permalink / raw)
  To: Matthew Wilcox, Jens Axboe, Christoph Hellwig, Darrick J. Wong
  Cc: linux-block, Mike Snitzer, dm-devel

If we use bio_for_each_folio_all on an empty bio, it will access the first
bio vector unconditionally (it is uninitialized) and it may crash
depending on the uninitialized data.

This patch fixes it by checking the parameter "i" against "bio->bi_vcnt"
and returning NULL fi->folio if it is out of range.

The patch also drops the test "if (fi->_i + 1 < bio->bi_vcnt)" from
bio_next_folio because the same condition is already being checked in
bio_first_folio.

Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>

---
 include/linux/bio.h |   24 +++++++++++++-----------
 1 file changed, 13 insertions(+), 11 deletions(-)

Index: linux-2.6/include/linux/bio.h
===================================================================
--- linux-2.6.orig/include/linux/bio.h
+++ linux-2.6/include/linux/bio.h
@@ -279,15 +279,19 @@ struct folio_iter {
 static inline void bio_first_folio(struct folio_iter *fi, struct bio *bio,
 				   int i)
 {
-	struct bio_vec *bvec = bio_first_bvec_all(bio) + i;
+	if (i < bio->bi_vcnt) {
+		struct bio_vec *bvec = bio_first_bvec_all(bio) + i;
 
-	fi->folio = page_folio(bvec->bv_page);
-	fi->offset = bvec->bv_offset +
-			PAGE_SIZE * (bvec->bv_page - &fi->folio->page);
-	fi->_seg_count = bvec->bv_len;
-	fi->length = min(folio_size(fi->folio) - fi->offset, fi->_seg_count);
-	fi->_next = folio_next(fi->folio);
-	fi->_i = i;
+		fi->folio = page_folio(bvec->bv_page);
+		fi->offset = bvec->bv_offset +
+				PAGE_SIZE * (bvec->bv_page - &fi->folio->page);
+		fi->_seg_count = bvec->bv_len;
+		fi->length = min(folio_size(fi->folio) - fi->offset, fi->_seg_count);
+		fi->_next = folio_next(fi->folio);
+		fi->_i = i;
+	} else {
+		fi->folio = NULL;
+	}
 }
 
 static inline void bio_next_folio(struct folio_iter *fi, struct bio *bio)
@@ -298,10 +302,8 @@ static inline void bio_next_folio(struct
 		fi->offset = 0;
 		fi->length = min(folio_size(fi->folio), fi->_seg_count);
 		fi->_next = folio_next(fi->folio);
-	} else if (fi->_i + 1 < bio->bi_vcnt) {
-		bio_first_folio(fi, bio, fi->_i + 1);
 	} else {
-		fi->folio = NULL;
+		bio_first_folio(fi, bio, fi->_i + 1);
 	}
 }
 
--
dm-devel mailing list
dm-devel@redhat.com
https://listman.redhat.com/mailman/listinfo/dm-devel


^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2023-06-09 13:22 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-04-17 19:11 [dm-devel] [PATCH] block: fix a crash when bio_for_each_folio_all iterates over an empty bio Mikulas Patocka
2023-04-17 19:11 ` Mikulas Patocka
2023-04-17 19:32 ` [dm-devel] " Matthew Wilcox
2023-04-17 19:32   ` Matthew Wilcox
2023-04-17 19:56   ` [dm-devel] " Mikulas Patocka
2023-04-17 19:56     ` Mikulas Patocka
2023-04-18  4:57   ` [dm-devel] " Christoph Hellwig
2023-04-18  4:57     ` Christoph Hellwig
2023-04-18 15:20 ` [dm-devel] " Mike Snitzer
2023-04-18 15:20   ` Mike Snitzer
2023-06-09 13:22   ` [dm-devel] " Mike Snitzer
2023-06-09 13:22     ` Mike Snitzer

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.