orangefs: don't continue on to gpf if client dies on write.

I got a message from Farhad Alemi (farhad.alemi@berkeley.edu)
showing that this can happen:

Oops: general protection fault, probably for non-canonical address
0xdffffc0000000002: 0000 [#1] SMP KASAN NOPTI
  KASAN: null-ptr-deref in range [0x0000000000000010-0x0000000000000017]
  RIP: 0010:orangefs_writepages_callback fs/orangefs/inode.c:144 [inline]
  RIP: 0010:orangefs_writepages+0x642/0xc60 fs/orangefs/inode.c:205
  Call Trace:
   orangefs_writepages+0x642/0xc60 fs/orangefs/inode.c:205
   do_writepages+0x328/0x550 mm/page-writeback.c:2571
   filemap_write_and_wait_range+0x332/0x3f0 mm/filemap.c:685
   orangefs_flush+0x44/0x60 fs/orangefs/file.c:566
   filp_flush+0xbd/0x190 fs/open.c:1467
   filp_close+0x1d/0x40 fs/open.c:1480
   close_files fs/file.c:494 [inline]
   put_files_struct+0x1b6/0x340 fs/file.c:509
   do_exit+0x6a8/0x2360 kernel/exit.c:971

With the help of Grok I created a reproducer program that
causes a gpf on the same line: "ow->folios[ow->nfolios++] = folio;"
in orangefs_writepages_callback. The reproducer program flows into
this new code after this patch.

Signed-off-by: Mike Marshall <hubcap@omnibond.com>
This commit is contained in:
Mike Marshall 2026-09-07 12:02:40 -04:00
parent cb90176836
commit 2bc09cb0e9

View File

@ -181,8 +181,27 @@ static int orangefs_writepages(struct address_space *mapping,
{
struct orangefs_writepages *ow;
struct blk_plug plug;
int error;
int error = 0;
struct folio *folio = NULL;
int maxpages;
maxpages = orangefs_bufmap_size_query() / PAGE_SIZE;
if (maxpages < 1) {
/*
* Probably the client is dead and there's no bufmap.
* Walk writeback_iter anyway so each dirty folio is unlocked
* and writeback is ended. wait_for_direct_io will fail; the
* data is not written.
*/
gossip_err("%s: maxpages < 1. \n", __func__);
while ((folio = writeback_iter(mapping, wbc, folio, &error))) {
error = orangefs_writepage_locked(folio, wbc);
mapping_set_error(mapping, error);
folio_unlock(folio);
folio_end_writeback(folio);
}
return error;
}
ow = kzalloc_obj(struct orangefs_writepages);
if (!ow)