quota: Lock s_umount in exclusive mode for Q_XQUOTA{ON,OFF} quotactls.
[ Upstream commit
41c4f85cdac280d356df1f483000ecec4a8868be ]
Commit
1fa5efe3622db58cb8c7b9a50665e9eb9a6c7e97 (ext4: Use generic helpers for quotaon
and quotaoff) made possible to call quotactl(Q_XQUOTAON/OFF) on ext4 filesystems
with sysfile quota support. This leads to calling dquot_enable/disable without s_umount
held in excl. mode, because quotactl_cmd_onoff checks only for Q_QUOTAON/OFF.
The following WARN_ON_ONCE triggers (in this case for dquot_enable, ext4, latest Linus' tree):
[ 117.807056] EXT4-fs (dm-0): mounted filesystem with ordered data mode. Opts: quota,prjquota
[...]
[ 155.036847] WARNING: CPU: 0 PID: 2343 at fs/quota/dquot.c:2469 dquot_enable+0x34/0xb9
[ 155.036851] Modules linked in: quota_v2 quota_tree ipv6 af_packet joydev mousedev psmouse serio_raw pcspkr i2c_piix4 intel_agp intel_gtt e1000 ttm drm_kms_helper drm agpgart fb_sys_fops syscopyarea sysfillrect sysimgblt i2c_core input_leds kvm_intel kvm irqbypass qemu_fw_cfg floppy evdev parport_pc parport button crc32c_generic dm_mod ata_generic pata_acpi ata_piix libata loop ext4 crc16 mbcache jbd2 usb_storage usbcore sd_mod scsi_mod
[ 155.036901] CPU: 0 PID: 2343 Comm: qctl Not tainted 4.20.0-rc6-00025-gf5d582777bcb #9
[ 155.036903] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1ubuntu1 04/01/2014
[ 155.036911] RIP: 0010:dquot_enable+0x34/0xb9
[ 155.036915] Code: 41 56 41 55 41 54 55 53 4c 8b 6f 28 74 02 0f 0b 4d 8d 7d 70 49 89 fc 89 cb 41 89 d6 89 f5 4c 89 ff e8 23 09 ea ff 85 c0 74 0a <0f> 0b 4c 89 ff e8 8b 09 ea ff 85 db 74 6a 41 8b b5 f8 00 00 00 0f
[ 155.036918] RSP: 0018:
ffffb09b00493e08 EFLAGS:
00010202
[ 155.036922] RAX:
0000000000000001 RBX:
0000000000000008 RCX:
0000000000000008
[ 155.036924] RDX:
0000000000000001 RSI:
0000000000000002 RDI:
ffff9781b67cd870
[ 155.036926] RBP:
0000000000000002 R08:
0000000000000000 R09:
61c8864680b583eb
[ 155.036929] R10:
ffffb09b00493e48 R11:
ffffffffff7ce7d4 R12:
ffff9781b7ee8d78
[ 155.036932] R13:
ffff9781b67cd800 R14:
0000000000000004 R15:
ffff9781b67cd870
[ 155.036936] FS:
00007fd813250b88(0000) GS:
ffff9781ba000000(0000) knlGS:
0000000000000000
[ 155.036939] CS: 0010 DS: 0000 ES: 0000 CR0:
0000000080050033
[ 155.036942] CR2:
00007fd812ff61d6 CR3:
000000007c882000 CR4:
00000000000006b0
[ 155.036951] DR0:
0000000000000000 DR1:
0000000000000000 DR2:
0000000000000000
[ 155.036953] DR3:
0000000000000000 DR6:
00000000fffe0ff0 DR7:
0000000000000400
[ 155.036955] Call Trace:
[ 155.037004] dquot_quota_enable+0x8b/0xd0
[ 155.037011] kernel_quotactl+0x628/0x74e
[ 155.037027] ? do_mprotect_pkey+0x2a6/0x2cd
[ 155.037034] __x64_sys_quotactl+0x1a/0x1d
[ 155.037041] do_syscall_64+0x55/0xe4
[ 155.037078] entry_SYSCALL_64_after_hwframe+0x44/0xa9
[ 155.037105] RIP: 0033:0x7fd812fe1198
[ 155.037109] Code: 02 77 0d 48 89 c1 48 c1 e9 3f 75 04 48 8b 04 24 48 83 c4 50 5b c3 48 83 ec 08 49 89 ca 48 63 d2 48 63 ff b8 b3 00 00 00 0f 05 <48> 89 c7 e8 c1 eb ff ff 5a c3 48 63 ff b8 bb 00 00 00 0f 05 48 89
[ 155.037112] RSP: 002b:
00007ffe8cd7b050 EFLAGS:
00000206 ORIG_RAX:
00000000000000b3
[ 155.037116] RAX:
ffffffffffffffda RBX:
00007ffe8cd7b148 RCX:
00007fd812fe1198
[ 155.037119] RDX:
0000000000000000 RSI:
00007ffe8cd7cea9 RDI:
0000000000580102
[ 155.037121] RBP:
00007ffe8cd7b0f0 R08:
000055fc8eba8a9d R09:
0000000000000000
[ 155.037124] R10:
00007ffe8cd7b074 R11:
0000000000000206 R12:
00007ffe8cd7b168
[ 155.037126] R13:
000055fc8eba8897 R14:
0000000000000000 R15:
0000000000000000
[ 155.037131] ---[ end trace
210f864257175c51 ]---
and then the syscall proceeds without s_umount locking.
This patch locks the superblock ->s_umount sem. in exclusive mode for all Q_XQUOTAON/OFF
quotactls too in addition to Q_QUOTAON/OFF.
AFAICT, other than ext4, only xfs and ocfs2 are affected by this change.
The VFS will now call in xfs_quota_* functions with s_umount held, which wasn't the case
before. This looks good to me but I can not say for sure. Ext4 and ocfs2 where already
beeing called with s_umount exclusive via quota_quotaon/off which is basically the same.
Signed-off-by: Javier Barrio <javier.barrio.mart@gmail.com>
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Sasha Levin <sashal@kernel.org>