On Fri, 2020-02-28 at 12:22 +0300, Dan Carpenter wrote: > If sbi->s_flex_groups_allocated is zero and the first allocation > fails > then this code will crash. The problem is that "i--" will set "i" to > -1 but when we compare "i >= sbi->s_flex_groups_allocated" then the > -1 > is type promoted to unsigned and becomes UINT_MAX. Since UINT_MAX > is more than zero, the condition is true so we call > kvfree(new_groups[-1]). > The loop will carry on freeing invalid memory until it crashes. > > Fixes: 7c990728b99e ("ext4: fix potential race between s_flex_groups > online resizing and access") > Signed-off-by: Dan Carpenter <dan.carpenter@xxxxxxxxxx> Reviewed-by: Suraj Jitindar Singh <surajjs@xxxxxxxxxx> Cc: <stable@xxxxxxxxxx> > --- > I changed this from a -- loop to a ++ loop because I knew it would > make > Walter Harms happy. He hates -- loops and I don't when his birthday > so > I'm celebrating it today. :) > > fs/ext4/super.c | 6 +++--- > 1 file changed, 3 insertions(+), 3 deletions(-) > > diff --git a/fs/ext4/super.c b/fs/ext4/super.c > index ff1b764b0c0e..0c7c4adb664e 100644 > --- a/fs/ext4/super.c > +++ b/fs/ext4/super.c > @@ -2391,7 +2391,7 @@ int ext4_alloc_flex_bg_array(struct super_block > *sb, ext4_group_t ngroup) > { > struct ext4_sb_info *sbi = EXT4_SB(sb); > struct flex_groups **old_groups, **new_groups; > - int size, i; > + int size, i, j; > > if (!sbi->s_log_groups_per_flex) > return 0; > @@ -2412,8 +2412,8 @@ int ext4_alloc_flex_bg_array(struct super_block > *sb, ext4_group_t ngroup) > sizeof(struct flex_groups)), > GFP_KERNEL); > if (!new_groups[i]) { > - for (i--; i >= sbi->s_flex_groups_allocated; i- > -) > - kvfree(new_groups[i]); > + for (j = sbi->s_flex_groups_allocated; j < i; > j++) > + kvfree(new_groups[j]); > kvfree(new_groups); > ext4_msg(sb, KERN_ERR, > "not enough memory for %d flex > groups", size);