[PATCH] NFS: fix folio dereference before NULL check in nfs_inode_remove_request()

From: Jiangshan Yi

Date: Wed Jul 01 2026 - 21:50:38 EST


nfs_inode_remove_request() obtains the folio for the head request via
nfs_page_to_folio(), which returns NULL when the PG_FOLIO flag is not
set on req->wb_head.

The presence of the "if (likely(folio))" check shows the code already
assumes folio can be NULL. However, folio was dereferenced before that
check:

folio = nfs_page_to_folio(req->wb_head);
mapping = folio->mapping; /* deref */

spin_lock(&mapping->i_private_lock);
if (likely(folio)) { /* too late */

folio->mapping is read (and mapping->i_private_lock is taken, and
folio_end_dropbehind(folio) is called outside the check) before folio
is validated, so a NULL folio would crash before the guard is ever
reached, rendering the check useless.

Move the folio->mapping read, the i_private_lock section and the
folio_end_dropbehind() call inside the "if (likely(folio))" block so
the folio is only dereferenced after it has been confirmed non-NULL.
The behaviour is unchanged when folio is non-NULL.

Signed-off-by: Jiangshan Yi <yijiangshan@xxxxxxxxxx>
---
fs/nfs/write.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index fcffb8c9e9df..33d51eb9a3a4 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -739,17 +739,18 @@ static void nfs_inode_remove_request(struct nfs_page *req)
nfs_page_group_lock(req);
if (nfs_page_group_sync_on_bit_locked(req, PG_REMOVE)) {
struct folio *folio = nfs_page_to_folio(req->wb_head);
- struct address_space *mapping = folio->mapping;

- spin_lock(&mapping->i_private_lock);
if (likely(folio)) {
+ struct address_space *mapping = folio->mapping;
+
+ spin_lock(&mapping->i_private_lock);
folio->private = NULL;
folio_clear_private(folio);
clear_bit(PG_MAPPED, &req->wb_head->wb_flags);
- }
- spin_unlock(&mapping->i_private_lock);
+ spin_unlock(&mapping->i_private_lock);

- folio_end_dropbehind(folio);
+ folio_end_dropbehind(folio);
+ }
}
nfs_page_group_unlock(req);

--
2.25.1