linux/fs/afs
David Howells 00d3928737 afs: Fix race between post-modification dir edit and readdir/d_revalidate
commit 2105c2820d upstream.

AFS directories are retained locally as a structured file, with lookup
being effected by a local search of the file contents.  When a modification
(such as mkdir) happens, the dir file content is modified locally rather
than redownloading the directory.

The directory contents are accessed in a number of ways, with a number of
different locks schemes:

 (1) Download of contents - dvnode->validate_lock/write in afs_read_dir().

 (2) Lookup and readdir - dvnode->validate_lock/read in afs_dir_iterate(),
     downgrading from (1) if necessary.

 (3) d_revalidate of child dentry - dvnode->validate_lock/read in
     afs_do_lookup_one() downgrading from (1) if necessary.

 (4) Edit of dir after modification - page locks on individual dir pages.

Unfortunately, because (4) uses different locking scheme to (1) - (3),
nothing protects against the page being scanned whilst the edit is
underway.  Even download is not safe as it doesn't lock the pages - relying
instead on the validate_lock to serialise as a whole (the theory being that
directory contents are treated as a block and always downloaded as a
block).

Fix this by write-locking dvnode->validate_lock around the edits.  Care
must be taken in the rename case as there may be two different dirs - but
they need not be locked at the same time.  In any case, once the lock is
taken, the directory version must be rechecked, and the edit skipped if a
later version has been downloaded by revalidation (there can't have been
any local changes because the VFS holds the inode lock, but there can have
been remote changes).

Fixes: 63a4681ff3 ("afs: Locally edit directory data for mkdir/create/unlink/...")
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2020-04-23 10:36:25 +02:00
..
Kconfig
Makefile
addr_list.c
afs.h
afs_cm.h
afs_fs.h
afs_vl.h
cache.c
callback.c
cell.c
cmservice.c afs: Fix handling of an abort from a service handler 2020-04-01 11:02:04 +02:00
dir.c afs: Fix race between post-modification dir edit and readdir/d_revalidate 2020-04-23 10:36:25 +02:00
dir_edit.c
dir_silly.c afs: Fix race between post-modification dir edit and readdir/d_revalidate 2020-04-23 10:36:25 +02:00
dynroot.c
file.c
flock.c
fs_probe.c afs: Fix unpinned address list during probing 2020-04-01 11:02:08 +02:00
fsclient.c afs: Fix rename operation status delivery 2020-04-23 10:36:25 +02:00
inode.c
internal.h afs: Fix handling of an abort from a service handler 2020-04-01 11:02:04 +02:00
main.c
misc.c
mntpt.c
proc.c
protocol_uae.h
protocol_yfs.h
rotate.c
rxrpc.c rxrpc: Fix call interruptibility handling 2020-04-17 10:49:57 +02:00
security.c
server.c
server_list.c
super.c
vl_list.c
vl_probe.c
vl_rotate.c
vlclient.c
volume.c
write.c
xattr.c
xdr_fs.h
yfsclient.c afs: Fix rename operation status delivery 2020-04-23 10:36:25 +02:00