Skip to content

Commit 379475d

Browse files
Eric BiggersMikulas Patocka
authored andcommitted
dm-verity: reduce scope of real and wanted digests
In preparation for supporting interleaved hashing where dm-verity will need to keep track of the real and wanted digests for multiple data blocks simultaneously, stop using the want_digest and real_digest fields of struct dm_verity_io from so many different places. Specifically: - Make various functions take want_digest as a parameter rather than having it be implicitly passed via the struct dm_verity_io. - Add a new tmp_digest field, and use this instead of real_digest when computing a digest solely for the purpose of immediately checking it. The result is that real_digest and want_digest are used only by verity_verify_io(). Signed-off-by: Eric Biggers <ebiggers@kernel.org> Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
1 parent ba0f428 commit 379475d

4 files changed

Lines changed: 34 additions & 31 deletions

File tree

drivers/md/dm-verity-fec.c

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -188,14 +188,13 @@ static int fec_decode_bufs(struct dm_verity *v, struct dm_verity_io *io,
188188
* Locate data block erasures using verity hashes.
189189
*/
190190
static int fec_is_erasure(struct dm_verity *v, struct dm_verity_io *io,
191-
u8 *want_digest, u8 *data)
191+
const u8 *want_digest, const u8 *data)
192192
{
193193
if (unlikely(verity_hash(v, io, data, 1 << v->data_dev_block_bits,
194-
verity_io_real_digest(v, io))))
194+
io->tmp_digest)))
195195
return 0;
196196

197-
return memcmp(verity_io_real_digest(v, io), want_digest,
198-
v->digest_size) != 0;
197+
return memcmp(io->tmp_digest, want_digest, v->digest_size) != 0;
199198
}
200199

201200
/*
@@ -366,7 +365,7 @@ static void fec_init_bufs(struct dm_verity *v, struct dm_verity_fec_io *fio)
366365
*/
367366
static int fec_decode_rsb(struct dm_verity *v, struct dm_verity_io *io,
368367
struct dm_verity_fec_io *fio, u64 rsb, u64 offset,
369-
bool use_erasures)
368+
const u8 *want_digest, bool use_erasures)
370369
{
371370
int r, neras = 0;
372371
unsigned int pos;
@@ -392,12 +391,11 @@ static int fec_decode_rsb(struct dm_verity *v, struct dm_verity_io *io,
392391

393392
/* Always re-validate the corrected block against the expected hash */
394393
r = verity_hash(v, io, fio->output, 1 << v->data_dev_block_bits,
395-
verity_io_real_digest(v, io));
394+
io->tmp_digest);
396395
if (unlikely(r < 0))
397396
return r;
398397

399-
if (memcmp(verity_io_real_digest(v, io), verity_io_want_digest(v, io),
400-
v->digest_size)) {
398+
if (memcmp(io->tmp_digest, want_digest, v->digest_size)) {
401399
DMERR_LIMIT("%s: FEC %llu: failed to correct (%d erasures)",
402400
v->data_dev->name, (unsigned long long)rsb, neras);
403401
return -EILSEQ;
@@ -408,7 +406,8 @@ static int fec_decode_rsb(struct dm_verity *v, struct dm_verity_io *io,
408406

409407
/* Correct errors in a block. Copies corrected block to dest. */
410408
int verity_fec_decode(struct dm_verity *v, struct dm_verity_io *io,
411-
enum verity_block_type type, sector_t block, u8 *dest)
409+
enum verity_block_type type, const u8 *want_digest,
410+
sector_t block, u8 *dest)
412411
{
413412
int r;
414413
struct dm_verity_fec_io *fio = fec_io(io);
@@ -451,9 +450,9 @@ int verity_fec_decode(struct dm_verity *v, struct dm_verity_io *io,
451450
* them first. Do a second attempt with erasures if the corruption is
452451
* bad enough.
453452
*/
454-
r = fec_decode_rsb(v, io, fio, rsb, offset, false);
453+
r = fec_decode_rsb(v, io, fio, rsb, offset, want_digest, false);
455454
if (r < 0) {
456-
r = fec_decode_rsb(v, io, fio, rsb, offset, true);
455+
r = fec_decode_rsb(v, io, fio, rsb, offset, want_digest, true);
457456
if (r < 0)
458457
goto done;
459458
}

drivers/md/dm-verity-fec.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,8 @@ struct dm_verity_fec_io {
6868
extern bool verity_fec_is_enabled(struct dm_verity *v);
6969

7070
extern int verity_fec_decode(struct dm_verity *v, struct dm_verity_io *io,
71-
enum verity_block_type type, sector_t block,
72-
u8 *dest);
71+
enum verity_block_type type, const u8 *want_digest,
72+
sector_t block, u8 *dest);
7373

7474
extern unsigned int verity_fec_status_table(struct dm_verity *v, unsigned int sz,
7575
char *result, unsigned int maxlen);
@@ -99,6 +99,7 @@ static inline bool verity_fec_is_enabled(struct dm_verity *v)
9999
static inline int verity_fec_decode(struct dm_verity *v,
100100
struct dm_verity_io *io,
101101
enum verity_block_type type,
102+
const u8 *want_digest,
102103
sector_t block, u8 *dest)
103104
{
104105
return -EOPNOTSUPP;

drivers/md/dm-verity-target.c

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -229,12 +229,12 @@ static int verity_handle_err(struct dm_verity *v, enum verity_block_type type,
229229
* Verify hash of a metadata block pertaining to the specified data block
230230
* ("block" argument) at a specified level ("level" argument).
231231
*
232-
* On successful return, verity_io_want_digest(v, io) contains the hash value
233-
* for a lower tree level or for the data block (if we're at the lowest level).
232+
* On successful return, want_digest contains the hash value for a lower tree
233+
* level or for the data block (if we're at the lowest level).
234234
*
235235
* If "skip_unverified" is true, unverified buffer is skipped and 1 is returned.
236236
* If "skip_unverified" is false, unverified buffer is hashed and verified
237-
* against current value of verity_io_want_digest(v, io).
237+
* against current value of want_digest.
238238
*/
239239
static int verity_verify_level(struct dm_verity *v, struct dm_verity_io *io,
240240
sector_t block, int level, bool skip_unverified,
@@ -273,7 +273,7 @@ static int verity_verify_level(struct dm_verity *v, struct dm_verity_io *io,
273273
if (IS_ERR(data))
274274
return r;
275275
if (verity_fec_decode(v, io, DM_VERITY_BLOCK_TYPE_METADATA,
276-
hash_block, data) == 0) {
276+
want_digest, hash_block, data) == 0) {
277277
aux = dm_bufio_get_aux_data(buf);
278278
aux->hash_verified = 1;
279279
goto release_ok;
@@ -293,11 +293,11 @@ static int verity_verify_level(struct dm_verity *v, struct dm_verity_io *io,
293293
}
294294

295295
r = verity_hash(v, io, data, 1 << v->hash_dev_block_bits,
296-
verity_io_real_digest(v, io));
296+
io->tmp_digest);
297297
if (unlikely(r < 0))
298298
goto release_ret_r;
299299

300-
if (likely(memcmp(verity_io_real_digest(v, io), want_digest,
300+
if (likely(memcmp(io->tmp_digest, want_digest,
301301
v->digest_size) == 0))
302302
aux->hash_verified = 1;
303303
else if (static_branch_unlikely(&use_bh_wq_enabled) && io->in_bh) {
@@ -308,7 +308,7 @@ static int verity_verify_level(struct dm_verity *v, struct dm_verity_io *io,
308308
r = -EAGAIN;
309309
goto release_ret_r;
310310
} else if (verity_fec_decode(v, io, DM_VERITY_BLOCK_TYPE_METADATA,
311-
hash_block, data) == 0)
311+
want_digest, hash_block, data) == 0)
312312
aux->hash_verified = 1;
313313
else if (verity_handle_err(v,
314314
DM_VERITY_BLOCK_TYPE_METADATA,
@@ -372,7 +372,8 @@ int verity_hash_for_block(struct dm_verity *v, struct dm_verity_io *io,
372372
}
373373

374374
static noinline int verity_recheck(struct dm_verity *v, struct dm_verity_io *io,
375-
sector_t cur_block, u8 *dest)
375+
const u8 *want_digest, sector_t cur_block,
376+
u8 *dest)
376377
{
377378
struct page *page;
378379
void *buffer;
@@ -396,12 +397,11 @@ static noinline int verity_recheck(struct dm_verity *v, struct dm_verity_io *io,
396397
goto free_ret;
397398

398399
r = verity_hash(v, io, buffer, 1 << v->data_dev_block_bits,
399-
verity_io_real_digest(v, io));
400+
io->tmp_digest);
400401
if (unlikely(r))
401402
goto free_ret;
402403

403-
if (memcmp(verity_io_real_digest(v, io),
404-
verity_io_want_digest(v, io), v->digest_size)) {
404+
if (memcmp(io->tmp_digest, want_digest, v->digest_size)) {
405405
r = -EIO;
406406
goto free_ret;
407407
}
@@ -416,8 +416,9 @@ static noinline int verity_recheck(struct dm_verity *v, struct dm_verity_io *io,
416416

417417
static int verity_handle_data_hash_mismatch(struct dm_verity *v,
418418
struct dm_verity_io *io,
419-
struct bio *bio, sector_t blkno,
420-
u8 *data)
419+
struct bio *bio,
420+
const u8 *want_digest,
421+
sector_t blkno, u8 *data)
421422
{
422423
if (static_branch_unlikely(&use_bh_wq_enabled) && io->in_bh) {
423424
/*
@@ -426,14 +427,14 @@ static int verity_handle_data_hash_mismatch(struct dm_verity *v,
426427
*/
427428
return -EAGAIN;
428429
}
429-
if (verity_recheck(v, io, blkno, data) == 0) {
430+
if (verity_recheck(v, io, want_digest, blkno, data) == 0) {
430431
if (v->validated_blocks)
431432
set_bit(blkno, v->validated_blocks);
432433
return 0;
433434
}
434435
#if defined(CONFIG_DM_VERITY_FEC)
435-
if (verity_fec_decode(v, io, DM_VERITY_BLOCK_TYPE_DATA, blkno,
436-
data) == 0)
436+
if (verity_fec_decode(v, io, DM_VERITY_BLOCK_TYPE_DATA, want_digest,
437+
blkno, data) == 0)
437438
return 0;
438439
#endif
439440
if (bio->bi_status)
@@ -525,8 +526,9 @@ static int verity_verify_io(struct dm_verity_io *io)
525526
kunmap_local(data);
526527
continue;
527528
}
528-
r = verity_handle_data_hash_mismatch(v, io, bio, cur_block,
529-
data);
529+
r = verity_handle_data_hash_mismatch(v, io, bio,
530+
verity_io_want_digest(v, io),
531+
cur_block, data);
530532
kunmap_local(data);
531533
if (unlikely(r))
532534
return r;

drivers/md/dm-verity.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ struct dm_verity_io {
9999
struct work_struct work;
100100
struct work_struct bh_work;
101101

102+
u8 tmp_digest[HASH_MAX_DIGESTSIZE];
102103
u8 real_digest[HASH_MAX_DIGESTSIZE];
103104
u8 want_digest[HASH_MAX_DIGESTSIZE];
104105

0 commit comments

Comments
 (0)