Commit 4fd5ea43 authored by Darrick J. Wong's avatar Darrick J. Wong Committed by Theodore Ts'o

jbd2: checksum journal superblock

Calculate and verify a checksum covering the journal superblock.
Signed-off-by: default avatarDarrick J. Wong <djwong@us.ibm.com>
Signed-off-by: default avatar"Theodore Ts'o" <tytso@mit.edu>
parent 01b5adce
...@@ -106,6 +106,34 @@ int jbd2_verify_csum_type(journal_t *j, journal_superblock_t *sb) ...@@ -106,6 +106,34 @@ int jbd2_verify_csum_type(journal_t *j, journal_superblock_t *sb)
return sb->s_checksum_type == JBD2_CRC32C_CHKSUM; return sb->s_checksum_type == JBD2_CRC32C_CHKSUM;
} }
static __u32 jbd2_superblock_csum(journal_t *j, journal_superblock_t *sb)
{
__u32 csum, old_csum;
old_csum = sb->s_checksum;
sb->s_checksum = 0;
csum = jbd2_chksum(j, ~0, (char *)sb, sizeof(journal_superblock_t));
sb->s_checksum = old_csum;
return cpu_to_be32(csum);
}
int jbd2_superblock_csum_verify(journal_t *j, journal_superblock_t *sb)
{
if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2))
return 1;
return sb->s_checksum == jbd2_superblock_csum(j, sb);
}
void jbd2_superblock_csum_set(journal_t *j, journal_superblock_t *sb)
{
if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2))
return;
sb->s_checksum = jbd2_superblock_csum(j, sb);
}
/* /*
* Helper function used to manage commit timeouts * Helper function used to manage commit timeouts
*/ */
...@@ -1357,6 +1385,7 @@ static void jbd2_journal_update_sb_errno(journal_t *journal) ...@@ -1357,6 +1385,7 @@ static void jbd2_journal_update_sb_errno(journal_t *journal)
jbd_debug(1, "JBD2: updating superblock error (errno %d)\n", jbd_debug(1, "JBD2: updating superblock error (errno %d)\n",
journal->j_errno); journal->j_errno);
sb->s_errno = cpu_to_be32(journal->j_errno); sb->s_errno = cpu_to_be32(journal->j_errno);
jbd2_superblock_csum_set(journal, sb);
read_unlock(&journal->j_state_lock); read_unlock(&journal->j_state_lock);
jbd2_write_superblock(journal, WRITE_SYNC); jbd2_write_superblock(journal, WRITE_SYNC);
...@@ -1449,6 +1478,17 @@ static int journal_get_superblock(journal_t *journal) ...@@ -1449,6 +1478,17 @@ static int journal_get_superblock(journal_t *journal)
} }
} }
/* Check superblock checksum */
if (!jbd2_superblock_csum_verify(journal, sb)) {
printk(KERN_ERR "JBD: journal checksum error\n");
goto out;
}
/* Precompute checksum seed for all metadata */
if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2))
journal->j_csum_seed = jbd2_chksum(journal, ~0, sb->s_uuid,
sizeof(sb->s_uuid));
set_buffer_verified(bh); set_buffer_verified(bh);
return 0; return 0;
...@@ -1732,6 +1772,13 @@ int jbd2_journal_set_features (journal_t *journal, unsigned long compat, ...@@ -1732,6 +1772,13 @@ int jbd2_journal_set_features (journal_t *journal, unsigned long compat,
return 0; return 0;
} }
} }
/* Precompute checksum seed for all metadata */
if (JBD2_HAS_INCOMPAT_FEATURE(journal,
JBD2_FEATURE_INCOMPAT_CSUM_V2))
journal->j_csum_seed = jbd2_chksum(journal, ~0,
sb->s_uuid,
sizeof(sb->s_uuid));
} }
/* If enabling v1 checksums, downgrade superblock */ /* If enabling v1 checksums, downgrade superblock */
......
...@@ -969,6 +969,9 @@ struct journal_s ...@@ -969,6 +969,9 @@ struct journal_s
/* Reference to checksum algorithm driver via cryptoapi */ /* Reference to checksum algorithm driver via cryptoapi */
struct crypto_shash *j_chksum_driver; struct crypto_shash *j_chksum_driver;
/* Precomputed journal UUID checksum for seeding other checksums */
__u32 j_csum_seed;
}; };
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment