From 59075fb8b7887b4149e73e3d5aee2ceeeb87d287 Mon Sep 17 00:00:00 2001 From: Jiangshan Yi Date: Thu, 2 Jul 2026 09:50:14 +0800 Subject: [PATCH] NFS: fix folio dereference before NULL check in nfs_inode_remove_request() 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 Signed-off-by: Trond Myklebust --- 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 d2b03ceaeb4f..ec4e0d6c829c 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);