Function __bio_map_kern() allocates new fresh bio with bi_bdev field undefined
and set to NULL. Than it calls bio_add_pc_page() which in turn calls
merge_bvec_fn() callback if defined, passing bvec_megre_data structure
pointer, with bi_bdev filesd initialized to "bio::bi_bdev" (equal to NULL).
There are 9 of them so far. At least some of them (like "rbd_merge_bvec",
"linear_mergeable_bvec") then dereference undefined "bvec_megre_data::bi_bdev"
to get start sector of the device, resulting in NULL pointer dereference.
This patch adds check for non-NULL bio->bi_bdev pointer to make sure, that the
device is defined, otherwise there is no sense to call this callback at all.

Signed-of-by: Stanislav Kinsbursky <stanislav.kinsbur...@profitbricks.com>
---
 block/bio.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/block/bio.c b/block/bio.c
index 0ec61c9..cb45186 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -725,7 +725,7 @@ static int __bio_add_page(struct request_queue *q, struct 
bio *bio, struct page
                        unsigned int prev_bv_len = prev->bv_len;
                        prev->bv_len += len;
 
-                       if (q->merge_bvec_fn) {
+                       if (q->merge_bvec_fn && bio->bi_bdev) {
                                struct bvec_merge_data bvm = {
                                        /* prev_bvec is already charged in
                                           bi_size, discharge it in order to
@@ -787,7 +787,7 @@ static int __bio_add_page(struct request_queue *q, struct 
bio *bio, struct page
         * depending on offset), it can specify a merge_bvec_fn in the
         * queue to get further control
         */
-       if (q->merge_bvec_fn) {
+       if (q->merge_bvec_fn && bio->bi_bdev) {
                struct bvec_merge_data bvm = {
                        .bi_bdev = bio->bi_bdev,
                        .bi_sector = bio->bi_iter.bi_sector,

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to