[PATCH v2 1/2] mm/memory-failure: don't unpoison a leaked raw_hwp_unreliable folio

From: Mani Tofigh via B4 Relay

Date: Tue Nov 03 2026 - 16:02:33 EST


From: Mani Tofigh <mt4022@xxxxxxxxxxxx>

If memory_failure() can't save the raw error page of a hugetlb folio,
it marks the folio raw_hwp_unreliable and unpoison_memory() refuses to
unpoison it, since we don't know which subpages are poisoned. Once the
folio is freed, __update_and_free_hugetlb_folio() leaks it on purpose.
If its hugetlb flag is cleared by then, e.g., without vmemmap
optimization, unpoison_memory() doesn't see a hugetlb folio anymore.
It treats the leaked folio as a normal page and clears PG_hwpoison on
its head, while the poisoned subpages are still unknown.

The leaked folio is still a large folio and raw_hwp_unreliable stays set
in folio->private. We now check it on any large folio before taking the
page, so unpoison_memory() refuses the folio whether it's still hugetlb
or not. With the fix, it returns -EBUSY for the leaked folio as it did
before the folio was freed.

Fixes: ac5fcde0a96a ("mm, hwpoison: make unpoison aware of raw error info in hwpoisoned hugepage")
Reported-by: Miaohe Lin <linmiaohe@xxxxxxxxxx>
Closes: https://lore.kernel.org/all/ae6058ae-3703-a1d5-d82f-4102b46f227b@xxxxxxxxxx/
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Mani Tofigh <mt4022@xxxxxxxxxxxx>
---
mm/memory-failure.c | 9 +++++++++
1 file changed, 9 insertions(+)

diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index b215312f261b..496eacbefdf2 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -2809,6 +2809,15 @@ int unpoison_memory(unsigned long pfn)
goto unlock_mutex;
}

+ /*
+ * A hugetlb folio without reliable raw error info is leaked once it
+ * is freed, and its hugetlb flag may be cleared by then. Check the
+ * flag in folio->private, which stays set on the leaked folio.
+ */
+ if (folio_test_large(folio) &&
+ folio_test_hugetlb_raw_hwp_unreliable(folio))
+ goto unlock_mutex;
+
ghp = get_hwpoison_page(p, MF_UNPOISON);
if (!ghp) {
if (folio_test_hugetlb(folio)) {

--
2.53.0