Linux filesystem development
 help / color / mirror / Atom feed
From: Matthew Wilcox <willy@infradead.org>
To: Gregory Price <gourry@gourry.net>
Cc: Andrew Morton <akpm@linux-foundation.org>,
	Jane Chu <jane.chu@oracle.com>,
	linux-mm@kvack.org, 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 v8 10/15] mm: Check individual hugetlb pages for poison
Date: Tue, 4 Aug 2026 22:21:29 +0100	[thread overview]
Message-ID: <anJX2bjH57IHz-jX@casper.infradead.org> (raw)
In-Reply-To: <anI5bPVScck1WXvh@gourry-fedora-PF4VCD3F>

On Tue, Aug 04, 2026 at 03:15:37PM -0400, Gregory Price wrote:
> On Fri, Jul 31, 2026 at 09:07:55PM +0100, Matthew Wilcox (Oracle) wrote:
> > +/*
> > + * We have no reference on the folio containing this page.
> > + * The hugetlb_lock keeps hugetlb folios from being freed.
> > + */
> > +bool hugetlb_unref_page_hwpoison(const struct page *page)
> > +{
> > +	const struct folio *folio;
> > +	unsigned long flags;
> > +	bool ret;
> > +
> > +	spin_lock_irqsave(&hugetlb_lock, flags);
> > +	folio = page_folio(page);
> > +	if (!folio_test_huge_poison(folio)) {
> > +		ret = PageHWPoison(page);
> > +		goto unlock;
> > +	}
> > +
> > +	ret = precise_page_poisoned(folio, page);
> > +unlock:
> > +	spin_unlock_irqrestore(&hugetlb_lock, flags);
> > +	return ret;
> > +}
> > +
> 
> I ended up with the same question as sashiko - i think this behavior
> implies we must hold a reference on the page, otherwise the folio can
> be invalid and all these accesses are unsafe.
> 
> But that must be the existing behavior for poison checks like this, so
> this is at least no worse. Not sure it's worth addressing.

Let me just paste Sashiko's comment in here so we preserve it in the
lore archives and so we're definitely talking about the same thing:

> This is a pre-existing issue, but does calling page_folio()
> here without holding a reference to the page risk a panic during
> lockless PFN scanning?  If a monitoring tool reads /proc/kpageflags or
> /proc/kcore, pfn_to_online_page() retrieves the page without acquiring
> a reference. If the page is concurrently freed and reallocated for
> driver use, compound_info (which aliases lru.next) could be modified.
> Could this cause page_folio() to misidentify the page as a tail page
> and return an invalid folio pointer, leading to an out-of-bounds memory
> read when folio_test_huge_poison() accesses folio->page.page_type?
> While the hugetlb_lock is held here, can it stabilize unreferenced
> pages that might have already been repurposed into non-hugetlb pages?

Sashiko is mistaken (... and fair enough, I suspect you aren't the only
human who's confused by this either)

It's quite right that we can observe a page in literally any state since
we do not hold a refcount.  But it is forbidden to use bit 0 of lru.next
for any purpose other than indicating "this is a tail page":

       /*
         * Five words (20/40 bytes) are available in this union.
         * WARNING: bit 0 of the first word is used for PageTail(). That
         * means the other users of this union MUST NOT use the bit to
         * avoid collision and false-positive PageTail().
         */

That's been the rule since 2015 with commit 1d798ca3f164

So the pointer we get back from page_folio() must have been a folio _at
some point_.  It may not be a folio now.  It may be a folio, but not one
that contains this page.  But it's not a wild pointer, and treating it
as if it's a folio won't cause any harm (as long as we're really careful).

Specifically, we call:

> +	if (!folio_test_huge_poison(folio)) {

and all that does is access folio->page.page_type aka mapcount.  So if
the pointer we have is not a current folio, it'll just return false and
we'll check PageHWPoison.

So the only case this can return 'true' is if the folio was hugetlb
at that exact point.  And we've got the hugetlb lock, so it can't stop
being a hugetlb folio.  At this point it's safe to walk the list.

That's my reasoning, and I think Sashiko has explained enough of its
reasoning to be fairly sure Sashiko is wrong about this.  But hey,
you're not Sashiko.  Maybe you've found a gap in my logic.

  reply	other threads:[~2026-08-04 21:22 UTC|newest]

Thread overview: 46+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-31 20:07 [PATCH v8 00/15] Use generic_file_read_iter() in hugetlbfs Matthew Wilcox (Oracle)
2026-07-31 20:07 ` [PATCH v8 01/15] memory-failure: Fix hardware poison check in unpoison_memory() again Matthew Wilcox (Oracle)
2026-07-31 20:07 ` [PATCH v8 02/15] memory-failure: Prevent hugetlb freeing during unpoisoning Matthew Wilcox (Oracle)
2026-08-04  6:40   ` jane.chu
2026-08-04 15:35     ` Matthew Wilcox
2026-08-04 21:22       ` jane.chu
2026-07-31 20:07 ` [PATCH v8 03/15] mm: Rename folio_contain_hwpoison_page() to folio_has_hwpoison_page() Matthew Wilcox (Oracle)
2026-07-31 20:07 ` [PATCH v8 04/15] hugetlb: Mark some function arguments as const Matthew Wilcox (Oracle)
2026-08-04  6:41   ` jane.chu
2026-07-31 20:07 ` [PATCH v8 05/15] guest_memfd: Use folio_has_hwpoisoned_page() Matthew Wilcox (Oracle)
2026-08-04  6:42   ` jane.chu
2026-07-31 20:07 ` [PATCH v8 06/15] kpageflags: Use is_page_hwpoison() to set KPF_HWPOISON Matthew Wilcox (Oracle)
2026-08-04  6:44   ` jane.chu
2026-08-04 15:46     ` Matthew Wilcox
2026-08-04 20:21       ` jane.chu
2026-08-04 16:13   ` Gregory Price
2026-07-31 20:07 ` [PATCH v8 07/15] hugetlb: Move poison to pages before clearing hugetlb page type Matthew Wilcox (Oracle)
2026-08-04  6:47   ` jane.chu
2026-07-31 20:07 ` [PATCH v8 08/15] hugetlb: Use the has_hwpoisoned flag Matthew Wilcox (Oracle)
2026-08-04  6:51   ` jane.chu
2026-08-04 16:04     ` Matthew Wilcox
2026-08-04 16:28   ` Gregory Price
2026-08-04 16:42     ` Matthew Wilcox
2026-08-04 18:43       ` Gregory Price
2026-07-31 20:07 ` [PATCH v8 09/15] mm: Remove locking mf_mutex in is_raw_hwpoison_page_in_hugepage() Matthew Wilcox (Oracle)
2026-08-04  6:56   ` jane.chu
2026-08-04 16:36   ` Gregory Price
2026-08-04 16:58     ` Matthew Wilcox
2026-08-04 18:47       ` Gregory Price
2026-08-04 20:32       ` jane.chu
2026-07-31 20:07 ` [PATCH v8 10/15] mm: Check individual hugetlb pages for poison Matthew Wilcox (Oracle)
2026-08-04  6:59   ` jane.chu
2026-08-04 19:15   ` Gregory Price
2026-08-04 21:21     ` Matthew Wilcox [this message]
2026-08-04 23:01       ` Gregory Price
2026-07-31 20:07 ` [PATCH v8 11/15] filemap: Add hwpoison handling to filemap_read() Matthew Wilcox (Oracle)
2026-07-31 20:07 ` [PATCH v8 12/15] filemap: Remove checks in mapping_set_folio_order_range() Matthew Wilcox (Oracle)
2026-08-04  7:01   ` jane.chu
2026-08-04 21:23   ` Gregory Price
2026-08-05  3:28     ` Matthew Wilcox
2026-07-31 20:07 ` [PATCH v8 13/15] hugetlb: Set mapping folio order Matthew Wilcox (Oracle)
2026-08-04  7:01   ` jane.chu
2026-07-31 20:07 ` [PATCH v8 14/15] filemap: Add support for authoritative mappings Matthew Wilcox (Oracle)
2026-08-04  7:02   ` jane.chu
2026-07-31 20:08 ` [PATCH v8 15/15] hugetlb: replace hugetlbfs_read_iter() with generic_file_read_iter() Matthew Wilcox (Oracle)
2026-08-04 21:26   ` Gregory Price

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=anJX2bjH57IHz-jX@casper.infradead.org \
    --to=willy@infradead.org \
    --cc=akpm@linux-foundation.org \
    --cc=christian@brauner.io \
    --cc=david@kernel.org \
    --cc=gourry@gourry.net \
    --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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox