mirror-linux/fs/afs
David Howells c0410adf3d
afs: Fix the locking used by afs_get_link()
The afs filesystem in the kernel doesn't do locking correctly for symbolic
links.  There are a number of problems:

 (1) It doesn't do any locking around afs_read_single() to prevent races
     between multiple ->get_link() calls, thereby allowing the possibility
     of leaks.

 (2) It doesn't use RCU barriering when accessing the buffer pointers
     during RCU pathwalk.

 (3) It can race with another thread updating the contents of the symlink
     if a third party updated it on the server.

Fix this by the following means:

 (0) Move symlink handling into its own file as this makes it more
     complicated.

 (1) Take the validate_lock around afs_read_single() to prevent races
     between multiple ->get_link() calls.

 (2) Keep a separate copy of the symlink contents with an rcu_head.  This
     is always going to be a lot smaller than a page, so it can be
     kmalloc'd and save quite a bit of memory.  It also needs a refcount
     for non-RCU pathwalk.

 (3) Split the symlink read and write-to-cache routines in afs from those
     for directories.

 (4) Discard the I/O buffer as soon as the write-to-cache completes as this
     is a full page (plus a folio_queue).

 (5) If there's no cache, discard the I/O buffer immediately after reading
     and copying if there is no cache.

Fixes: eae9e78951 ("afs: Use netfslib for symlinks, allowing them to be cached")
Fixes: 6698c02d64 ("afs: Locally initialise the contents of a new symlink on creation")
Closes: https://sashiko.dev/#/patchset/20260326104544.509518-1-dhowells%40redhat.com
Signed-off-by: David Howells <dhowells@redhat.com>
Link: https://patch.msgid.link/20260512123404.719402-25-dhowells@redhat.com
cc: Marc Dionne <marc.dionne@auristor.com>
cc: linux-afs@lists.infradead.org
cc: linux-fsdevel@vger.kernel.org
Signed-off-by: Christian Brauner <brauner@kernel.org>
2026-05-12 14:42:33 +02:00
..
Kconfig afs: Use rxgk RESPONSE to pass token for callback channel 2025-04-14 17:36:42 -07:00
Makefile afs: Fix the locking used by afs_get_link() 2026-05-12 14:42:33 +02:00
addr_list.c rxrpc, afs: Fix missing error pointer check after rxrpc_kernel_lookup_peer() 2026-03-06 17:49:52 -08:00
addr_prefs.c Convert 'alloc_flex' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
afs.h afs: Fix the maximum cell name length 2025-01-07 15:55:25 +01:00
afs_cm.h treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 152 2019-05-30 11:26:32 -07:00
afs_fs.h treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 152 2019-05-30 11:26:32 -07:00
afs_vl.h afs: Fix the maximum cell name length 2025-01-07 15:55:25 +01:00
callback.c fs: replace use of system_unbound_wq with system_dfl_wq 2025-09-19 16:15:07 +02:00
cell.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
cm_security.c afs: Use rxgk RESPONSE to pass token for callback channel 2025-04-14 17:36:42 -07:00
cmservice.c Convert remaining multi-line kmalloc_obj/flex GFP_KERNEL uses 2026-02-22 08:26:33 -08:00
dir.c afs: Fix the locking used by afs_get_link() 2026-05-12 14:42:33 +02:00
dir_edit.c Simplifying ->d_name audits, easy part. 2025-10-03 11:14:02 -07:00
dir_search.c treewide: change inode->i_ino from unsigned long to u64 2026-03-06 14:31:28 +01:00
dir_silly.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
dynroot.c treewide: change inode->i_ino from unsigned long to u64 2026-03-06 14:31:28 +01:00
file.c netfs: Fix potential for tearing in ->remote_i_size and ->zero_point 2026-05-12 14:42:30 +02:00
flock.c afs: adapt to breakup of struct file_lock 2024-02-05 13:11:42 +01:00
fs_operation.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
fs_probe.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
fsclient.c afs: Fix the locking used by afs_get_link() 2026-05-12 14:42:33 +02:00
inode.c afs: Fix the locking used by afs_get_link() 2026-05-12 14:42:33 +02:00
internal.h afs: Fix the locking used by afs_get_link() 2026-05-12 14:42:33 +02:00
main.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
misc.c afs: Add support for RENAME_NOREPLACE and RENAME_EXCHANGE 2025-09-25 09:19:07 +02:00
mntpt.c afs: Fix dynamic lookup to fail on cell lookup failure 2025-10-29 13:51:38 +01:00
proc.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
protocol_afs.h afs: Fix corruption in reads at fpos 2G-4G from an OpenAFS server 2021-09-13 09:14:21 +01:00
protocol_uae.h afs: Add support for the UAE error table 2019-06-28 18:37:53 +01:00
protocol_yfs.h afs: Add support for RENAME_NOREPLACE and RENAME_EXCHANGE 2025-09-25 09:19:07 +02:00
rotate.c Convert remaining multi-line kmalloc_obj/flex GFP_KERNEL uses 2026-02-22 08:26:33 -08:00
rxrpc.c treewide: Replace kmalloc with kmalloc_obj for non-scalar types 2026-02-21 01:02:28 -08:00
security.c treewide: Replace kmalloc with kmalloc_obj for non-scalar types 2026-02-21 01:02:28 -08:00
server.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
server_list.c Convert 'alloc_flex' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
super.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
symlink.c afs: Fix the locking used by afs_get_link() 2026-05-12 14:42:33 +02:00
validation.c afs: Fix the locking used by afs_get_link() 2026-05-12 14:42:33 +02:00
vl_alias.c afs: Fix dynamic lookup to fail on cell lookup failure 2025-10-29 13:51:38 +01:00
vl_list.c Convert 'alloc_flex' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
vl_probe.c afs: Keep a record of the current fileserver endpoint state 2024-01-01 16:37:27 +00:00
vl_rotate.c afs: Simplify cell record handling 2025-03-10 09:47:15 +00:00
vlclient.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
volume.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
write.c netfs: Fix potential for tearing in ->remote_i_size and ->zero_point 2026-05-12 14:42:30 +02:00
xattr.c Convert 'alloc_flex' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
xdr_fs.h afs: Fix directory format encoding struct 2024-12-20 22:34:04 +01:00
yfsclient.c afs: Fix the locking used by afs_get_link() 2026-05-12 14:42:33 +02:00