On 22/06/01 05:27PM, Zhang Yi wrote: > We capture a NULL pointer issue when resizing a corrupt ext4 image which > is freshly clear resize_inode feature (not run e2fsck). It could be > simply reproduced by following steps. The problem is because of the > resize_inode feature was cleared, and it will convert the filesystem to > meta_bg mode in ext4_resize_fs(), but the es->s_reserved_gdt_blocks was > not reduced to zero, so could we mistakenly call reserve_backup_gdb() > and passing an uninitialized resize_inode to it when adding new group > descriptors. > > mkfs.ext4 /dev/sda 3G > tune2fs -O ^resize_inode /dev/sda #forget to run requested e2fsck > mount /dev/sda /mnt > resize2fs /dev/sda 8G > > ======== > BUG: kernel NULL pointer dereference, address: 0000000000000028 > CPU: 19 PID: 3243 Comm: resize2fs Not tainted 5.18.0-rc7-00001-gfde086c5ebfd #748 > ... > RIP: 0010:ext4_flex_group_add+0xe08/0x2570 > ... > Call Trace: > <TASK> > ext4_resize_fs+0xbec/0x1660 > __ext4_ioctl+0x1749/0x24e0 > ext4_ioctl+0x12/0x20 > __x64_sys_ioctl+0xa6/0x110 > do_syscall_64+0x3b/0x90 > entry_SYSCALL_64_after_hwframe+0x44/0xae > RIP: 0033:0x7f2dd739617b > ======== > > The fix is simple, add a check in ext4_resize_begin() to make sure that > the es->s_reserved_gdt_blocks is zero when the resize_inode feature is > disabled. Sure, I have verified this change at my end too with your execerciser. And having this check this in ext4_resize_begin(), looks good to me. Feel free to add - Reviewed-by: Ritesh Harjani <ritesh.list@xxxxxxxxx> > > Signed-off-by: Zhang Yi <yi.zhang@xxxxxxxxxx> > --- > v2->v1: > - move check from ext4_resize_fs() to ext4_resize_begin(). > > fs/ext4/resize.c | 10 ++++++++++ > 1 file changed, 10 insertions(+) > > diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c > index 90a941d20dff..8b70a4701293 100644 > --- a/fs/ext4/resize.c > +++ b/fs/ext4/resize.c > @@ -53,6 +53,16 @@ int ext4_resize_begin(struct super_block *sb) > if (!capable(CAP_SYS_RESOURCE)) > return -EPERM; > > + /* > + * If the reserved GDT blocks is non-zero, the resize_inode feature > + * should always be set. > + */ > + if (EXT4_SB(sb)->s_es->s_reserved_gdt_blocks && > + !ext4_has_feature_resize_inode(sb)) { > + ext4_error(sb, "resize_inode disabled but reserved GDT blocks non-zero"); > + return -EFSCORRUPTED; > + } > + > /* > * If we are not using the primary superblock/GDT copy don't resize, > * because the user tools have no way of handling this. Probably a > -- > 2.31.1 >