Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ext4: don't clear SB_RDONLY when remounting r/w until quota is re-enabled

When a file system currently mounted read/only is remounted
read/write, if we clear the SB_RDONLY flag too early, before the quota
is initialized, and there is another process/thread constantly
attempting to create a directory, it's possible to trigger the

WARN_ON_ONCE(dquot_initialize_needed(inode));

in ext4_xattr_block_set(), with the following stack trace:

WARNING: CPU: 0 PID: 5338 at fs/ext4/xattr.c:2141 ext4_xattr_block_set+0x2ef2/0x3680
RIP: 0010:ext4_xattr_block_set+0x2ef2/0x3680 fs/ext4/xattr.c:2141
Call Trace:
ext4_xattr_set_handle+0xcd4/0x15c0 fs/ext4/xattr.c:2458
ext4_initxattrs+0xa3/0x110 fs/ext4/xattr_security.c:44
security_inode_init_security+0x2df/0x3f0 security/security.c:1147
__ext4_new_inode+0x347e/0x43d0 fs/ext4/ialloc.c:1324
ext4_mkdir+0x425/0xce0 fs/ext4/namei.c:2992
vfs_mkdir+0x29d/0x450 fs/namei.c:4038
do_mkdirat+0x264/0x520 fs/namei.c:4061
__do_sys_mkdirat fs/namei.c:4076 [inline]
__se_sys_mkdirat fs/namei.c:4074 [inline]
__x64_sys_mkdirat+0x89/0xa0 fs/namei.c:4074

Cc: stable@kernel.org
Link: https://lore.kernel.org/r/20230506142419.984260-1-tytso@mit.edu
Reported-by: syzbot+6385d7d3065524c5ca6d@syzkaller.appspotmail.com
Link: https://syzkaller.appspot.com/bug?id=6513f6cb5cd6b5fc9f37e3bb70d273b94be9c34c
Signed-off-by: Theodore Ts'o <tytso@mit.edu>

+5 -1
+5 -1
fs/ext4/super.c
··· 6387 6387 struct ext4_mount_options old_opts; 6388 6388 ext4_group_t g; 6389 6389 int err = 0; 6390 + int enable_rw = 0; 6390 6391 #ifdef CONFIG_QUOTA 6391 6392 int enable_quota = 0; 6392 6393 int i, j; ··· 6574 6573 if (err) 6575 6574 goto restore_opts; 6576 6575 6577 - sb->s_flags &= ~SB_RDONLY; 6576 + enable_rw = 1; 6578 6577 if (ext4_has_feature_mmp(sb)) { 6579 6578 err = ext4_multi_mount_protect(sb, 6580 6579 le64_to_cpu(es->s_mmp_block)); ··· 6632 6631 #endif 6633 6632 if (!test_opt(sb, BLOCK_VALIDITY) && sbi->s_system_blks) 6634 6633 ext4_release_system_zone(sb); 6634 + 6635 + if (enable_rw) 6636 + sb->s_flags &= ~SB_RDONLY; 6635 6637 6636 6638 if (!ext4_has_feature_mmp(sb) || sb_rdonly(sb)) 6637 6639 ext4_stop_mmpd(sbi);