Re: [PATCH v3] mm/memory-failure: set PG_hwpoison of a non-hugetlb page under hugetlb_lock

From: Miaohe Lin

Date: Mon Nov 09 2026 - 06:33:37 EST


On 2026/11/7 6:39, Andrew Morton wrote:
> On Fri, 06 Nov 2026 11:09:50 -0500 Mani Tofigh via B4 Relay <devnull+mt4022.columbia.edu@xxxxxxxxxx> wrote:
>
>> From: Mani Tofigh <mt4022@xxxxxxxxxxxx>
>>
>> memory_failure() checks under hugetlb_lock that the page isn't part of
>> a hugetlb folio and sets PG_hwpoison only after dropping the lock. The
>> page can become a tail page of a new hugetlb folio in the meantime.
>> With hugetlb_free_vmemmap=on its struct page then lives in the tail
>> page that all such folios in the zone share, so the flag lands on tail
>> pages of every one of them:
>>
>> Task A (memory_failure) Task B (nr_hugepages write)
>> get_huge_page_for_hwpoison()
>> /* P not hugetlb */
>> alloc_fresh_hugetlb_folio()
>> /* P becomes a tail page */
>> hugetlb_vmemmap_optimize_folio()
>> /* P's struct page now in
>> the shared tail page */
>> TestSetPageHWPoison(P)
>>
>> The error on P itself is ignored, while healthy pages of other folios
>> stay marked and are never reused once their folio is freed. After
>> freeing the pool, /proc/kpageflags shows them as hwpoisoned.
>>
>> This is the allocation side of the race that commit 32c877191e02
>> ("hugetlb: do not clear hugetlb dtor until allocating vmemmap") fixed
>> for freeing.
>>
>> Set the hugetlb flag of a new folio under hugetlb_lock and set
>> PG_hwpoison of a non-hugetlb page inside the locked check, so that the
>> vmemmap can't be optimized in between. The retry path clears it under
>> the same lock, unless the page has become part of a hugetlb folio in
>> the meantime and its struct page isn't in the first vmemmap page of the
>> folio, which HVO doesn't share. The retry then knows the flag is its
>> own. With the fix, no healthy page gets marked anymore.
>>
>> This bug was identified and confirmed with the help of a deterministic
>> hypervisor currently under development. The C reproducer below however
>> hits it within about 35s.
>
> Thanks.
>
> So as I understand it, if a single 4k page turns bad at just the right
> time, we can mark a lot of healthy 4k pages as bad (hence lost until
> reboot) while the bad 4k page remains in use? But that race is very
> unlikely?
>
>> Fixes: f41f2ed43ca5 ("mm: hugetlb: free the vmemmap pages associated with each HugeTLB page")
>> Cc: stable@xxxxxxxxxxxxxxx
>
> I'm hoping we don't need to backport, because the race is so unlikely,
> the consequences aren't world-ending and the backporting story is
> messy.
>
> But I don't think I'll get my hope, because the consequences of this
> race are worse in older kernels:
>
> In 6.6.162 HVO maps shared tail metadata read-only, so the misplaced
> PG_hwpoison write can cause an oops.
>
> Also in 6.6.162 memory_failure() still has a ClearPageHWPoison(p) in
> its PageCompound retry block so with HVO enabled and
> CONFIG_TRANSPARENT_HUGEPAGE=n, its compound retry can still reach
> read-only tail metadata.
>
> Miaohe, wdyt?

Yes, even though the probability is very low, it can still happen, and
it may cause the kernel to crash or something like that, so I guess we
have to backport it.

Thanks both.
.


>
> .
>