It's possible for nfs_closedir() to be called without filp->private_data ever having been set. This causes a crash when put_nfs_open_dir_context() calls list_del on filp->private_data->list. I have a test program that provokes this crash (with a misbehaving NFS server). Here's my partial understanding of what happens: * A program tries to create a new file "x". * The NFS v4 server replies OK to the open RPC, but includes attributes with an invalid (huge) fattr4.type. * This causes decode_attr_type() to not set NFS_ATTR_FATTR_TYPE, so the type test in nfs4_open_done() isn't executed, which would ordinarily prevent all this from happening. * But the open mostly succeeds, and allocates an inode; _nfs4_proc_open() sends another getattr RPC to get the type &c. * The server replies to this second getattr with type=NF4DIR, and nfs_fhget() sets inode->i_fop = nfs_dir_operations. But i_fop.open=nfs_diropen won't be called because this inode is stale... * The NF4DIR causes nfs_finish_open() to return EOPENSTALE, which causes do_filp_open() to retry the open. * The NFS server replies to this open with attribute type=NF4REG. * nfs_find_actor() allocates a new struct inode, since the type is different. * Meanwhile, path_openat() had called fput(file) for the original stale open, which causes a background task eventually to call ___fput, which makes the nfs_closedir() call that crashes. One way to view this is that inode->i_fop gets out of sync with file->private_data. I've attached my test program: # cc nfs_7.c # ./a.out ... [ 26.691442] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000 [ 26.704718] Oops [#1] [ 26.709193] Modules linked in: [ 26.715724] CPU: 0 PID: 73 Comm: sh Not tainted 5.15.0-rc7-dirty #20 [ 26.725572] Hardware name: ucbbar,riscvemu-bare (DT) [ 26.733242] epc : __list_del_entry_valid+0x8/0xa0 [ 26.741500] ra : nfs_closedir+0x28/0x5c [ 26.748036] epc : ffffffff802ed742 ra : ffffffff80206bea sp : ffffffd00059bd60 ... [ 26.866512] status: 0000000200000121 badaddr: 0000000000000000 cause: 000000000000000d [ 26.877462] [<ffffffff802ed742>] __list_del_entry_valid+0x8/0xa0 [ 26.887319] [<ffffffff80206bea>] nfs_closedir+0x28/0x5c [ 26.895619] [<ffffffff8012b4c6>] __fput+0x78/0x1c6 [ 26.903952] [<ffffffff8012b67c>] ____fput+0xc/0x14 [ 26.912274] [<ffffffff8002344c>] task_work_run+0x68/0xa4 [ 26.920516] [<ffffffff80003df0>] do_notify_resume+0x74/0x356 [ 26.930376] [<ffffffff80003054>] ret_from_exception+0x0/0xc
Attachment:
nfs_7.c
Description: Binary data