Re: [syzbot] [sound?] kernel BUG in filemap_fault (2)

From: David Hildenbrand
Date: Wed Sep 17 2025 - 05:04:41 EST



if (!lock_folio_maybe_drop_mmap(vmf, folio, &fpin))
goto out_retry;

/* Did it get truncated? */
if (unlikely(folio->mapping != mapping)) {
folio_unlock(folio);
folio_put(folio);
goto retry_find;
}
VM_BUG_ON_FOLIO(!folio_contains(folio, index), folio);


I would assume that if !folio_contains(folio, index), either the folio got
split in the meantime (filemap_get_folio() returned with a raised reference,
though) or that file pagecache contained something wrong.

Right.

In __filemap_get_folio() we perform the same checks after locking the folio
(with FGP_LOCK), and weird enough it didn't trigger yet there.

But we don't call __filemap_get_folio() with FGP_LOCK from filemap_fault().

Yes. I should have clarified that we haven't seen the VM_BUG_ON_FOLIO() trigger on other callpaths that set FGP_LOCK, because I would think the very same problem could happen there as well.

The folio locking is handled by lock_folio_maybe_drop_mmap() as you
mentioned. So this is the first time we do the assert after getting the
folio AFAICT. So some race with folio split looks plausible. Checking the
reproducer it does play with mmap(2) and madvise(MADV_REMOVE) over the
mapped range so the page fault may be racing with
truncate_inode_partial_folio()->try_folio_split(). But I don't see the race
there now...

__filemap_get_folio() will grab a reference and verify that the xarray didn't change. So having a concurrent split succeed would be weird, because freezing the refcount should fail. Of course, some refcounting inconsistency could trigger something weird like that.

I can spot that we are also manually calling __filemap_get_folio(FGP_CREAT|FGP_FOR_MMAP) on the else path if filemap_get_folio() failed, maybe that's the problematic bit (and maybe that's where readahead logic makes a difference).

--
Cheers

David / dhildenb