diff options
Diffstat (limited to 'fs/jbd2/recovery.c')
-rw-r--r-- | fs/jbd2/recovery.c | 22 |
1 files changed, 22 insertions, 0 deletions
diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c index 980f3d6b5f88..728ecd0705d9 100644 --- a/fs/jbd2/recovery.c +++ b/fs/jbd2/recovery.c | |||
@@ -706,6 +706,25 @@ static int do_one_pass(journal_t *journal, | |||
706 | return err; | 706 | return err; |
707 | } | 707 | } |
708 | 708 | ||
709 | static int jbd2_revoke_block_csum_verify(journal_t *j, | ||
710 | void *buf) | ||
711 | { | ||
712 | struct jbd2_journal_revoke_tail *tail; | ||
713 | __u32 provided, calculated; | ||
714 | |||
715 | if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2)) | ||
716 | return 1; | ||
717 | |||
718 | tail = (struct jbd2_journal_revoke_tail *)(buf + j->j_blocksize - | ||
719 | sizeof(struct jbd2_journal_revoke_tail)); | ||
720 | provided = tail->r_checksum; | ||
721 | tail->r_checksum = 0; | ||
722 | calculated = jbd2_chksum(j, j->j_csum_seed, buf, j->j_blocksize); | ||
723 | tail->r_checksum = provided; | ||
724 | |||
725 | provided = be32_to_cpu(provided); | ||
726 | return provided == calculated; | ||
727 | } | ||
709 | 728 | ||
710 | /* Scan a revoke record, marking all blocks mentioned as revoked. */ | 729 | /* Scan a revoke record, marking all blocks mentioned as revoked. */ |
711 | 730 | ||
@@ -720,6 +739,9 @@ static int scan_revoke_records(journal_t *journal, struct buffer_head *bh, | |||
720 | offset = sizeof(jbd2_journal_revoke_header_t); | 739 | offset = sizeof(jbd2_journal_revoke_header_t); |
721 | max = be32_to_cpu(header->r_count); | 740 | max = be32_to_cpu(header->r_count); |
722 | 741 | ||
742 | if (!jbd2_revoke_block_csum_verify(journal, header)) | ||
743 | return -EINVAL; | ||
744 | |||
723 | if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_64BIT)) | 745 | if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_64BIT)) |
724 | record_len = 8; | 746 | record_len = 8; |
725 | 747 | ||