From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 018CBC43219 for ; Mon, 14 Nov 2022 12:47:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237260AbiKNMrf (ORCPT ); Mon, 14 Nov 2022 07:47:35 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39168 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237402AbiKNMrR (ORCPT ); Mon, 14 Nov 2022 07:47:17 -0500 Received: from ams.source.kernel.org (ams.source.kernel.org [145.40.68.75]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 54F9F6456 for ; Mon, 14 Nov 2022 04:47:16 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id F3FB0B80EBB for ; Mon, 14 Nov 2022 12:47:14 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 594F7C433D6; Mon, 14 Nov 2022 12:47:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1668430033; bh=wspomMSRnZUBG7cHQ8nPBwItbd1jFaK7Pti6INzHzr4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=NqYTA5ojGPvJ3IIxDY+b/JeifaWoKJD00YBizgkdRC7upHqjGJ4k3LDKuI0YlIlj8 Qc6zWBptBRfne+LE41U3d/ctXspq+lJ3qFIbS4jczZpTyqpLudOOnAWbIFEDlV7iOp IahWdl4BnhRV7HzEIhFIAKskeuBOBu/ohVBoVhbA= From: Greg Kroah-Hartman To: stable@vger.kernel.org Cc: Greg Kroah-Hartman , patches@lists.linux.dev, Frank Sorenson , Miklos Szeredi , Sasha Levin Subject: [PATCH 5.10 01/95] fuse: fix readdir cache race Date: Mon, 14 Nov 2022 13:44:55 +0100 Message-Id: <20221114124442.590148413@linuxfoundation.org> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20221114124442.530286937@linuxfoundation.org> References: <20221114124442.530286937@linuxfoundation.org> User-Agent: quilt/0.67 X-stable: review X-Patchwork-Hint: ignore MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: stable@vger.kernel.org From: Miklos Szeredi [ 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 Fixes: 5d7bc7e8680c ("fuse: allow using readdir cache") Cc: # v4.20 Signed-off-by: Miklos Szeredi Signed-off-by: Sasha Levin --- fs/fuse/readdir.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/fs/fuse/readdir.c b/fs/fuse/readdir.c index bc267832310c..d5294e663df5 100644 --- a/fs/fuse/readdir.c +++ b/fs/fuse/readdir.c @@ -77,8 +77,10 @@ static void fuse_add_dirent_to_cache(struct file *file, goto unlock; addr = kmap_atomic(page); - if (!offset) + if (!offset) { clear_page(addr); + SetPageUptodate(page); + } memcpy(addr + offset, dirent, reclen); kunmap_atomic(addr); fi->rdc.size = (index << PAGE_SHIFT) + offset + reclen; @@ -516,6 +518,12 @@ static int fuse_readdir_cached(struct file *file, struct dir_context *ctx) page = find_get_page_flags(file->f_mapping, index, FGP_ACCESSED | FGP_LOCK); + /* Page gone missing, then re-added to cache, but not initialized? */ + if (page && !PageUptodate(page)) { + unlock_page(page); + put_page(page); + page = NULL; + } spin_lock(&fi->rdc.lock); if (!page) { /* -- 2.35.1