[PATCH 4.19] NFS: fix null-ptr-deref in nfs_inode_add_request()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: ChenXiaoSong <chenxiaosong@xxxxxxxxxx>

There is panic as follows:

  BUG: unable to handle kernel NULL pointer dereference at 0000000000000080
  Call Trace:
   nfs_inode_add_request+0x1cc/0x5b8
   nfs_setup_write_request+0x1fa/0x1fc
   nfs_writepage_setup+0x2d/0x7d
   nfs_updatepage+0x8b8/0x936
   nfs_write_end+0x61d/0xd45
   generic_perform_write+0x19a/0x3f0
   nfs_file_write+0x2cc/0x6e5
   new_sync_write+0x442/0x560
   __vfs_write+0xda/0xef
   vfs_write+0x176/0x48b
   ksys_write+0x10a/0x1e9
   __se_sys_write+0x24/0x29
   __x64_sys_write+0x79/0x93
   do_syscall_64+0x16d/0x4bb
   entry_SYSCALL_64_after_hwframe+0x5c/0xc1

The above panic may happen as follows:

  nfs_updatepage
    nfs_writepage_setup
      nfs_setup_write_request
        nfs_try_to_update_request will return NULL
          nfs_wb_page will return 0
            if (clear_page_dirty_for_io(page)) == true
            nfs_writepage_locked will return 0
              nfs_do_writepage will return 0
                nfs_page_async_flush
                  if (nfs_error_is_fatal_on_server(ret)) == true
                  nfs_write_error_remove_page
                    generic_error_remove_page
                      truncate_inode_page
                        delete_from_page_cache
                          __delete_from_page_cache
                            page_cache_tree_delete
                              page->mapping = NULL
                nfs_page_async_flush() return 0 <== this is point
              nfs_do_writepage return 0
            nfs_writepage_locked return 0
          nfs_wb_page return 0
        nfs_try_to_update_request return NULL
        if (req != NULL) == false
        nfs_create_request
          req->wb_page = page // page->mapping == NULL
        nfs_inode_add_request
          mapping = page_file_mapping(req->wb_page) == NULL
            return page->mapping // is NULL
          spin_lock(&mapping->private_lock) // oops, mapping is NULL

Fix this by reporting fatal errors and stop writeback.

The patchset (29 patches) "Fix up soft mounts for NFSv4.x" [1] replaces
the custom error reporting mechanism. It seems that we can fix this bug
if we merge all the patchset into LTS 4.19. However, it is clear that
this is not the best option for LTS 4.19.

By the way, applying commit 22876f540bdf ("NFS: Don't call
generic_error_remove_page() while holding locks") into LTS 4.19 will
introduce other issues [2].

Link[1]: https://lore.kernel.org/all/20190407175912.23528-1-trond.myklebust@xxxxxxxxxxxxxxx/
Link[2]: https://lore.kernel.org/all/tencent_F89651CE8E1BFCEC42C4BFEDD0CA77F82609@xxxxxx/
Fixes: 89047634f5ce ("NFS: Don't interrupt file writeout due to fatal errors")
Signed-off-by: ChenXiaoSong <chenxiaosong@xxxxxxxxxx>
---
 fs/nfs/write.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 65aaa6eaad2c..c69a539eee2c 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -660,7 +660,7 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio,
 	return ret;
 out_launder:
 	nfs_write_error_remove_page(req);
-	return 0;
+	return ret;
 }
 
 static int nfs_do_writepage(struct page *page, struct writeback_control *wbc,
-- 
2.34.1





[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux