linux/fs
NeilBrown b7d2eee1f5 nfsd: fix RELEASE_LOCKOWNER
commit edcf972515 upstream.

The test on so_count in nfsd4_release_lockowner() is nonsense and
harmful.  Revert to using check_for_locks(), changing that to not sleep.

First: harmful.
As is documented in the kdoc comment for nfsd4_release_lockowner(), the
test on so_count can transiently return a false positive resulting in a
return of NFS4ERR_LOCKS_HELD when in fact no locks are held.  This is
clearly a protocol violation and with the Linux NFS client it can cause
incorrect behaviour.

If RELEASE_LOCKOWNER is sent while some other thread is still
processing a LOCK request which failed because, at the time that request
was received, the given owner held a conflicting lock, then the nfsd
thread processing that LOCK request can hold a reference (conflock) to
the lock owner that causes nfsd4_release_lockowner() to return an
incorrect error.

The Linux NFS client ignores that NFS4ERR_LOCKS_HELD error because it
never sends NFS4_RELEASE_LOCKOWNER without first releasing any locks, so
it knows that the error is impossible.  It assumes the lock owner was in
fact released so it feels free to use the same lock owner identifier in
some later locking request.

When it does reuse a lock owner identifier for which a previous RELEASE
failed, it will naturally use a lock_seqid of zero.  However the server,
which didn't release the lock owner, will expect a larger lock_seqid and
so will respond with NFS4ERR_BAD_SEQID.

So clearly it is harmful to allow a false positive, which testing
so_count allows.

The test is nonsense because ... well... it doesn't mean anything.

so_count is the sum of three different counts.
1/ the set of states listed on so_stateids
2/ the set of active vfs locks owned by any of those states
3/ various transient counts such as for conflicting locks.

When it is tested against '2' it is clear that one of these is the
transient reference obtained by find_lockowner_str_locked().  It is not
clear what the other one is expected to be.

In practice, the count is often 2 because there is precisely one state
on so_stateids.  If there were more, this would fail.

In my testing I see two circumstances when RELEASE_LOCKOWNER is called.
In one case, CLOSE is called before RELEASE_LOCKOWNER.  That results in
all the lock states being removed, and so the lockowner being discarded
(it is removed when there are no more references which usually happens
when the lock state is discarded).  When nfsd4_release_lockowner() finds
that the lock owner doesn't exist, it returns success.

The other case shows an so_count of '2' and precisely one state listed
in so_stateid.  It appears that the Linux client uses a separate lock
owner for each file resulting in one lock state per lock owner, so this
test on '2' is safe.  For another client it might not be safe.

So this patch changes check_for_locks() to use the (newish)
find_any_file_locked() so that it doesn't take a reference on the
nfs4_file and so never calls nfsd_file_put(), and so never sleeps.  With
this check is it safe to restore the use of check_for_locks() rather
than testing so_count against the mysterious '2'.

Fixes: ce3c4ad7f4 ("NFSD: Fix possible sleep during nfsd4_release_lockowner()")
Signed-off-by: NeilBrown <neilb@suse.de>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Cc: stable@vger.kernel.org # v6.2+
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2024-01-31 16:19:06 -08:00
..
9p 9p: v9fs_listxattr: fix %s null argument warning 2023-11-28 17:19:46 +00:00
adfs for-6.6/block-2023-08-28 2023-08-29 20:21:42 -07:00
affs for-6.6/block-2023-08-28 2023-08-29 20:21:42 -07:00
afs afs: Hide silly-rename files from userspace 2024-01-31 16:19:01 -08:00
autofs
befs for-6.6/block-2023-08-28 2023-08-29 20:21:42 -07:00
bfs for-6.6/block-2023-08-28 2023-08-29 20:21:42 -07:00
btrfs btrfs: don't abort filesystem when attempting to snapshot deleted subvolume 2024-01-31 16:19:06 -08:00
cachefiles - Some swap cleanups from Ma Wupeng ("fix WARN_ON in add_to_avail_list") 2023-08-29 14:25:26 -07:00
ceph ceph: select FS_ENCRYPTION_ALGS if FS_ENCRYPTION 2024-01-25 15:35:44 -08:00
coda
configfs
cramfs
crypto
debugfs debugfs: fix automount d_fsdata usage 2024-01-20 11:51:37 +01:00
devpts
dlm dlm: use kernel_connect() and kernel_bind() 2024-01-31 16:18:54 -08:00
ecryptfs fs: Pass AT_GETATTR_NOSEC flag to getattr interface function 2023-12-03 07:33:03 +01:00
efivarfs efivarfs: Free s_fs_info on unmount 2024-01-25 15:35:15 -08:00
efs for-6.6/block-2023-08-28 2023-08-29 20:21:42 -07:00
erofs erofs: fix lz4 inplace decompression 2024-01-31 16:18:49 -08:00
exfat exfat: support handle zero-size directory 2023-11-28 17:19:44 +00:00
exportfs exportfs: remove kernel-doc warnings in exportfs 2023-08-29 17:45:22 -04:00
ext2 ext2: Fix ki_pos update for DIO buffered-io fallback case 2023-12-08 08:52:19 +01:00
ext4 ext4: allow for the last group to be marked as trimmed 2024-01-31 16:18:49 -08:00
f2fs f2fs: fix to check return value of f2fs_recover_xattr_data 2024-01-25 15:35:37 -08:00
fat for-6.6/block-2023-08-28 2023-08-29 20:21:42 -07:00
freevxfs for-6.6/block-2023-08-28 2023-08-29 20:21:42 -07:00
fscache netfs, fscache: Prevent Oops in fscache_put_cache() 2024-01-31 16:19:01 -08:00
fuse fuse: dax: set fc->dax to NULL in fuse_dax_conn_free() 2023-12-20 17:01:52 +01:00
gfs2 gfs2: fix kernel BUG in gfs2_quota_cleanup 2024-01-25 15:35:17 -08:00
hfs for-6.6/block-2023-08-28 2023-08-29 20:21:42 -07:00
hfsplus for-6.6/block-2023-08-28 2023-08-29 20:21:42 -07:00
hostfs
hpfs for-6.6/block-2023-08-28 2023-08-29 20:21:42 -07:00
hugetlbfs fs: use nth_page() in place of direct struct page manipulation 2023-11-28 17:20:05 +00:00
iomap iomap: fix short copy in iomap_write_iter() 2023-10-19 09:41:36 -07:00
isofs for-6.6/block-2023-08-28 2023-08-29 20:21:42 -07:00
jbd2 jbd2: fix soft lockup in journal_finish_inode_data_buffers() 2024-01-20 11:51:43 +01:00
jffs2
jfs jfs: fix array-index-out-of-bounds in diAlloc 2023-11-28 17:19:43 +00:00
kernfs Revert "kernfs: convert kernfs_idr_lock to an irq safe raw spinlock" 2024-01-25 15:35:41 -08:00
lockd SUNRPC: Add enum svc_auth_status 2023-08-29 17:45:22 -04:00
minix for-6.6/block-2023-08-28 2023-08-29 20:21:42 -07:00
netfs netfs: Only call folio_start_fscache() one time for each folio 2023-09-18 12:03:46 -07:00
nfs pNFS: Fix the pnfs block driver's calculation of layoutget size 2024-01-25 15:35:18 -08:00
nfs_common
nfsd nfsd: fix RELEASE_LOCKOWNER 2024-01-31 16:19:06 -08:00
nilfs2 nilfs2: prevent WARNING in nilfs_sufile_set_segment_usage() 2023-12-13 18:45:22 +01:00
nls nls: Hide new NLS_UCS2_UTILS 2023-08-31 12:07:34 -05:00
notify fanotify: limit reporting of event with non-decodeable file handles 2023-10-19 16:19:20 +02:00
ntfs for-6.6/block-2023-08-28 2023-08-29 20:21:42 -07:00
ntfs3 driver ntfs3 for linux 6.6 2023-10-19 09:10:18 -07:00
ocfs2 Many ext4 and jbd2 cleanups and bug fixes for v6.6-rc1. 2023-08-31 15:18:15 -07:00
omfs for-6.6/block-2023-08-28 2023-08-29 20:21:42 -07:00
openpromfs
orangefs
overlayfs fs: Pass AT_GETATTR_NOSEC flag to getattr interface function 2023-12-03 07:33:03 +01:00
proc watchdog: move softlockup_panic back to early_param 2023-11-28 17:19:57 +00:00
pstore pstore: ram_core: fix possible overflow in persistent_ram_init_ecc() 2024-01-25 15:35:17 -08:00
qnx4 for-6.6/block-2023-08-28 2023-08-29 20:21:42 -07:00
qnx6 for-6.6/block-2023-08-28 2023-08-29 20:21:42 -07:00
quota quota: explicitly forbid quota files from being encrypted 2023-11-28 17:20:04 +00:00
ramfs
reiserfs reiserfs: Replace 1-element array with C99 style flex-array 2023-09-11 14:07:46 +02:00
romfs for-6.6/block-2023-08-28 2023-08-29 20:21:42 -07:00
smb cifs: after disabling multichannel, mark tcon for reconnect 2024-01-31 16:19:00 -08:00
squashfs
sysfs
sysv for-6.6/block-2023-08-28 2023-08-29 20:21:42 -07:00
tracefs eventfs: Do not allow NULL parent to eventfs_start_creating() 2023-12-20 17:02:00 +01:00
ubifs ubifs: ubifs_symlink: Fix memleak of inode->i_link in error path 2024-01-31 16:18:56 -08:00
udf \n 2023-08-30 12:10:50 -07:00
ufs for-6.6/block-2023-08-28 2023-08-29 20:21:42 -07:00
unicode
vboxsf
verity
xfs xfs: recovery should not clear di_flushiter unconditionally 2023-11-28 17:20:09 +00:00
zonefs
aio.c aio: Annotate struct kioctx_table with __counted_by 2023-09-20 14:22:01 +02:00
anon_inodes.c
attr.c
bad_inode.c
binfmt_elf_fdpic.c fs: binfmt_elf_efpic: fix personality for ELF-FDPIC 2023-09-29 17:20:45 -07:00
binfmt_elf_test.c
binfmt_elf.c
binfmt_flat.c
binfmt_misc.c
binfmt_script.c
buffer.c iomap: add a workaround for racy i_size updates on block devices 2023-09-25 08:55:00 -07:00
char_dev.c
compat_binfmt_elf.c
coredump.c
d_path.c
dax.c mm: convert DAX lock/unlock page to lock/unlock folio 2024-01-10 17:16:53 +01:00
dcache.c
direct-io.c
drop_caches.c
eventfd.c
eventpoll.c
exec.c exec: Fix error handling in begin_new_exec() 2024-01-31 16:19:06 -08:00
fcntl.c
fhandle.c
file_table.c
file.c
filesystems.c
fs_context.c fs: factor out vfs_parse_monolithic_sep() helper 2023-10-12 18:53:36 +03:00
fs_parser.c
fs_pin.c
fs_struct.c
fs_types.c
fs-writeback.c writeback, cgroup: switch inodes with dirty timestamps to release dying cgwbs 2023-11-20 11:58:52 +01:00
fsopen.c
init.c
inode.c filemap: add a per-mapping stable writes flag 2023-12-03 07:33:03 +01:00
internal.h for-6.6/block-2023-08-28 2023-08-29 20:21:42 -07:00
ioctl.c lsm: new security_file_ioctl_compat() hook 2024-01-31 16:18:54 -08:00
Kconfig for-6.6/block-2023-08-28 2023-08-29 20:21:42 -07:00
Kconfig.binfmt
kernel_read_file.c
libfs.c fs: new accessor methods for atime and mtime 2024-01-05 15:19:40 +01:00
locks.c NFSD 6.6 Release Notes 2023-08-31 15:32:18 -07:00
Makefile
mbcache.c
mnt_idmapping.c
mount.h
mpage.c
namei.c rename(): fix the locking of subdirectories 2024-01-31 16:18:57 -08:00
namespace.c fs: indicate request originates from old mount API 2024-01-25 15:35:17 -08:00
nsfs.c
open.c cred: get rid of CONFIG_DEBUG_CREDENTIALS 2023-12-20 17:01:51 +01:00
pipe.c fs/pipe: remove duplicate "offset" initializer 2023-09-20 14:22:01 +02:00
pnode.c
pnode.h
posix_acl.c
proc_namespace.c
read_write.c
readdir.c
remap_range.c
select.c
seq_file.c
signalfd.c
splice.c - Some swap cleanups from Ma Wupeng ("fix WARN_ON in add_to_avail_list") 2023-08-29 14:25:26 -07:00
stack.c
stat.c fs: Pass AT_GETATTR_NOSEC flag to getattr interface function 2023-12-03 07:33:03 +01:00
statfs.c
super.c fs: export sget_dev() 2023-08-31 12:47:15 +02:00
sync.c
sysctls.c
timerfd.c
userfaultfd.c
utimes.c
xattr.c