Skip to content

Commit 3d17ade

Browse files
adam900710kdave
authored andcommitted
btrfs: make thaw time super block check to also verify checksum
Previous commit a05d3c9 ("btrfs: check superblock to ensure the fs was not modified at thaw time") only checks the content of the super block, but it doesn't really check if the on-disk super block has a matching checksum. This patch will add the checksum verification to thaw time superblock verification. This involves the following extra changes: - Export btrfs_check_super_csum() As we need to call it in super.c. - Change the argument list of btrfs_check_super_csum() Instead of passing a char *, directly pass struct btrfs_super_block * pointer. - Verify that our checksum type didn't change before checking the checksum value, like it's done at mount time Fixes: a05d3c9 ("btrfs: check superblock to ensure the fs was not modified at thaw time") Reviewed-by: Johannes Thumshirn <[email protected]> Signed-off-by: Qu Wenruo <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent 968b715 commit 3d17ade

File tree

3 files changed

+22
-6
lines changed

3 files changed

+22
-6
lines changed

fs/btrfs/disk-io.c

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -166,11 +166,9 @@ static bool btrfs_supported_super_csum(u16 csum_type)
166166
* Return 0 if the superblock checksum type matches the checksum value of that
167167
* algorithm. Pass the raw disk superblock data.
168168
*/
169-
static int btrfs_check_super_csum(struct btrfs_fs_info *fs_info,
170-
char *raw_disk_sb)
169+
int btrfs_check_super_csum(struct btrfs_fs_info *fs_info,
170+
const struct btrfs_super_block *disk_sb)
171171
{
172-
struct btrfs_super_block *disk_sb =
173-
(struct btrfs_super_block *)raw_disk_sb;
174172
char result[BTRFS_CSUM_SIZE];
175173
SHASH_DESC_ON_STACK(shash, fs_info->csum_shash);
176174

@@ -181,7 +179,7 @@ static int btrfs_check_super_csum(struct btrfs_fs_info *fs_info,
181179
* BTRFS_SUPER_INFO_SIZE range, we expect that the unused space is
182180
* filled with zeros and is included in the checksum.
183181
*/
184-
crypto_shash_digest(shash, raw_disk_sb + BTRFS_CSUM_SIZE,
182+
crypto_shash_digest(shash, (const u8 *)disk_sb + BTRFS_CSUM_SIZE,
185183
BTRFS_SUPER_INFO_SIZE - BTRFS_CSUM_SIZE, result);
186184

187185
if (memcmp(disk_sb->csum, result, fs_info->csum_size))
@@ -3479,7 +3477,7 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device
34793477
* We want to check superblock checksum, the type is stored inside.
34803478
* Pass the whole disk block of size BTRFS_SUPER_INFO_SIZE (4k).
34813479
*/
3482-
if (btrfs_check_super_csum(fs_info, (u8 *)disk_super)) {
3480+
if (btrfs_check_super_csum(fs_info, disk_super)) {
34833481
btrfs_err(fs_info, "superblock checksum mismatch");
34843482
err = -EINVAL;
34853483
btrfs_release_disk_super(disk_super);

fs/btrfs/disk-io.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ struct extent_buffer *btrfs_find_create_tree_block(
4242
void btrfs_clean_tree_block(struct extent_buffer *buf);
4343
void btrfs_clear_oneshot_options(struct btrfs_fs_info *fs_info);
4444
int btrfs_start_pre_rw_mount(struct btrfs_fs_info *fs_info);
45+
int btrfs_check_super_csum(struct btrfs_fs_info *fs_info,
46+
const struct btrfs_super_block *disk_sb);
4547
int __cold open_ctree(struct super_block *sb,
4648
struct btrfs_fs_devices *fs_devices,
4749
char *options);

fs/btrfs/super.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2555,6 +2555,7 @@ static int check_dev_super(struct btrfs_device *dev)
25552555
{
25562556
struct btrfs_fs_info *fs_info = dev->fs_info;
25572557
struct btrfs_super_block *sb;
2558+
u16 csum_type;
25582559
int ret = 0;
25592560

25602561
/* This should be called with fs still frozen. */
@@ -2569,6 +2570,21 @@ static int check_dev_super(struct btrfs_device *dev)
25692570
if (IS_ERR(sb))
25702571
return PTR_ERR(sb);
25712572

2573+
/* Verify the checksum. */
2574+
csum_type = btrfs_super_csum_type(sb);
2575+
if (csum_type != btrfs_super_csum_type(fs_info->super_copy)) {
2576+
btrfs_err(fs_info, "csum type changed, has %u expect %u",
2577+
csum_type, btrfs_super_csum_type(fs_info->super_copy));
2578+
ret = -EUCLEAN;
2579+
goto out;
2580+
}
2581+
2582+
if (btrfs_check_super_csum(fs_info, sb)) {
2583+
btrfs_err(fs_info, "csum for on-disk super block no longer matches");
2584+
ret = -EUCLEAN;
2585+
goto out;
2586+
}
2587+
25722588
/* Btrfs_validate_super() includes fsid check against super->fsid. */
25732589
ret = btrfs_validate_super(fs_info, sb, 0);
25742590
if (ret < 0)

0 commit comments

Comments
 (0)