From: Matthew Wilcox <willy@infradead.org>
To: Andrew Morton <akpm@linux-foundation.org>,
Jane Chu <jane.chu@oracle.com>,
linux-mm@kvack.org
Cc: Muchun Song <muchun.song@linux.dev>,
Oscar Salvador <osalvador@suse.de>,
David Hildenbrand <david@kernel.org>,
Miaohe Lin <linmiaohe@huawei.com>,
Naoya Horiguchi <nao.horiguchi@gmail.com>,
Jan Kara <jack@suse.cz>,
linux-fsdevel@vger.kernel.org,
Christian Brauner <christian@brauner.io>,
Jiaqi Yan <jiaqiyan@google.com>
Subject: Re: [PATCH v4 10/14] filemap: Add hwpoison handling to filemap_read()
Date: Fri, 24 Jul 2026 17:06:22 +0100 [thread overview]
Message-ID: <amONfpgJInjm8XgF@casper.infradead.org> (raw)
In-Reply-To: <20260723143034.175661-11-willy@infradead.org>
Sashiko review:
> --- Patch [10]: [PATCH v4 10/14] filemap: Add hwpoison handling to filemap_read() ---
> commit c46fb3fcf6cb7055457888cfb186af5ae3a493c2
> Author: Jane Chu <jane.chu@oracle.com>
>
> filemap: Add hwpoison handling to filemap_read()
>
> This commit adds hardware poison handling to filemap_read(). It allows the
> read iterator to make a best-effort copy of data from clean pages,
> preventing Machine Check Exceptions when the page cache contains HWpoison.
>
> > diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
> > index 9cde74320e48a..b146c5228741c 100644
> > --- a/include/linux/page-flags.h
> > +++ b/include/linux/page-flags.h
> > @@ -1111,6 +1112,16 @@ static inline bool is_page_hwpoison(const struct page *page)
> > return PageHWPoison(page);
> > }
> >
> > +static inline bool is_ref_page_hwpoison(const struct folio *folio,
> > + const struct page *page)
> > +{
> > + if (PageHWPoison(page))
> > + return true;
> > + if (folio_test_hugetlb(folio))
> > + return hugetlb_page_hwpoison(folio, page);
>
> Does this lockless traversal risk a Use-After-Free?
>
> When this function calls into hugetlb_page_hwpoison(), it eventually reaches
> precise_page_poisoned() which performs a lockless iteration of the
> hugetlb_hwpoison llist:
>
> precise_page_poisoned()
> llist_for_each_entry(p, READ_ONCE(list->first), node) {
> ...
> }
>
> However, a concurrent memory_failure() can free the list nodes while the
> lockless traversal is in progress, since __folio_free_raw_hwp() calls
> kfree(p) on the nodes without an RCU grace period.
>
> While filemap_read() does not process hugetlb folios, hugetlbfs_read_iter()
> (added earlier in this series) does, making the Use-After-Free directly
> reachable.
Will be addressed by the spinlock I mentioned earlier.
> [ ... ]
>
> > diff --git a/mm/filemap.c b/mm/filemap.c
> > index 58eb9d2406434..26a5f18121f90 100644
> > --- a/mm/filemap.c
> > +++ b/mm/filemap.c
> > @@ -2483,6 +2483,8 @@ static void filemap_get_read_batch(struct address_space *mapping,
> >
> > if (!folio_batch_add(fbatch, folio))
> > break;
> > + if (folio_has_hwpoisoned_page(folio))
> > + break;
>
> This isn't a bug introduced by this patch, but does returning a poisoned
> folio here risk a Machine Check Exception if a disk read populates the folio?
Sure, but we remove hwpoisoned pages from the pagecache for
storage-backed files. So this doesn't come up.
> If a poisoned folio in the page cache is not uptodate,
> filemap_get_read_batch() will return it as the last folio in the batch.
>
> Then filemap_get_pages() will see !folio_test_uptodate(folio) and call
> filemap_update_page(), which locks the folio and passes it to the
> filesystem's read_folio callback:
>
> filemap_update_page()
> error = filemap_read_folio(iocb->ki_filp, mapping->a_ops->read_folio,
> folio);
>
> If the filesystem populates the folio using CPU operations (which is common
> for inline data, fscrypt, squashfs, or block device emulation), the CPU will
> access the poisoned memory and trigger an unrecoverable Machine Check
> Exception. The patch guards the userspace copy path, but misses guarding the
> cache-miss path where the kernel itself reads into the poisoned folio.
>
> > if (!folio_test_uptodate(folio))
> > break;
>
> [ ... ]
>
> > @@ -2862,14 +2887,18 @@ ssize_t filemap_read(struct kiocb *iocb, struct iov_iter *iter,
> > if (writably_mapped)
> > flush_dcache_folio(folio);
> >
> > - copied = copy_folio_to_iter(folio, offset, bytes, iter);
> > + copied = adjust_range_hwpoison(folio, offset, bytes);
> > + if (copied < bytes)
> > + error = -EIO;
> > + copied = copy_folio_to_iter(folio, offset, copied, iter);
>
> This isn't a bug introduced by this patch, but will filemap_splice_read()
> still trigger a Machine Check Exception on poisoned pages since it lacks
> similar protection?
>
> While this patch successfully updates filemap_read() to use
> adjust_range_hwpoison() to prevent reading poisoned memory,
> filemap_splice_read() was left unmodified.
Hugetlb doesn't implement splice_read(), so this is irrelevant.
> filemap_splice_read() uses the same filemap_get_pages() logic, loops over
> the returned batch, and unconditionally splices each folio into the pipe:
>
> filemap_splice_read()
> ...
> n = splice_folio_into_pipe(pipe, folio, *ppos, n);
>
> When a userspace process subsequently reads from the pipe, the kernel will
> access the poisoned physical page (e.g., via copy_page_to_iter()), triggering
> an unrecoverable Machine Check Exception.
next prev parent reply other threads:[~2026-07-24 16:06 UTC|newest]
Thread overview: 37+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-23 14:30 [PATCH v4 00/14] Use generic_file_read_iter() in hugetlbfs Matthew Wilcox (Oracle)
2026-07-23 14:30 ` [PATCH v4 01/14] memory-failure: Fix hardware poison check in unpoison_memory() again Matthew Wilcox (Oracle)
2026-07-24 12:32 ` Matthew Wilcox
2026-07-23 14:30 ` [PATCH v4 02/14] memory-failure: Test the page is hwpoison before taking the mutex Matthew Wilcox (Oracle)
2026-07-24 12:34 ` Matthew Wilcox
2026-07-23 14:30 ` [PATCH v4 03/14] mm: Rename folio_contain_hwpoison_page() to folio_has_hwpoison_page() Matthew Wilcox (Oracle)
2026-07-24 12:36 ` Matthew Wilcox
2026-07-24 12:52 ` Michael S. Tsirkin
2026-07-24 13:24 ` Matthew Wilcox
2026-07-23 14:30 ` [PATCH v4 04/14] hugetlb: Mark some function arguments as const Matthew Wilcox (Oracle)
2026-07-24 12:38 ` Matthew Wilcox
2026-07-23 14:30 ` [PATCH v4 05/14] guest_memfd: Use folio_has_hwpoisoned_page() Matthew Wilcox (Oracle)
2026-07-24 12:44 ` Matthew Wilcox
2026-07-24 15:16 ` Sean Christopherson
2026-07-24 16:51 ` Ackerley Tng
2026-07-24 18:04 ` Matthew Wilcox
2026-07-24 15:16 ` Sean Christopherson
2026-07-24 16:40 ` Ackerley Tng
2026-07-23 14:30 ` [PATCH v4 06/14] memory-failure: Remove raw_hwp_list_head() Matthew Wilcox (Oracle)
2026-07-24 12:45 ` Matthew Wilcox
2026-07-23 14:30 ` [PATCH v4 07/14] hugetlb: Use the has_hwpoisoned flag Matthew Wilcox (Oracle)
2026-07-24 13:21 ` Matthew Wilcox
2026-07-23 14:30 ` [PATCH v4 08/14] mm: Remove locking mf_mutex in is_raw_hwpoison_page_in_hugepage() Matthew Wilcox (Oracle)
2026-07-24 13:41 ` Matthew Wilcox
2026-07-23 14:30 ` [PATCH v4 09/14] mm: Check individual hugetlb pages for poison Matthew Wilcox (Oracle)
2026-07-24 14:00 ` Matthew Wilcox
2026-07-23 14:30 ` [PATCH v4 10/14] filemap: Add hwpoison handling to filemap_read() Matthew Wilcox (Oracle)
2026-07-24 16:06 ` Matthew Wilcox [this message]
2026-07-23 14:30 ` [PATCH v4 11/14] filemap: Remove checks in mapping_set_folio_order_range() Matthew Wilcox (Oracle)
2026-07-24 16:08 ` Matthew Wilcox
2026-07-23 14:30 ` [PATCH v4 12/14] hugetlb: Set mapping folio order Matthew Wilcox (Oracle)
2026-07-24 16:16 ` Matthew Wilcox
2026-07-23 14:30 ` [PATCH v4 13/14] filemap: Add support for authoritative mappings Matthew Wilcox (Oracle)
2026-07-24 16:15 ` Matthew Wilcox
2026-07-24 16:29 ` Matthew Wilcox
2026-07-23 14:30 ` [PATCH v4 14/14] hugetlb: replace hugetlbfs_read_iter() with generic_file_read_iter() Matthew Wilcox (Oracle)
2026-07-24 16:36 ` Matthew Wilcox
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=amONfpgJInjm8XgF@casper.infradead.org \
--to=willy@infradead.org \
--cc=akpm@linux-foundation.org \
--cc=christian@brauner.io \
--cc=david@kernel.org \
--cc=jack@suse.cz \
--cc=jane.chu@oracle.com \
--cc=jiaqiyan@google.com \
--cc=linmiaohe@huawei.com \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=muchun.song@linux.dev \
--cc=nao.horiguchi@gmail.com \
--cc=osalvador@suse.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.