summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2018-07-12 19:08:05 -0400
committerTheodore Ts'o <tytso@mit.edu>2018-07-12 19:08:05 -0400
commit8d5a803c6a6ce4ec258e31f76059ea5153ba46ef (patch)
tree1efe5596c31c67ad7a80006b6930ebe66373ed31
parent362eca70b53389bddf3143fe20f53dcce2cfdf61 (diff)
ext4: check for allocation block validity with block group locked
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
-rw-r--r--fs/ext4/balloc.c3
-rw-r--r--fs/ext4/ialloc.c3
2 files changed, 6 insertions, 0 deletions
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index e68cefe08261..aa52d87985aa 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -368,6 +368,8 @@ static int ext4_validate_block_bitmap(struct super_block *sb,
368 return -EFSCORRUPTED; 368 return -EFSCORRUPTED;
369 369
370 ext4_lock_group(sb, block_group); 370 ext4_lock_group(sb, block_group);
371 if (buffer_verified(bh))
372 goto verified;
371 if (unlikely(!ext4_block_bitmap_csum_verify(sb, block_group, 373 if (unlikely(!ext4_block_bitmap_csum_verify(sb, block_group,
372 desc, bh))) { 374 desc, bh))) {
373 ext4_unlock_group(sb, block_group); 375 ext4_unlock_group(sb, block_group);
@@ -386,6 +388,7 @@ static int ext4_validate_block_bitmap(struct super_block *sb,
386 return -EFSCORRUPTED; 388 return -EFSCORRUPTED;
387 } 389 }
388 set_buffer_verified(bh); 390 set_buffer_verified(bh);
391verified:
389 ext4_unlock_group(sb, block_group); 392 ext4_unlock_group(sb, block_group);
390 return 0; 393 return 0;
391} 394}
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index fb83750c1a14..e9d8e2667ab5 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -90,6 +90,8 @@ static int ext4_validate_inode_bitmap(struct super_block *sb,
90 return -EFSCORRUPTED; 90 return -EFSCORRUPTED;
91 91
92 ext4_lock_group(sb, block_group); 92 ext4_lock_group(sb, block_group);
93 if (buffer_verified(bh))
94 goto verified;
93 blk = ext4_inode_bitmap(sb, desc); 95 blk = ext4_inode_bitmap(sb, desc);
94 if (!ext4_inode_bitmap_csum_verify(sb, block_group, desc, bh, 96 if (!ext4_inode_bitmap_csum_verify(sb, block_group, desc, bh,
95 EXT4_INODES_PER_GROUP(sb) / 8)) { 97 EXT4_INODES_PER_GROUP(sb) / 8)) {
@@ -101,6 +103,7 @@ static int ext4_validate_inode_bitmap(struct super_block *sb,
101 return -EFSBADCRC; 103 return -EFSBADCRC;
102 } 104 }
103 set_buffer_verified(bh); 105 set_buffer_verified(bh);
106verified:
104 ext4_unlock_group(sb, block_group); 107 ext4_unlock_group(sb, block_group);
105 return 0; 108 return 0;
106} 109}