linux/fs/nfsd
Lizhi Xu cad3f4a22c inotify: Fix possible deadlock in fsnotify_destroy_mark
[Syzbot reported]
WARNING: possible circular locking dependency detected
6.11.0-rc4-syzkaller-00019-gb311c1b497e5 #0 Not tainted
------------------------------------------------------
kswapd0/78 is trying to acquire lock:
ffff88801b8d8930 (&group->mark_mutex){+.+.}-{3:3}, at: fsnotify_group_lock include/linux/fsnotify_backend.h:270 [inline]
ffff88801b8d8930 (&group->mark_mutex){+.+.}-{3:3}, at: fsnotify_destroy_mark+0x38/0x3c0 fs/notify/mark.c:578

but task is already holding lock:
ffffffff8ea2fd60 (fs_reclaim){+.+.}-{0:0}, at: balance_pgdat mm/vmscan.c:6841 [inline]
ffffffff8ea2fd60 (fs_reclaim){+.+.}-{0:0}, at: kswapd+0xbb4/0x35a0 mm/vmscan.c:7223

which lock already depends on the new lock.

the existing dependency chain (in reverse order) is:

-> #1 (fs_reclaim){+.+.}-{0:0}:
       ...
       kmem_cache_alloc_noprof+0x3d/0x2a0 mm/slub.c:4044
       inotify_new_watch fs/notify/inotify/inotify_user.c:599 [inline]
       inotify_update_watch fs/notify/inotify/inotify_user.c:647 [inline]
       __do_sys_inotify_add_watch fs/notify/inotify/inotify_user.c:786 [inline]
       __se_sys_inotify_add_watch+0x72e/0x1070 fs/notify/inotify/inotify_user.c:729
       do_syscall_x64 arch/x86/entry/common.c:52 [inline]
       do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83
       entry_SYSCALL_64_after_hwframe+0x77/0x7f

-> #0 (&group->mark_mutex){+.+.}-{3:3}:
       ...
       __mutex_lock+0x136/0xd70 kernel/locking/mutex.c:752
       fsnotify_group_lock include/linux/fsnotify_backend.h:270 [inline]
       fsnotify_destroy_mark+0x38/0x3c0 fs/notify/mark.c:578
       fsnotify_destroy_marks+0x14a/0x660 fs/notify/mark.c:934
       fsnotify_inoderemove include/linux/fsnotify.h:264 [inline]
       dentry_unlink_inode+0x2e0/0x430 fs/dcache.c:403
       __dentry_kill+0x20d/0x630 fs/dcache.c:610
       shrink_kill+0xa9/0x2c0 fs/dcache.c:1055
       shrink_dentry_list+0x2c0/0x5b0 fs/dcache.c:1082
       prune_dcache_sb+0x10f/0x180 fs/dcache.c:1163
       super_cache_scan+0x34f/0x4b0 fs/super.c:221
       do_shrink_slab+0x701/0x1160 mm/shrinker.c:435
       shrink_slab+0x1093/0x14d0 mm/shrinker.c:662
       shrink_one+0x43b/0x850 mm/vmscan.c:4815
       shrink_many mm/vmscan.c:4876 [inline]
       lru_gen_shrink_node mm/vmscan.c:4954 [inline]
       shrink_node+0x3799/0x3de0 mm/vmscan.c:5934
       kswapd_shrink_node mm/vmscan.c:6762 [inline]
       balance_pgdat mm/vmscan.c:6954 [inline]
       kswapd+0x1bcd/0x35a0 mm/vmscan.c:7223

[Analysis]
The problem is that inotify_new_watch() is using GFP_KERNEL to allocate
new watches under group->mark_mutex, however if dentry reclaim races
with unlinking of an inode, it can end up dropping the last dentry reference
for an unlinked inode resulting in removal of fsnotify mark from reclaim
context which wants to acquire group->mark_mutex as well.

This scenario shows that all notification groups are in principle prone
to this kind of a deadlock (previously, we considered only fanotify and
dnotify to be problematic for other reasons) so make sure all
allocations under group->mark_mutex happen with GFP_NOFS.

Reported-and-tested-by: syzbot+c679f13773f295d2da53@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=c679f13773f295d2da53
Signed-off-by: Lizhi Xu <lizhi.xu@windriver.com>
Reviewed-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Jan Kara <jack@suse.cz>
Link: https://patch.msgid.link/20240927143642.2369508-1-lizhi.xu@windriver.com
2024-10-02 15:14:29 +02:00
..
acl.h NFSD: add posix ACLs to struct nfsd_attrs 2022-08-04 10:28:03 -04:00
auth.c nfsd: Pass 'cred' instead of 'rqstp' to some functions. 2024-09-20 19:31:03 -04:00
auth.h nfsd: Pass 'cred' instead of 'rqstp' to some functions. 2024-09-20 19:31:03 -04:00
blocklayout.c NFSD: Annotate struct pnfs_block_deviceaddr with __counted_by() 2024-09-20 19:31:03 -04:00
blocklayoutxdr.c NFSD: Make @gdev parameter of ->encode_getdeviceinfo a const pointer 2023-10-16 12:44:29 -04:00
blocklayoutxdr.h NFSD: Annotate struct pnfs_block_deviceaddr with __counted_by() 2024-09-20 19:31:03 -04:00
cache.h nfsd: don't allocate the versions array. 2024-09-20 19:29:23 -04:00
current_stateid.h
export.c NFSD: Handle @rqstp == NULL in check_nfsd_access() 2024-09-23 15:03:29 -04:00
export.h nfsd: Pass 'cred' instead of 'rqstp' to some functions. 2024-09-20 19:31:03 -04:00
filecache.c inotify: Fix possible deadlock in fsnotify_destroy_mark 2024-10-02 15:14:29 +02:00
filecache.h nfs_common: prepare for the NFS client to use nfsd_file for LOCALIO 2024-09-23 15:03:30 -04:00
flexfilelayout.c nfsd: move nfserrno() to vfs.c 2022-11-28 12:54:44 -05:00
flexfilelayoutxdr.c NFSD: Make @gdev parameter of ->encode_getdeviceinfo a const pointer 2023-10-16 12:44:29 -04:00
flexfilelayoutxdr.h NFSD: Make @gdev parameter of ->encode_getdeviceinfo a const pointer 2023-10-16 12:44:29 -04:00
idmap.h
Kconfig nfs_common: factor out nfs_errtbl and nfs_stat_to_errno 2024-09-23 15:03:29 -04:00
localio.c nfsd: implement server support for NFS_LOCALIO_PROGRAM 2024-09-23 15:03:30 -04:00
lockd.c
Makefile nfsd: add LOCALIO support 2024-09-23 15:03:30 -04:00
netlink.c nfsd: new netlink ops to get/set server pool_mode 2024-07-08 14:10:05 -04:00
netlink.h nfsd: new netlink ops to get/set server pool_mode 2024-07-08 14:10:05 -04:00
netns.h nfsd: add LOCALIO support 2024-09-23 15:03:30 -04:00
nfs2acl.c NFSD: remove unused structs 'nfsd3_voidargs' 2024-07-08 14:10:01 -04:00
nfs3acl.c NFSD: remove unused structs 'nfsd3_voidargs' 2024-07-08 14:10:01 -04:00
nfs3proc.c nfsd: move error choice for incorrect object types to version-specific code. 2024-09-20 19:31:03 -04:00
nfs3xdr.c nfsd: Fix NFSv3 atomicity bugs in nfsd_setattr() 2024-03-01 09:12:33 -05:00
nfs4acl.c nfsd: inherit required unset default acls from effective set 2023-08-29 17:45:22 -04:00
nfs4callback.c nfsd: add more nfsd_cb tracepoints 2024-09-20 19:31:03 -04:00
nfs4idmap.c nfsd: call cache_put if xdr_reserve_space returns NULL 2024-09-20 19:31:03 -04:00
nfs4layouts.c nfsd: track the main opcode for callbacks 2024-09-20 19:31:03 -04:00
nfs4proc.c NFSD: Wrap async copy operations with trace points 2024-09-20 19:31:03 -04:00
nfs4recover.c nfsd: enforce upper limit for namelen in __cld_pipe_inprogress_downcall() 2024-09-20 19:31:35 -04:00
nfs4state.c nfsd: fix delegation_blocked() to block correctly for at least 30 seconds 2024-09-20 19:31:38 -04:00
nfs4xdr.c NFSD: Fix NFSv4's PUTPUBFH operation 2024-09-20 19:31:03 -04:00
nfscache.c nfsd: Simplify the allocation of slab caches in nfsd_drc_slab_create 2024-03-01 09:12:24 -05:00
nfsctl.c nfsd: add LOCALIO support 2024-09-23 15:03:30 -04:00
nfsd.h nfsd: implement server support for NFS_LOCALIO_PROGRAM 2024-09-23 15:03:30 -04:00
nfsfh.c nfsd: add nfsd_file_acquire_local() 2024-09-23 15:03:30 -04:00
nfsfh.h nfsd: add nfsd_file_acquire_local() 2024-09-23 15:03:30 -04:00
nfsproc.c nfsd: move error choice for incorrect object types to version-specific code. 2024-09-20 19:31:03 -04:00
nfssvc.c nfsd: implement server support for NFS_LOCALIO_PROGRAM 2024-09-23 15:03:30 -04:00
nfsxdr.c NFSD: Ensure that xdr_write_pages updates rq_next_page 2023-06-05 09:01:44 -04:00
pnfs.h nfsd: allow layout state to be admin-revoked. 2024-03-01 09:12:22 -05:00
state.h nfsd: track the main opcode for callbacks 2024-09-20 19:31:03 -04:00
stats.c fs: nfsd: use group allocation/free of per-cpu counters API 2024-05-06 09:07:17 -04:00
stats.h fs: nfsd: use group allocation/free of per-cpu counters API 2024-05-06 09:07:17 -04:00
trace.c
trace.h nfsd: add LOCALIO support 2024-09-23 15:03:30 -04:00
vfs.c nfsd: map the EBADMSG to nfserr_io to avoid warning 2024-09-20 19:31:03 -04:00
vfs.h nfsd: add LOCALIO support 2024-09-23 15:03:30 -04:00
xdr3.h nfsd: Fix NFSv3 atomicity bugs in nfsd_setattr() 2024-03-01 09:12:33 -05:00
xdr4.h NFSD: Limit the number of concurrent async COPY operations 2024-09-20 19:31:03 -04:00
xdr4cb.h NFSD: add support for CB_GETATTR callback 2024-03-01 09:12:31 -05:00
xdr.h NFSD: prevent underflow in nfssvc_decode_writeargs() 2022-03-15 09:35:56 -04:00