summaryrefslogtreecommitdiff
path: root/fs/ext4/resize.c
diff options
context:
space:
mode:
authorSuraj Jitindar Singh <surajjs@amazon.com>2020-02-29 03:48:17 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-03-11 20:02:43 +0300
commit4d830e847378b37294652da7dd4746019991f37a (patch)
tree55f82f8425c456ad848f8b0ef346dd9759ef8b8a /fs/ext4/resize.c
parent2afeb56881da66c09e8d2b5f6965eabeb75ce834 (diff)
downloadlinux-4d830e847378b37294652da7dd4746019991f37a.tar.xz
ext4: fix potential race between s_flex_groups online resizing and access
commit 7c990728b99ed6fbe9c75fc202fce1172d9916da upstream. During an online resize an array of s_flex_groups structures gets replaced so it can get enlarged. If there is a concurrent access to the array and this memory has been reused then this can lead to an invalid memory access. The s_flex_group array has been converted into an array of pointers rather than an array of structures. This is to ensure that the information contained in the structures cannot get out of sync during a resize due to an accessor updating the value in the old structure after it has been copied but before the array pointer is updated. Since the structures them- selves are no longer copied but only the pointers to them this case is mitigated. Link: https://bugzilla.kernel.org/show_bug.cgi?id=206443 Link: https://lore.kernel.org/r/20200221053458.730016-4-tytso@mit.edu Signed-off-by: Suraj Jitindar Singh <surajjs@amazon.com> Signed-off-by: Theodore Ts'o <tytso@mit.edu> Cc: stable@kernel.org # 4.14.x Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'fs/ext4/resize.c')
-rw-r--r--fs/ext4/resize.c7
1 files changed, 5 insertions, 2 deletions
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
index 16e3830da548..d42f7471fd5b 100644
--- a/fs/ext4/resize.c
+++ b/fs/ext4/resize.c
@@ -1425,11 +1425,14 @@ static void ext4_update_super(struct super_block *sb,
percpu_counter_read(&sbi->s_freeclusters_counter));
if (ext4_has_feature_flex_bg(sb) && sbi->s_log_groups_per_flex) {
ext4_group_t flex_group;
+ struct flex_groups *fg;
+
flex_group = ext4_flex_group(sbi, group_data[0].group);
+ fg = sbi_array_rcu_deref(sbi, s_flex_groups, flex_group);
atomic64_add(EXT4_NUM_B2C(sbi, free_blocks),
- &sbi->s_flex_groups[flex_group].free_clusters);
+ &fg->free_clusters);
atomic_add(EXT4_INODES_PER_GROUP(sb) * flex_gd->count,
- &sbi->s_flex_groups[flex_group].free_inodes);
+ &fg->free_inodes);
}
/*