summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2018-06-14 00:58:00 -0400
committerTheodore Ts'o <tytso@mit.edu>2018-06-14 00:58:00 -0400
commit8844618d8aa7a9973e7b527d038a2a589665002c (patch)
tree73e3eeb52d03d548d6cab2c600984f07a72b9e10 /fs
parent77260807d1170a8cf35dbb06e07461a655f67eee (diff)
ext4: only look at the bg_flags field if it is valid
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> Cc: stable@kernel.org
Diffstat (limited to 'fs')
-rw-r--r--fs/ext4/balloc.c11
-rw-r--r--fs/ext4/ialloc.c14
-rw-r--r--fs/ext4/mballoc.c6
-rw-r--r--fs/ext4/super.c11
4 files changed, 36 insertions, 6 deletions
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index 8a2e202ade8a..e68cefe08261 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -438,7 +438,16 @@ ext4_read_block_bitmap_nowait(struct super_block *sb, ext4_group_t block_group)
438 goto verify; 438 goto verify;
439 } 439 }
440 ext4_lock_group(sb, block_group); 440 ext4_lock_group(sb, block_group);
441 if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { 441 if (ext4_has_group_desc_csum(sb) &&
442 (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))) {
443 if (block_group == 0) {
444 ext4_unlock_group(sb, block_group);
445 unlock_buffer(bh);
446 ext4_error(sb, "Block bitmap for bg 0 marked "
447 "uninitialized");
448 err = -EFSCORRUPTED;
449 goto out;
450 }
442 err = ext4_init_block_bitmap(sb, bh, block_group, desc); 451 err = ext4_init_block_bitmap(sb, bh, block_group, desc);
443 set_bitmap_uptodate(bh); 452 set_bitmap_uptodate(bh);
444 set_buffer_uptodate(bh); 453 set_buffer_uptodate(bh);
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index 4d6e007f3569..da6c10c1e37a 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -150,7 +150,16 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group)
150 } 150 }
151 151
152 ext4_lock_group(sb, block_group); 152 ext4_lock_group(sb, block_group);
153 if (desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) { 153 if (ext4_has_group_desc_csum(sb) &&
154 (desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT))) {
155 if (block_group == 0) {
156 ext4_unlock_group(sb, block_group);
157 unlock_buffer(bh);
158 ext4_error(sb, "Inode bitmap for bg 0 marked "
159 "uninitialized");
160 err = -EFSCORRUPTED;
161 goto out;
162 }
154 memset(bh->b_data, 0, (EXT4_INODES_PER_GROUP(sb) + 7) / 8); 163 memset(bh->b_data, 0, (EXT4_INODES_PER_GROUP(sb) + 7) / 8);
155 ext4_mark_bitmap_end(EXT4_INODES_PER_GROUP(sb), 164 ext4_mark_bitmap_end(EXT4_INODES_PER_GROUP(sb),
156 sb->s_blocksize * 8, bh->b_data); 165 sb->s_blocksize * 8, bh->b_data);
@@ -994,7 +1003,8 @@ got:
994 1003
995 /* recheck and clear flag under lock if we still need to */ 1004 /* recheck and clear flag under lock if we still need to */
996 ext4_lock_group(sb, group); 1005 ext4_lock_group(sb, group);
997 if (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { 1006 if (ext4_has_group_desc_csum(sb) &&
1007 (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))) {
998 gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT); 1008 gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT);
999 ext4_free_group_clusters_set(sb, gdp, 1009 ext4_free_group_clusters_set(sb, gdp,
1000 ext4_free_clusters_after_init(sb, group, gdp)); 1010 ext4_free_clusters_after_init(sb, group, gdp));
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index 243c42fdc155..402c769c51ea 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -2444,7 +2444,8 @@ int ext4_mb_add_groupinfo(struct super_block *sb, ext4_group_t group,
2444 * initialize bb_free to be able to skip 2444 * initialize bb_free to be able to skip
2445 * empty groups without initialization 2445 * empty groups without initialization
2446 */ 2446 */
2447 if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { 2447 if (ext4_has_group_desc_csum(sb) &&
2448 (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))) {
2448 meta_group_info[i]->bb_free = 2449 meta_group_info[i]->bb_free =
2449 ext4_free_clusters_after_init(sb, group, desc); 2450 ext4_free_clusters_after_init(sb, group, desc);
2450 } else { 2451 } else {
@@ -3010,7 +3011,8 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
3010#endif 3011#endif
3011 ext4_set_bits(bitmap_bh->b_data, ac->ac_b_ex.fe_start, 3012 ext4_set_bits(bitmap_bh->b_data, ac->ac_b_ex.fe_start,
3012 ac->ac_b_ex.fe_len); 3013 ac->ac_b_ex.fe_len);
3013 if (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { 3014 if (ext4_has_group_desc_csum(sb) &&
3015 (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))) {
3014 gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT); 3016 gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT);
3015 ext4_free_group_clusters_set(sb, gdp, 3017 ext4_free_group_clusters_set(sb, gdp,
3016 ext4_free_clusters_after_init(sb, 3018 ext4_free_clusters_after_init(sb,
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index c61675d62195..4d34430d75f6 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -3139,13 +3139,22 @@ static ext4_group_t ext4_has_uninit_itable(struct super_block *sb)
3139 ext4_group_t group, ngroups = EXT4_SB(sb)->s_groups_count; 3139 ext4_group_t group, ngroups = EXT4_SB(sb)->s_groups_count;
3140 struct ext4_group_desc *gdp = NULL; 3140 struct ext4_group_desc *gdp = NULL;
3141 3141
3142 if (!ext4_has_group_desc_csum(sb))
3143 return ngroups;
3144
3142 for (group = 0; group < ngroups; group++) { 3145 for (group = 0; group < ngroups; group++) {
3143 gdp = ext4_get_group_desc(sb, group, NULL); 3146 gdp = ext4_get_group_desc(sb, group, NULL);
3144 if (!gdp) 3147 if (!gdp)
3145 continue; 3148 continue;
3146 3149
3147 if (!(gdp->bg_flags & cpu_to_le16(EXT4_BG_INODE_ZEROED))) 3150 if (gdp->bg_flags & cpu_to_le16(EXT4_BG_INODE_ZEROED))
3151 continue;
3152 if (group != 0)
3148 break; 3153 break;
3154 ext4_error(sb, "Inode table for bg 0 marked as "
3155 "needing zeroing");
3156 if (sb_rdonly(sb))
3157 return ngroups;
3149 } 3158 }
3150 3159
3151 return group; 3160 return group;