126 lines
4.4 KiB
Diff
126 lines
4.4 KiB
Diff
From: Theodore Ts'o <tytso@mit.edu>
|
|
Date: Thu, 14 Jun 2018 00:58:00 -0400
|
|
Subject: ext4: only look at the bg_flags field if it is valid
|
|
Origin: https://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4.git/commit?id=32a82d31527ae9cb568f5d7fa5ad27b2860324ed
|
|
Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2018-10876
|
|
|
|
The bg_flags field in the block group descripts is only valid if the
|
|
uninit_bg or metadata_csum feature is enabled. We were not
|
|
consistently looking at this field; fix this.
|
|
|
|
Also block group #0 must never have uninitialized allocation bitmaps,
|
|
or need to be zeroed, since that's where the root inode, and other
|
|
special inodes are set up. Check for these conditions and mark the
|
|
file system as corrupted if they are detected.
|
|
|
|
This addresses CVE-2018-10876.
|
|
|
|
https://bugzilla.kernel.org/show_bug.cgi?id=199403
|
|
|
|
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
|
|
---
|
|
fs/ext4/balloc.c | 11 ++++++++++-
|
|
fs/ext4/ialloc.c | 14 ++++++++++++--
|
|
fs/ext4/mballoc.c | 6 ++++--
|
|
fs/ext4/super.c | 11 ++++++++++-
|
|
4 files changed, 36 insertions(+), 6 deletions(-)
|
|
|
|
--- a/fs/ext4/balloc.c
|
|
+++ b/fs/ext4/balloc.c
|
|
@@ -451,7 +451,16 @@ ext4_read_block_bitmap_nowait(struct sup
|
|
goto verify;
|
|
}
|
|
ext4_lock_group(sb, block_group);
|
|
- if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
|
|
+ if (ext4_has_group_desc_csum(sb) &&
|
|
+ (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))) {
|
|
+ if (block_group == 0) {
|
|
+ ext4_unlock_group(sb, block_group);
|
|
+ unlock_buffer(bh);
|
|
+ ext4_error(sb, "Block bitmap for bg 0 marked "
|
|
+ "uninitialized");
|
|
+ err = -EFSCORRUPTED;
|
|
+ goto out;
|
|
+ }
|
|
err = ext4_init_block_bitmap(sb, bh, block_group, desc);
|
|
set_bitmap_uptodate(bh);
|
|
set_buffer_uptodate(bh);
|
|
--- a/fs/ext4/ialloc.c
|
|
+++ b/fs/ext4/ialloc.c
|
|
@@ -155,7 +155,16 @@ ext4_read_inode_bitmap(struct super_bloc
|
|
}
|
|
|
|
ext4_lock_group(sb, block_group);
|
|
- if (desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) {
|
|
+ if (ext4_has_group_desc_csum(sb) &&
|
|
+ (desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT))) {
|
|
+ if (block_group == 0) {
|
|
+ ext4_unlock_group(sb, block_group);
|
|
+ unlock_buffer(bh);
|
|
+ ext4_error(sb, "Inode bitmap for bg 0 marked "
|
|
+ "uninitialized");
|
|
+ err = -EFSCORRUPTED;
|
|
+ goto out;
|
|
+ }
|
|
memset(bh->b_data, 0, (EXT4_INODES_PER_GROUP(sb) + 7) / 8);
|
|
ext4_mark_bitmap_end(EXT4_INODES_PER_GROUP(sb),
|
|
sb->s_blocksize * 8, bh->b_data);
|
|
@@ -1000,7 +1009,8 @@ got:
|
|
|
|
/* recheck and clear flag under lock if we still need to */
|
|
ext4_lock_group(sb, group);
|
|
- if (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
|
|
+ if (ext4_has_group_desc_csum(sb) &&
|
|
+ (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))) {
|
|
gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT);
|
|
ext4_free_group_clusters_set(sb, gdp,
|
|
ext4_free_clusters_after_init(sb, group, gdp));
|
|
--- a/fs/ext4/mballoc.c
|
|
+++ b/fs/ext4/mballoc.c
|
|
@@ -2444,7 +2444,8 @@ int ext4_mb_add_groupinfo(struct super_b
|
|
* initialize bb_free to be able to skip
|
|
* empty groups without initialization
|
|
*/
|
|
- if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
|
|
+ if (ext4_has_group_desc_csum(sb) &&
|
|
+ (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))) {
|
|
meta_group_info[i]->bb_free =
|
|
ext4_free_clusters_after_init(sb, group, desc);
|
|
} else {
|
|
@@ -3011,7 +3012,8 @@ ext4_mb_mark_diskspace_used(struct ext4_
|
|
#endif
|
|
ext4_set_bits(bitmap_bh->b_data, ac->ac_b_ex.fe_start,
|
|
ac->ac_b_ex.fe_len);
|
|
- if (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
|
|
+ if (ext4_has_group_desc_csum(sb) &&
|
|
+ (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))) {
|
|
gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT);
|
|
ext4_free_group_clusters_set(sb, gdp,
|
|
ext4_free_clusters_after_init(sb,
|
|
--- a/fs/ext4/super.c
|
|
+++ b/fs/ext4/super.c
|
|
@@ -3098,13 +3098,22 @@ static ext4_group_t ext4_has_uninit_itab
|
|
ext4_group_t group, ngroups = EXT4_SB(sb)->s_groups_count;
|
|
struct ext4_group_desc *gdp = NULL;
|
|
|
|
+ if (!ext4_has_group_desc_csum(sb))
|
|
+ return ngroups;
|
|
+
|
|
for (group = 0; group < ngroups; group++) {
|
|
gdp = ext4_get_group_desc(sb, group, NULL);
|
|
if (!gdp)
|
|
continue;
|
|
|
|
- if (!(gdp->bg_flags & cpu_to_le16(EXT4_BG_INODE_ZEROED)))
|
|
+ if (gdp->bg_flags & cpu_to_le16(EXT4_BG_INODE_ZEROED))
|
|
+ continue;
|
|
+ if (group != 0)
|
|
break;
|
|
+ ext4_error(sb, "Inode table for bg 0 marked as "
|
|
+ "needing zeroing");
|
|
+ if (sb_rdonly(sb))
|
|
+ return ngroups;
|
|
}
|
|
|
|
return group;
|