linux-yocto/fs/nfs
Max Kellermann 14f5549ad1 fs/nfs/read: fix double-unlock bug in nfs_return_empty_folio()
commit 4c10fa44bc upstream.

Sometimes, when a file was read while it was being truncated by
another NFS client, the kernel could deadlock because folio_unlock()
was called twice, and the second call would XOR back the `PG_locked`
flag.

Most of the time (depending on the timing of the truncation), nobody
notices the problem because folio_unlock() gets called three times,
which flips `PG_locked` back off:

 1. vfs_read, nfs_read_folio, ... nfs_read_add_folio,
    nfs_return_empty_folio
 2. vfs_read, nfs_read_folio, ... netfs_read_collection,
    netfs_unlock_abandoned_read_pages
 3. vfs_read, ... nfs_do_read_folio, nfs_read_add_folio,
    nfs_return_empty_folio

The problem is that nfs_read_add_folio() is not supposed to unlock the
folio if fscache is enabled, and a nfs_netfs_folio_unlock() check is
missing in nfs_return_empty_folio().

Rarely this leads to a warning in netfs_read_collection():

 ------------[ cut here ]------------
 R=0000031c: folio 10 is not locked
 WARNING: CPU: 0 PID: 29 at fs/netfs/read_collect.c:133 netfs_read_collection+0x7c0/0xf00
 [...]
 Workqueue: events_unbound netfs_read_collection_worker
 RIP: 0010:netfs_read_collection+0x7c0/0xf00
 [...]
 Call Trace:
  <TASK>
  netfs_read_collection_worker+0x67/0x80
  process_one_work+0x12e/0x2c0
  worker_thread+0x295/0x3a0

Most of the time, however, processes just get stuck forever in
folio_wait_bit_common(), waiting for `PG_locked` to disappear, which
never happens because nobody is really holding the folio lock.

Fixes: 000dbe0bec ("NFS: Convert buffered read paths to use netfs when fscache is enabled")
Cc: stable@vger.kernel.org
Signed-off-by: Max Kellermann <max.kellermann@ionos.com>
Reviewed-by: Dave Wysochanski <dwysocha@redhat.com>
Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2025-06-27 11:08:44 +01:00
..
blocklayout
filelayout nfs: don't share pNFS DS connections between net namespaces 2025-06-04 14:42:25 +02:00
flexfilelayout nfs: don't share pNFS DS connections between net namespaces 2025-06-04 14:42:25 +02:00
cache_lib.c
cache_lib.h
callback_proc.c
callback_xdr.c SUNRPC: Fix integer overflow in decode_rc_list() 2024-10-17 15:24:23 +02:00
callback.c nfsd: stop setting ->pg_stats for unused stats 2024-08-19 06:04:23 +02:00
callback.h
client.c NFS: Avoid flushing data while holding directory locks in nfs_rename() 2025-06-04 14:42:25 +02:00
delegation.c NFSv4: Check for delegation validity in nfs_start_delegation_return_locked() 2025-06-04 14:41:54 +02:00
delegation.h
dir.c NFS: Avoid flushing data while holding directory locks in nfs_rename() 2025-06-04 14:42:25 +02:00
direct.c NFS: O_DIRECT writes must check and adjust the file length 2025-03-13 12:58:21 +01:00
dns_resolve.c
dns_resolve.h
export.c
file.c NFS: fix nfs_release_folio() to not deadlock via kcompactd writeback 2025-03-13 12:58:27 +01:00
fs_context.c nfs: keep server info for remounts 2024-06-12 11:12:47 +02:00
fscache.c NFS: Fix nfs_netfs_issue_read() xarray locking for writeback interrupt 2024-03-26 18:20:03 -04:00
fscache.h
getroot.c
inode.c NFS: Don't allow waiting for exiting tasks 2025-06-04 14:41:54 +02:00
internal.h NFS: Don't allow waiting for exiting tasks 2025-06-04 14:41:54 +02:00
io.c
iostat.h
Kconfig nfs: add missing selections of CONFIG_CRC32 2025-04-25 10:45:46 +02:00
Makefile
mount_clnt.c
namespace.c
netns.h nfs: make the rpc_stat per net namespace 2024-05-17 12:01:57 +02:00
nfs.h
nfs2super.c
nfs2xdr.c
nfs3_fs.h
nfs3acl.c
nfs3client.c
nfs3proc.c NFS: Don't allow waiting for exiting tasks 2025-06-04 14:41:54 +02:00
nfs3super.c
nfs3xdr.c
nfs4_fs.h
nfs4client.c NFSv4.1 another fix for EXCHGID4_FLAG_USE_PNFS_DS for DS server 2024-08-03 08:53:54 +02:00
nfs4file.c
nfs4getroot.c
nfs4idmap.c
nfs4idmap.h
nfs4namespace.c
nfs4proc.c NFS: Don't allow waiting for exiting tasks 2025-06-04 14:41:54 +02:00
nfs4renewd.c
nfs4session.c
nfs4session.h nfs: add missing selections of CONFIG_CRC32 2025-04-25 10:45:46 +02:00
nfs4state.c NFSv4: Treat ENETUNREACH errors as fatal for state recovery 2025-06-04 14:41:55 +02:00
nfs4super.c
nfs4sysctl.c
nfs4trace.c
nfs4trace.h
nfs4xdr.c
nfs42.h
nfs42proc.c NFSv4.2: mark OFFLOAD_CANCEL MOVEABLE 2025-02-08 09:52:27 +01:00
nfs42xattr.c
nfs42xdr.c NFSv4.2: fix COPY_NOTIFY xdr buf size calculation 2025-02-08 09:52:27 +01:00
nfsroot.c NFS: Fix an off by one in root_nfs_cat() 2024-03-26 18:20:03 -04:00
nfstrace.c
nfstrace.h
pagelist.c nfs: Avoid flushing many pages with NFS_FILE_SYNC 2024-07-25 09:50:45 +02:00
pnfs_dev.c
pnfs_nfs.c nfs: don't share pNFS DS connections between net namespaces 2025-06-04 14:42:25 +02:00
pnfs.c NFSv4/pnfs: Reset the layout state after a layoutreturn 2025-05-22 14:12:18 +02:00
pnfs.h nfs: don't share pNFS DS connections between net namespaces 2025-06-04 14:42:25 +02:00
proc.c
read.c fs/nfs/read: fix double-unlock bug in nfs_return_empty_folio() 2025-06-27 11:08:44 +01:00
super.c nfs: ignore SB_RDONLY when remounting nfs 2025-06-19 15:28:28 +02:00
symlink.c nfs: propagate readlink errors in nfs_symlink_filler 2024-07-25 09:50:44 +02:00
sysctl.c
sysfs.c NFS: Shut down the nfs_client only after all the superblocks 2025-04-10 14:37:35 +02:00
sysfs.h
unlink.c
write.c nfs: fix UAF in direct writes 2024-04-03 15:28:29 +02:00