mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v2 0/2] mm/memory: refuse to map page cache folios that are not uptodate
@ 2026-11-09 12:04 Kiryl Shutsemau (Meta)
  2026-11-09 12:04 ` [PATCH v2 1/2] mm/memory: recheck PG_uptodate after ->page_mkwrite() Kiryl Shutsemau (Meta)
  2026-11-09 12:04 ` [PATCH v2 2/2] mm/memory: refuse to map page cache folios that are not uptodate Kiryl Shutsemau (Meta)
  0 siblings, 2 replies; 10+ messages in thread
From: Kiryl Shutsemau (Meta) @ 2026-11-09 12:04 UTC (permalink / raw)
  To: Andrew Morton, David Hildenbrand (Arm), Pedro Falcato
  Cc: Kiryl Shutsemau (Meta),
	Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
	Suren Baghdasaryan, Michal Hocko, Matthew Wilcox (Oracle),
	Hugh Dickins, Chris Mason, linux-mm, linux-fsdevel, linux-kernel,
	kernel-team

A page cache folio that is not uptodate holds data that was never read
in or cleared. Each path that maps page cache checks for this itself,
and a path that misses the check leaks stale memory to userspace.
MADV_COLLAPSE did exactly that with fallocated shmem THPs.

Patch 2 adds a backstop: warn and refuse the mapping in __do_fault()
and do_set_pmd().

Patch 1 fixes a race the backstop would trip over. do_shared_fault()
unlocks the folio around ->page_mkwrite(), and a writeback error can
clear PG_uptodate in that window. The fault goes on to map the folio,
and stores through the mapping can be lost when it is read in again.
Retry the fault instead.

v2:
 - New patch 1: recheck PG_uptodate after ->page_mkwrite() (Sashiko)
 - Check in __do_fault(), before the folio is unlocked, instead of in
   finish_fault()
 - WARN_ON_ONCE() without a message
 - Rebase on current mm-new

v1: https://lore.kernel.org/all/20261106144323.3634477-1-kirill@shutemov.name/

Kiryl Shutsemau (Meta) (2):
  mm/memory: recheck PG_uptodate after ->page_mkwrite()
  mm/memory: refuse to map page cache folios that are not uptodate

 mm/memory.c | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

Range-diff against v1:
-:  ------------ > 1:  632ab50e643d mm/memory: recheck PG_uptodate after ->page_mkwrite()
1:  af1dd44c0e1b ! 2:  1e329f330c41 mm/memory: refuse to map page cache folios that are not uptodate
    @@ Commit message
         leaks stale memory silently. MADV_COLLAPSE did exactly that with
         fallocated shmem THPs until recently.
     
    -    Warn and refuse the mapping in finish_fault() and do_set_pmd().
    -    finish_fault() checks the folio ->fault() returned rather than the one
    -    it maps: for CoW, do_cow_fault() copies the page cache folio and maps
    -    the copy. do_set_pmd() covers MADV_COLLAPSE, which maps without a
    -    fault.
    +    Warn and refuse the mapping in __do_fault() and do_set_pmd().
    +
    +    __do_fault() checks the folio ->fault() returned while it is still
    +    locked. do_shared_fault() unlocks it for ->page_mkwrite(), and a
    +    writeback error can clear PG_uptodate after that; that case retries the
    +    fault instead. For CoW, __do_fault() sees the page cache folio that
    +    do_cow_fault() copies from. do_set_pmd() covers MADV_COLLAPSE, which
    +    maps without a fault.
     
         The fault gets SIGBUS, as for a folio that fails to read in.
         MADV_COLLAPSE fails and leaves the range to be faulted in.
    @@ Commit message
     
      ## mm/memory.c ##
     @@ mm/memory.c: static vm_fault_t __do_fault(struct vm_fault *vmf)
    + 	else
    + 		VM_BUG_ON_PAGE(!folio_test_locked(folio), vmf->page);
    + 
    ++	if (WARN_ON_ONCE(file_folio_not_uptodate(folio))) {
    ++		folio_unlock(folio);
    ++		folio_put(folio);
    ++		vmf->page = NULL;
    ++		return VM_FAULT_SIGBUS;
    ++	}
    ++
      	return ret;
      }
      
    -+/*
    -+ * A page cache folio that is not uptodate holds data that was never read in
    -+ * or cleared, and mapping it leaks stale memory to userspace. The callers are
    -+ * expected to check, so treat a hit as a kernel bug and refuse the mapping.
    -+ */
    -+static bool file_folio_not_uptodate(struct folio *folio)
    -+{
    -+	if (likely(folio_test_uptodate(folio)))
    -+		return false;
    -+	/* Driver pages from ->fault() never get PG_uptodate */
    -+	if (folio_test_anon(folio) || !folio->mapping)
    -+		return false;
    -+	WARN_ONCE(1, "refusing to map a page cache folio that is not uptodate\n");
    -+	return true;
    -+}
    -+
    - #ifdef CONFIG_TRANSPARENT_HUGEPAGE
    - static void deposit_prealloc_pte(struct vm_fault *vmf)
    - {
     @@ mm/memory.c: vm_fault_t do_set_pmd(struct vm_fault *vmf, struct folio *folio, struct page *pa
      		return ret;
      	page = &folio->page;
      
    -+	if (file_folio_not_uptodate(folio))
    ++	if (WARN_ON_ONCE(file_folio_not_uptodate(folio)))
     +		return VM_FAULT_SIGBUS;
     +
      	/*
      	 * Just backoff if any subpage of a THP is corrupted otherwise
      	 * the corrupted page may mapped by PMD silently to escape the
    -@@ mm/memory.c: vm_fault_t finish_fault(struct vm_fault *vmf)
    - 	unsigned long addr;
    - 	bool needs_fallback = false;
    - 
    -+	/*
    -+	 * Check the folio ->fault() returned. For CoW that is the source of the
    -+	 * copy; DAX CoW has none.
    -+	 */
    -+	if (vmf->page) {
    -+		folio = page_folio(vmf->page);
    -+		if (file_folio_not_uptodate(folio))
    -+			return VM_FAULT_SIGBUS;
    -+	}
    -+
    - fallback:
    - 	addr = vmf->address;
    - 

base-commit: b95f8bb86713c860ce8536d22a988b949b884d5f
-- 
2.54.0


^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2026-11-09 20:30 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-09 12:04 [PATCH v2 0/2] mm/memory: refuse to map page cache folios that are not uptodate Kiryl Shutsemau (Meta)
2026-11-09 12:04 ` [PATCH v2 1/2] mm/memory: recheck PG_uptodate after ->page_mkwrite() Kiryl Shutsemau (Meta)
2026-11-09 14:11   ` Pedro Falcato
2026-11-09 14:40     ` Kiryl Shutsemau
2026-11-09 16:11   ` Lorenzo Stoakes (ARM)
2026-11-09 17:17     ` Kiryl Shutsemau
2026-11-09 17:30       ` Lorenzo Stoakes (ARM)
2026-11-09 20:30   ` Matthew Wilcox
2026-11-09 12:04 ` [PATCH v2 2/2] mm/memory: refuse to map page cache folios that are not uptodate Kiryl Shutsemau (Meta)
2026-11-09 14:13   ` Pedro Falcato

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®