* [PATCH] mm/highmem: refuse to copy hwpoisoned folios in the !copy_mc fallbacks
@ 2026-10-26 2:57 Yuanhe Shu
2026-10-26 9:55 ` David Hildenbrand (Arm)
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: Yuanhe Shu @ 2026-10-26 2:57 UTC (permalink / raw)
To: akpm, david
Cc: Huang, Ying, Kaitao Cheng, vbabka, ljs, liam, rppt, surenb,
mhocko, linmiaohe, nao.horiguchi, ziy, wangkefeng.wang,
tujinjiang, mgorman, chengkaitao, muchun.song, linux-mm,
linux-kernel, xiangzao
Where copy_mc_to_kernel is defined, copy_mc_user_highpage() and
copy_mc_highpage() stop at a hardware error during the copy, report
the not-copied bytes and queue the source page for memory_failure().
The !copy_mc fallbacks return 0 after a plain copy instead. With
PG_hwpoison set while the data stays readable - software-injected
poison (MADV_HWPOISON, the debugfs corrupt-pfn injector) or a
transient hardware error - there is no fault to recover from: the
copy completes, the destination folio carries no poison marker, and
the poison is consumed silently, the same poison consumption
commit 841a8bfcbad9 ("mm: prevent poison consumption when splitting
THP") refused to risk on the split path.
Check the source folio with folio_contain_hwpoisoned_page() in both
fallbacks and return PAGE_SIZE, the not-copied-bytes convention of
the real copy_mc paths, so the callers take their existing error
paths: the COW and fork paths fail with -EHWPOISON, KSM and
khugepaged abort, and folio_mc_copy() propagates to the migration
core, where this composes with the separate migration-side checks.
On archs with copy_mc this code does not compile.
The check runs after the copy: a check before it would leave open
the window between itself and the copy. A flag set before or during
the copy is caught, whatever state the data is in. A late software
injection cannot have corrupted the completed copy, and a synchronous
hardware error takes an arch without copy_mc down at the access; the
residue no flag check, before or after, can catch is corruption whose
hardware report lands after the last check. Closing that would need
architecture support, as discussed.
The fallbacks do not queue memory_failure() on refusal: the flag is
already set, and memory failure either knows about the page or has
abandoned it.
Suggested-by: "Huang, Ying" <ying.huang@linux.alibaba.com>
Suggested-by: Kaitao Cheng <kaitao.cheng@linux.dev>
Assisted-by: LLM
Signed-off-by: Yuanhe Shu <xiangzao@linux.alibaba.com>
Link: https://lore.kernel.org/r/877bjowf9i.fsf@DESKTOP-5N7EMDA/
---
include/linux/highmem.h | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/include/linux/highmem.h b/include/linux/highmem.h
index d7aac9de1c8a..f90f0c6204a4 100644
--- a/include/linux/highmem.h
+++ b/include/linux/highmem.h
@@ -474,12 +474,21 @@ static inline int copy_mc_user_highpage(struct page *to, struct page *from,
unsigned long vaddr, struct vm_area_struct *vma)
{
copy_user_highpage(to, from, vaddr, vma);
+ /*
+ * The flag can be set while the copy runs, so check after it;
+ * a flag landing later can no longer have corrupted this copy.
+ */
+ if (folio_contain_hwpoisoned_page(page_folio(from)))
+ return PAGE_SIZE;
return 0;
}
static inline int copy_mc_highpage(struct page *to, struct page *from)
{
copy_highpage(to, from);
+ /* Same reasoning as in copy_mc_user_highpage(). */
+ if (folio_contain_hwpoisoned_page(page_folio(from)))
+ return PAGE_SIZE;
return 0;
}
#endif
--
2.43.7
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] mm/highmem: refuse to copy hwpoisoned folios in the !copy_mc fallbacks
2026-10-26 2:57 [PATCH] mm/highmem: refuse to copy hwpoisoned folios in the !copy_mc fallbacks Yuanhe Shu
@ 2026-10-26 9:55 ` David Hildenbrand (Arm)
2026-10-26 11:21 ` Huang, Ying
2026-10-26 12:09 ` Garg, Shivank
2 siblings, 0 replies; 5+ messages in thread
From: David Hildenbrand (Arm) @ 2026-10-26 9:55 UTC (permalink / raw)
To: Yuanhe Shu, akpm
Cc: Huang, Ying, Kaitao Cheng, vbabka, ljs, liam, rppt, surenb,
mhocko, linmiaohe, nao.horiguchi, ziy, wangkefeng.wang,
tujinjiang, mgorman, chengkaitao, muchun.song, linux-mm,
linux-kernel
On 10/26/26 03:57, Yuanhe Shu wrote:
> Where copy_mc_to_kernel is defined, copy_mc_user_highpage() and
> copy_mc_highpage() stop at a hardware error during the copy, report
> the not-copied bytes and queue the source page for memory_failure().
> The !copy_mc fallbacks return 0 after a plain copy instead. With
> PG_hwpoison set while the data stays readable - software-injected
> poison (MADV_HWPOISON, the debugfs corrupt-pfn injector) or a
> transient hardware error - there is no fault to recover from: the
> copy completes, the destination folio carries no poison marker, and
> the poison is consumed silently, the same poison consumption
> commit 841a8bfcbad9 ("mm: prevent poison consumption when splitting
> THP") refused to risk on the split path.
>
> Check the source folio with folio_contain_hwpoisoned_page() in both
> fallbacks and return PAGE_SIZE, the not-copied-bytes convention of
> the real copy_mc paths, so the callers take their existing error
> paths: the COW and fork paths fail with -EHWPOISON, KSM and
> khugepaged abort, and folio_mc_copy() propagates to the migration
> core, where this composes with the separate migration-side checks.
> On archs with copy_mc this code does not compile.
>
> The check runs after the copy: a check before it would leave open
> the window between itself and the copy. A flag set before or during
> the copy is caught, whatever state the data is in. A late software
> injection cannot have corrupted the completed copy, and a synchronous
> hardware error takes an arch without copy_mc down at the access; the
> residue no flag check, before or after, can catch is corruption whose
> hardware report lands after the last check. Closing that would need
> architecture support, as discussed.
>
> The fallbacks do not queue memory_failure() on refusal: the flag is
> already set, and memory failure either knows about the page or has
> abandoned it.
There must be a way to shorten this description.
>
> Suggested-by: "Huang, Ying" <ying.huang@linux.alibaba.com>
> Suggested-by: Kaitao Cheng <kaitao.cheng@linux.dev>
> Assisted-by: LLM
> Signed-off-by: Yuanhe Shu <xiangzao@linux.alibaba.com>
> Link: https://lore.kernel.org/r/877bjowf9i.fsf@DESKTOP-5N7EMDA/
> ---
> include/linux/highmem.h | 9 +++++++++
> 1 file changed, 9 insertions(+)
>
> diff --git a/include/linux/highmem.h b/include/linux/highmem.h
> index d7aac9de1c8a..f90f0c6204a4 100644
> --- a/include/linux/highmem.h
> +++ b/include/linux/highmem.h
> @@ -474,12 +474,21 @@ static inline int copy_mc_user_highpage(struct page *to, struct page *from,
> unsigned long vaddr, struct vm_area_struct *vma)
> {
> copy_user_highpage(to, from, vaddr, vma);
> + /*
> + * The flag can be set while the copy runs, so check after it;
> + * a flag landing later can no longer have corrupted this copy.
> + */
> + if (folio_contain_hwpoisoned_page(page_folio(from)))
> + return PAGE_SIZE;
> return 0;
> }
>
> static inline int copy_mc_highpage(struct page *to, struct page *from)
> {
> copy_highpage(to, from);
> + /* Same reasoning as in copy_mc_user_highpage(). */
> + if (folio_contain_hwpoisoned_page(page_folio(from)))
> + return PAGE_SIZE;
> return 0;
> }
> #endif
As I said in the other thread, how is copying data that was already poisoned
(and might trigger another MCE) reasonable?
I can understand why you would want to maintain the second check (although I do
wonder about memory barriers ... hmmm).
--
Cheers,
David
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] mm/highmem: refuse to copy hwpoisoned folios in the !copy_mc fallbacks
2026-10-26 2:57 [PATCH] mm/highmem: refuse to copy hwpoisoned folios in the !copy_mc fallbacks Yuanhe Shu
2026-10-26 9:55 ` David Hildenbrand (Arm)
@ 2026-10-26 11:21 ` Huang, Ying
2026-10-26 12:17 ` Garg, Shivank
2026-10-26 12:09 ` Garg, Shivank
2 siblings, 1 reply; 5+ messages in thread
From: Huang, Ying @ 2026-10-26 11:21 UTC (permalink / raw)
To: Yuanhe Shu
Cc: akpm, david, Kaitao Cheng, vbabka, ljs, liam, rppt, surenb,
mhocko, linmiaohe, nao.horiguchi, ziy, wangkefeng.wang,
tujinjiang, mgorman, chengkaitao, muchun.song, linux-mm,
linux-kernel
Yuanhe Shu <xiangzao@linux.alibaba.com> writes:
> Where copy_mc_to_kernel is defined, copy_mc_user_highpage() and
> copy_mc_highpage() stop at a hardware error during the copy, report
> the not-copied bytes and queue the source page for memory_failure().
> The !copy_mc fallbacks return 0 after a plain copy instead. With
> PG_hwpoison set while the data stays readable - software-injected
> poison (MADV_HWPOISON, the debugfs corrupt-pfn injector) or a
> transient hardware error - there is no fault to recover from: the
> copy completes, the destination folio carries no poison marker, and
> the poison is consumed silently, the same poison consumption
> commit 841a8bfcbad9 ("mm: prevent poison consumption when splitting
> THP") refused to risk on the split path.
As far as I know, software-injected poison is used for debugging only ,
so I don't think it's that important. Hardware poison state in DDR is
sticky; that is, even a transient hardware error will cause a permanent
hardware poison state until a reset.
Therefore, the primary value of this patch should be to reduce machine
checks (and panics) during memory copies. If so, we should place the
check code before copying.
> Check the source folio with folio_contain_hwpoisoned_page() in both
> fallbacks and return PAGE_SIZE, the not-copied-bytes convention of
> the real copy_mc paths, so the callers take their existing error
> paths: the COW and fork paths fail with -EHWPOISON, KSM and
> khugepaged abort, and folio_mc_copy() propagates to the migration
> core, where this composes with the separate migration-side checks.
> On archs with copy_mc this code does not compile.
>
> The check runs after the copy: a check before it would leave open
> the window between itself and the copy. A flag set before or during
> the copy is caught, whatever state the data is in. A late software
> injection cannot have corrupted the completed copy, and a synchronous
> hardware error takes an arch without copy_mc down at the access; the
> residue no flag check, before or after, can catch is corruption whose
> hardware report lands after the last check. Closing that would need
> architecture support, as discussed.
>
> The fallbacks do not queue memory_failure() on refusal: the flag is
> already set, and memory failure either knows about the page or has
> abandoned it.
>
> Suggested-by: "Huang, Ying" <ying.huang@linux.alibaba.com>
> Suggested-by: Kaitao Cheng <kaitao.cheng@linux.dev>
> Assisted-by: LLM
> Signed-off-by: Yuanhe Shu <xiangzao@linux.alibaba.com>
> Link: https://lore.kernel.org/r/877bjowf9i.fsf@DESKTOP-5N7EMDA/
> ---
> include/linux/highmem.h | 9 +++++++++
> 1 file changed, 9 insertions(+)
>
> diff --git a/include/linux/highmem.h b/include/linux/highmem.h
> index d7aac9de1c8a..f90f0c6204a4 100644
> --- a/include/linux/highmem.h
> +++ b/include/linux/highmem.h
> @@ -474,12 +474,21 @@ static inline int copy_mc_user_highpage(struct page *to, struct page *from,
> unsigned long vaddr, struct vm_area_struct *vma)
> {
> copy_user_highpage(to, from, vaddr, vma);
> + /*
> + * The flag can be set while the copy runs, so check after it;
> + * a flag landing later can no longer have corrupted this copy.
> + */
> + if (folio_contain_hwpoisoned_page(page_folio(from)))
> + return PAGE_SIZE;
Why not just use PageHWPoison()?
> return 0;
> }
>
> static inline int copy_mc_highpage(struct page *to, struct page *from)
> {
> copy_highpage(to, from);
> + /* Same reasoning as in copy_mc_user_highpage(). */
> + if (folio_contain_hwpoisoned_page(page_folio(from)))
> + return PAGE_SIZE;
> return 0;
> }
> #endif
---
Best Regards,
Huang, Ying
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] mm/highmem: refuse to copy hwpoisoned folios in the !copy_mc fallbacks
2026-10-26 2:57 [PATCH] mm/highmem: refuse to copy hwpoisoned folios in the !copy_mc fallbacks Yuanhe Shu
2026-10-26 9:55 ` David Hildenbrand (Arm)
2026-10-26 11:21 ` Huang, Ying
@ 2026-10-26 12:09 ` Garg, Shivank
2 siblings, 0 replies; 5+ messages in thread
From: Garg, Shivank @ 2026-10-26 12:09 UTC (permalink / raw)
To: david, xiangzao, akpm
Cc: rppt, wangkefeng.wang, chengkaitao, vbabka, ying.huang,
linux-kernel, surenb, linux-mm, muchun.song, ziy, nao.horiguchi,
liam, linmiaohe, mhocko, ljs, tujinjiang, kaitao.cheng, mgorman
On Mon, 2026-10-26 at 10:57 +0800, Yuanhe Shu wrote:
> Where copy_mc_to_kernel is defined, copy_mc_user_highpage() and
> copy_mc_highpage() stop at a hardware error during the copy, report
> the not-copied bytes and queue the source page for memory_failure().
> The !copy_mc fallbacks return 0 after a plain copy instead. With
> PG_hwpoison set while the data stays readable - software-injected
> poison (MADV_HWPOISON, the debugfs corrupt-pfn injector) or a
> transient hardware error - there is no fault to recover from: the
> copy completes, the destination folio carries no poison marker, and
> the poison is consumed silently, the same poison consumption
> commit 841a8bfcbad9 ("mm: prevent poison consumption when splitting
> THP") refused to risk on the split path.
>
> Check the source folio with folio_contain_hwpoisoned_page() in both
> fallbacks and return PAGE_SIZE, the not-copied-bytes convention of
> the real copy_mc paths, so the callers take their existing error
> paths: the COW and fork paths fail with -EHWPOISON, KSM and
> khugepaged abort, and folio_mc_copy() propagates to the migration
> core, where this composes with the separate migration-side checks.
> On archs with copy_mc this code does not compile.
>
> The check runs after the copy: a check before it would leave open
> the window between itself and the copy. A flag set before or during
> the copy is caught, whatever state the data is in. A late software
> injection cannot have corrupted the completed copy, and a synchronous
> hardware error takes an arch without copy_mc down at the access; the
> residue no flag check, before or after, can catch is corruption whose
> hardware report lands after the last check. Closing that would need
> architecture support, as discussed.
>
> The fallbacks do not queue memory_failure() on refusal: the flag is
> already set, and memory failure either knows about the page or has
> abandoned it.
>
> Suggested-by: "Huang, Ying" <ying.huang@linux.alibaba.com>
> Suggested-by: Kaitao Cheng <kaitao.cheng@linux.dev>
> Assisted-by: LLM
> Signed-off-by: Yuanhe Shu <xiangzao@linux.alibaba.com>
> Link: https://lore.kernel.org/r/877bjowf9i.fsf@DESKTOP-5N7EMDA/
> ---
> include/linux/highmem.h | 9 +++++++++
> 1 file changed, 9 insertions(+)
>
> diff --git a/include/linux/highmem.h b/include/linux/highmem.h
> index d7aac9de1c8a..f90f0c6204a4 100644
> --- a/include/linux/highmem.h
> +++ b/include/linux/highmem.h
> @@ -474,12 +474,21 @@ static inline int copy_mc_user_highpage(struct page *to, struct page *from,
> unsigned long vaddr, struct vm_area_struct *vma)
> {
> copy_user_highpage(to, from, vaddr, vma);
> + /*
> + * The flag can be set while the copy runs, so check after it;
> + * a flag landing later can no longer have corrupted this copy.
> + */
> + if (folio_contain_hwpoisoned_page(page_folio(from)))
> + return PAGE_SIZE;
> return 0;
> }
>
> static inline int copy_mc_highpage(struct page *to, struct page *from)
> {
> copy_highpage(to, from);
> + /* Same reasoning as in copy_mc_user_highpage(). */
> + if (folio_contain_hwpoisoned_page(page_folio(from)))
> + return PAGE_SIZE;
> return 0;
> }
> #endif
Should we use is_page_hwpoison() instead? It looks simpler and more
reliable. memory_failure() sets the page flag first and the folio flag
later, so there is a race when folio check can say "okay" but page flag
check says "poisoned".
Thanks,
Shivank
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] mm/highmem: refuse to copy hwpoisoned folios in the !copy_mc fallbacks
2026-10-26 11:21 ` Huang, Ying
@ 2026-10-26 12:17 ` Garg, Shivank
0 siblings, 0 replies; 5+ messages in thread
From: Garg, Shivank @ 2026-10-26 12:17 UTC (permalink / raw)
To: xiangzao, ying.huang
Cc: rppt, wangkefeng.wang, chengkaitao, vbabka, david, akpm,
linux-kernel, surenb, linux-mm, muchun.song, ziy, nao.horiguchi,
liam, linmiaohe, mhocko, kaitao.cheng, tujinjiang, mgorman, ljs
On Mon, 2026-10-26 at 19:21 +0800, Huang, Ying wrote:
> Yuanhe Shu <xiangzao@linux.alibaba.com> writes:
>
> > Where copy_mc_to_kernel is defined, copy_mc_user_highpage() and
> > copy_mc_highpage() stop at a hardware error during the copy, report
> > the not-copied bytes and queue the source page for memory_failure().
> > The !copy_mc fallbacks return 0 after a plain copy instead. With
> > PG_hwpoison set while the data stays readable - software-injected
> > poison (MADV_HWPOISON, the debugfs corrupt-pfn injector) or a
> > transient hardware error - there is no fault to recover from: the
> > copy completes, the destination folio carries no poison marker, and
> > the poison is consumed silently, the same poison consumption
> > commit 841a8bfcbad9 ("mm: prevent poison consumption when splitting
> > THP") refused to risk on the split path.
>
> As far as I know, software-injected poison is used for debugging only ,
> so I don't think it's that important. Hardware poison state in DDR is
> sticky; that is, even a transient hardware error will cause a permanent
> hardware poison state until a reset.
>
> Therefore, the primary value of this patch should be to reduce machine
> checks (and panics) during memory copies. If so, we should place the
> check code before copying.
>
> > Check the source folio with folio_contain_hwpoisoned_page() in both
> > fallbacks and return PAGE_SIZE, the not-copied-bytes convention of
> > the real copy_mc paths, so the callers take their existing error
> > paths: the COW and fork paths fail with -EHWPOISON, KSM and
> > khugepaged abort, and folio_mc_copy() propagates to the migration
> > core, where this composes with the separate migration-side checks.
> > On archs with copy_mc this code does not compile.
> >
> > The check runs after the copy: a check before it would leave open
> > the window between itself and the copy. A flag set before or during
> > the copy is caught, whatever state the data is in. A late software
> > injection cannot have corrupted the completed copy, and a synchronous
> > hardware error takes an arch without copy_mc down at the access; the
> > residue no flag check, before or after, can catch is corruption whose
> > hardware report lands after the last check. Closing that would need
> > architecture support, as discussed.
> >
> > The fallbacks do not queue memory_failure() on refusal: the flag is
> > already set, and memory failure either knows about the page or has
> > abandoned it.
> >
> > Suggested-by: "Huang, Ying" <ying.huang@linux.alibaba.com>
> > Suggested-by: Kaitao Cheng <kaitao.cheng@linux.dev>
> > Assisted-by: LLM
> > Signed-off-by: Yuanhe Shu <xiangzao@linux.alibaba.com>
> > Link: https://lore.kernel.org/r/877bjowf9i.fsf@DESKTOP-5N7EMDA/
> > ---
> > include/linux/highmem.h | 9 +++++++++
> > 1 file changed, 9 insertions(+)
> >
> > diff --git a/include/linux/highmem.h b/include/linux/highmem.h
> > index d7aac9de1c8a..f90f0c6204a4 100644
> > --- a/include/linux/highmem.h
> > +++ b/include/linux/highmem.h
> > @@ -474,12 +474,21 @@ static inline int copy_mc_user_highpage(struct page *to, struct page *from,
> > unsigned long vaddr, struct vm_area_struct *vma)
> > {
> > copy_user_highpage(to, from, vaddr, vma);
> > + /*
> > + * The flag can be set while the copy runs, so check after it;
> > + * a flag landing later can no longer have corrupted this copy.
> > + */
> > + if (folio_contain_hwpoisoned_page(page_folio(from)))
> > + return PAGE_SIZE;
>
> Why not just use PageHWPoison()?
This will miss out on hugetlb folios I think. is_page_hwpoison() is more
appropriate as it covers hugetlb cases as well.
Thanks,
Shivank
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-10-26 12:17 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-26 2:57 [PATCH] mm/highmem: refuse to copy hwpoisoned folios in the !copy_mc fallbacks Yuanhe Shu
2026-10-26 9:55 ` David Hildenbrand (Arm)
2026-10-26 11:21 ` Huang, Ying
2026-10-26 12:17 ` Garg, Shivank
2026-10-26 12:09 ` Garg, Shivank
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®