dm verity: fix biovecs hash calculation regression
authorMilan Broz <gmazyland@gmail.com>
Mon, 14 Apr 2014 20:02:30 +0000 (22:02 +0200)
committerMike Snitzer <snitzer@redhat.com>
Tue, 15 Apr 2014 16:19:24 +0000 (12:19 -0400)
Commit 003b5c5719f159f4f4bf97511c4702a0638313dd ("block: Convert drivers
to immutable biovecs") incorrectly converted biovec iteration in
dm-verity to always calculate the hash from a full biovec, but the
function only needs to calculate the hash from part of the biovec (up to
the calculated "todo" value).

Fix this issue by limiting hash input to only the requested data size.

This problem was identified using the cryptsetup regression test for
veritysetup (verity-compat-test).

Signed-off-by: Milan Broz <gmazyland@gmail.com>
Acked-by: Mikulas Patocka <mpatocka@redhat.com>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Cc: stable@vger.kernel.org # 3.14+
drivers/md/dm-verity.c

index 796007a..7a7bab8 100644 (file)
@@ -330,15 +330,17 @@ test_block_hash:
                                return r;
                        }
                }
-
                todo = 1 << v->data_dev_block_bits;
-               while (io->iter.bi_size) {
+               do {
                        u8 *page;
+                       unsigned len;
                        struct bio_vec bv = bio_iter_iovec(bio, io->iter);
 
                        page = kmap_atomic(bv.bv_page);
-                       r = crypto_shash_update(desc, page + bv.bv_offset,
-                                               bv.bv_len);
+                       len = bv.bv_len;
+                       if (likely(len >= todo))
+                               len = todo;
+                       r = crypto_shash_update(desc, page + bv.bv_offset, len);
                        kunmap_atomic(page);
 
                        if (r < 0) {
@@ -346,8 +348,9 @@ test_block_hash:
                                return r;
                        }
 
-                       bio_advance_iter(bio, &io->iter, bv.bv_len);
-               }
+                       bio_advance_iter(bio, &io->iter, len);
+                       todo -= len;
+               } while (todo);
 
                if (!v->version) {
                        r = crypto_shash_update(desc, v->salt, v->salt_size);