| From 8d5a803c6a6ce4ec258e31f76059ea5153ba46ef Mon Sep 17 00:00:00 2001 |
| From: Theodore Ts'o <tytso@mit.edu> |
| Date: Thu, 12 Jul 2018 19:08:05 -0400 |
| Subject: ext4: check for allocation block validity with block group locked |
| |
| From: Theodore Ts'o <tytso@mit.edu> |
| |
| commit 8d5a803c6a6ce4ec258e31f76059ea5153ba46ef upstream. |
| |
| With commit 044e6e3d74a3: "ext4: don't update checksum of new |
| initialized bitmaps" the buffer valid bit will get set without |
| actually setting up the checksum for the allocation bitmap, since the |
| checksum will get calculated once we actually allocate an inode or |
| block. |
| |
| If we are doing this, then we need to (re-)check the verified bit |
| after we take the block group lock. Otherwise, we could race with |
| another process reading and verifying the bitmap, which would then |
| complain about the checksum being invalid. |
| |
| https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1780137 |
| |
| Signed-off-by: Theodore Ts'o <tytso@mit.edu> |
| Cc: stable@kernel.org |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| fs/ext4/balloc.c | 3 +++ |
| fs/ext4/ialloc.c | 3 +++ |
| 2 files changed, 6 insertions(+) |
| |
| --- a/fs/ext4/balloc.c |
| +++ b/fs/ext4/balloc.c |
| @@ -378,6 +378,8 @@ static int ext4_validate_block_bitmap(st |
| return -EFSCORRUPTED; |
| |
| ext4_lock_group(sb, block_group); |
| + if (buffer_verified(bh)) |
| + goto verified; |
| if (unlikely(!ext4_block_bitmap_csum_verify(sb, block_group, |
| desc, bh))) { |
| ext4_unlock_group(sb, block_group); |
| @@ -400,6 +402,7 @@ static int ext4_validate_block_bitmap(st |
| return -EFSCORRUPTED; |
| } |
| set_buffer_verified(bh); |
| +verified: |
| ext4_unlock_group(sb, block_group); |
| return 0; |
| } |
| --- a/fs/ext4/ialloc.c |
| +++ b/fs/ext4/ialloc.c |
| @@ -88,6 +88,8 @@ static int ext4_validate_inode_bitmap(st |
| return -EFSCORRUPTED; |
| |
| ext4_lock_group(sb, block_group); |
| + if (buffer_verified(bh)) |
| + goto verified; |
| blk = ext4_inode_bitmap(sb, desc); |
| if (!ext4_inode_bitmap_csum_verify(sb, block_group, desc, bh, |
| EXT4_INODES_PER_GROUP(sb) / 8)) { |
| @@ -105,6 +107,7 @@ static int ext4_validate_inode_bitmap(st |
| return -EFSBADCRC; |
| } |
| set_buffer_verified(bh); |
| +verified: |
| ext4_unlock_group(sb, block_group); |
| return 0; |
| } |