fuse: fix readdir cache race
authorMiklos Szeredi <mszeredi@redhat.com>
Thu, 20 Oct 2022 15:18:58 +0000 (17:18 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 16 Nov 2022 08:58:13 +0000 (09:58 +0100)
commit93a5de7e88433b6277082c35d947dc5ea4d8dec0
treeaa14f3a6bdec922189f0318e3c6c0f21466b3c0e
parent1920cf94545a35d1485b911cd7ad49d4785b1d8e
fuse: fix readdir cache race

[ Upstream commit 9fa248c65bdbf5af0a2f74dd38575acfc8dfd2bf ]

There's a race in fuse's readdir cache that can result in an uninitilized
page being read.  The page lock is supposed to prevent this from happening
but in the following case it doesn't:

Two fuse_add_dirent_to_cache() start out and get the same parameters
(size=0,offset=0).  One of them wins the race to create and lock the page,
after which it fills in data, sets rdc.size and unlocks the page.

In the meantime the page gets evicted from the cache before the other
instance gets to run.  That one also creates the page, but finds the
size to be mismatched, bails out and leaves the uninitialized page in the
cache.

Fix by marking a filled page uptodate and ignoring non-uptodate pages.

Reported-by: Frank Sorenson <fsorenso@redhat.com>
Fixes: 5d7bc7e8680c ("fuse: allow using readdir cache")
Cc: <stable@vger.kernel.org> # v4.20
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
fs/fuse/readdir.c