2
0
mirror of https://github.com/edk2-porting/linux-next.git synced 2024-12-25 13:43:55 +08:00
linux-next/fs/afs
David Howells b61f7dcf4e afs: Fix directory page locking
The afs directory loading code (primarily afs_read_dir()) locks all the
pages that hold a directory's content blob to defend against
getdents/getdents races and getdents/lookup races where the competitors
issue conflicting reads on the same data.  As the reads will complete
consecutively, they may retrieve different versions of the data and
one may overwrite the data that the other is busy parsing.

Fix this by not locking the pages at all, but rather by turning the
validation lock into an rwsem and getting an exclusive lock on it whilst
reading the data or validating the attributes and a shared lock whilst
parsing the data.  Sharing the attribute validation lock should be fine as
the data fetch will retrieve the attributes also.

The individual page locks aren't needed at all as the only place they're
being used is to serialise data loading.

Without this patch, the:

 	if (!test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags)) {
		...
	}

part of afs_read_dir() may be skipped, leaving the pages unlocked when we
hit the success: clause - in which case we try to unlock the not-locked
pages, leading to the following oops:

  page:ffffe38b405b4300 count:3 mapcount:0 mapping:ffff98156c83a978 index:0x0
  flags: 0xfffe000001004(referenced|private)
  raw: 000fffe000001004 ffff98156c83a978 0000000000000000 00000003ffffffff
  raw: dead000000000100 dead000000000200 0000000000000001 ffff98156b27c000
  page dumped because: VM_BUG_ON_PAGE(!PageLocked(page))
  page->mem_cgroup:ffff98156b27c000
  ------------[ cut here ]------------
  kernel BUG at mm/filemap.c:1205!
  ...
  RIP: 0010:unlock_page+0x43/0x50
  ...
  Call Trace:
   afs_dir_iterate+0x789/0x8f0 [kafs]
   ? _cond_resched+0x15/0x30
   ? kmem_cache_alloc_trace+0x166/0x1d0
   ? afs_do_lookup+0x69/0x490 [kafs]
   ? afs_do_lookup+0x101/0x490 [kafs]
   ? key_default_cmp+0x20/0x20
   ? request_key+0x3c/0x80
   ? afs_lookup+0xf1/0x340 [kafs]
   ? __lookup_slow+0x97/0x150
   ? lookup_slow+0x35/0x50
   ? walk_component+0x1bf/0x490
   ? path_lookupat.isra.52+0x75/0x200
   ? filename_lookup.part.66+0xa0/0x170
   ? afs_end_vnode_operation+0x41/0x60 [kafs]
   ? __check_object_size+0x9c/0x171
   ? strncpy_from_user+0x4a/0x170
   ? vfs_statx+0x73/0xe0
   ? __do_sys_newlstat+0x39/0x70
   ? __x64_sys_getdents+0xc9/0x140
   ? __x64_sys_getdents+0x140/0x140
   ? do_syscall_64+0x5b/0x160
   ? entry_SYSCALL_64_after_hwframe+0x44/0xa9

Fixes: f3ddee8dc4 ("afs: Fix directory handling")
Reported-by: Marc Dionne <marc.dionne@auristor.com>
Signed-off-by: David Howells <dhowells@redhat.com>
2018-05-14 13:17:35 +01:00
..
addr_list.c afs: Fix checker warnings 2018-04-09 21:12:31 +01:00
afs_cm.h afs: support the CB.ProbeUuid RPC op 2008-04-29 08:06:26 -07:00
afs_fs.h afs: Prospectively look up extra files when doing a single lookup 2018-04-09 21:12:31 +01:00
afs_vl.h afs: Make use of the YFS service upgrade to fully support IPv6 2017-11-13 15:38:19 +00:00
afs.h afs: Rearrange status mapping 2018-04-09 21:53:59 +01:00
cache.c fscache: Pass object size in rather than calling back for it 2018-04-06 14:05:14 +01:00
callback.c afs: Do better accretion of small writes on newly created content 2018-04-09 21:54:48 +01:00
cell.c afs: Implement @cell substitution handling 2018-04-09 21:18:58 +01:00
cmservice.c afs: Trace protocol errors 2018-04-09 21:54:48 +01:00
dir_edit.c afs: Locally edit directory data for mkdir/create/unlink/... 2018-04-09 21:54:48 +01:00
dir.c afs: Fix directory page locking 2018-05-14 13:17:35 +01:00
dynroot.c afs: Split the dynroot stuff out and give it its own ops tables 2018-04-09 21:54:00 +01:00
file.c afs: Do better accretion of small writes on newly created content 2018-04-09 21:54:48 +01:00
flock.c afs: Make it possible to get the data version in readpage 2018-04-09 21:53:56 +01:00
fsclient.c afs: Trace protocol errors 2018-04-09 21:54:48 +01:00
inode.c afs: Fix directory page locking 2018-05-14 13:17:35 +01:00
internal.h afs: Fix directory page locking 2018-05-14 13:17:35 +01:00
Kconfig fs/afs: remove depends on CONFIG_EXPERIMENTAL 2013-01-21 14:39:04 -08:00
main.c afs: Implement @sys substitution handling 2018-04-09 21:12:31 +01:00
Makefile afs: Locally edit directory data for mkdir/create/unlink/... 2018-04-09 21:54:48 +01:00
misc.c afs: Consolidate abort_to_error translators 2017-11-13 15:38:17 +00:00
mntpt.c afs: Support the AFS dynamic root 2018-02-06 14:43:37 +00:00
netdevices.c License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
proc.c afs: Add stats for data transfer operations 2018-04-09 21:54:48 +01:00
rotate.c afs: Fix checker warnings 2018-04-09 21:12:31 +01:00
rxrpc.c afs: Trace protocol errors 2018-04-09 21:54:48 +01:00
security.c afs: Make it possible to get the data version in readpage 2018-04-09 21:53:56 +01:00
server_list.c afs: Fix server list handling 2018-02-06 14:36:54 +00:00
server.c afs: Fix server record deletion 2018-04-20 09:59:33 -07:00
super.c afs: Fix directory page locking 2018-05-14 13:17:35 +01:00
vlclient.c afs: Trace protocol errors 2018-04-09 21:54:48 +01:00
volume.c fscache: Pass object size in rather than calling back for it 2018-04-06 14:05:14 +01:00
write.c Merge branch 'afs-dh' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs 2018-04-12 11:59:06 -07:00
xattr.c afs: Overhaul volume and server record caching and fileserver rotation 2017-11-13 15:38:19 +00:00
xdr_fs.h afs: Adjust the directory XDR structures 2018-04-09 21:54:48 +01:00