On 2022/10/22 4:01, Tony Luck wrote: > If the kernel is copying a page as the result of a copy-on-write > fault and runs into an uncorrectable error, Linux will crash because > it does not have recovery code for this case where poison is consumed > by the kernel. > > It is easy to set up a test case. Just inject an error into a private > page, fork(2), and have the child process write to the page. > > I wrapped that neatly into a test at: > > git://git.kernel.org/pub/scm/linux/kernel/git/aegl/ras-tools.git > > just enable ACPI error injection and run: > > # ./einj_mem-uc -f copy-on-write > > Add a new copy_user_highpage_mc() function that uses copy_mc_to_kernel() > on architectures where that is available (currently x86 and powerpc). > When an error is detected during the page copy, return VM_FAULT_HWPOISON > to caller of wp_page_copy(). This propagates up the call stack. Both x86 > and powerpc have code in their fault handler to deal with this code by > sending a SIGBUS to the application. > > Note that this patch avoids a system crash and signals the process that > triggered the copy-on-write action. It does not take any action for the > memory error that is still in the shared page. To handle that a call to > memory_failure() is needed. But this cannot be done from wp_page_copy() > because it holds mmap_lock(). Perhaps the architecture fault handlers > can deal with this loose end in a subsequent patch? > > On Intel/x86 this loose end will often be handled automatically because > the memory controller provides an additional notification of the h/w > poison in memory, the handler for this will call memory_failure(). This > isn't a 100% solution. If there are multiple errors, not all may be > logged in this way. > > Reviewed-by: Dan Williams <dan.j.williams@xxxxxxxxx> > Signed-off-by: Tony Luck <tony.luck@xxxxxxxxx> Thanks for your work, Tony. > > --- > Changes in V3: > Dan Williams > Rename copy_user_highpage_mc() to copy_mc_user_highpage() for > consistency with Linus' discussion on names of functions that > check for machine check. > Write complete functions for the have/have-not copy_mc_to_kernel > cases (so grep shows there are two versions) > Change __wp_page_copy_user() to return 0 for success, negative for fail > [I picked -EAGAIN for both non-EHWPOISON cases] > > Changes in V2: > Naoya Horiguchi: > 1) Use -EHWPOISON error code instead of minus one. > 2) Poison path needs also to deal with old_page > Tony Luck: > Rewrote commit message > Added some powerpc folks to Cc: list > --- > include/linux/highmem.h | 24 ++++++++++++++++++++++++ > mm/memory.c | 30 ++++++++++++++++++++---------- > 2 files changed, 44 insertions(+), 10 deletions(-) > > diff --git a/include/linux/highmem.h b/include/linux/highmem.h > index e9912da5441b..a32c64681f03 100644 > --- a/include/linux/highmem.h > +++ b/include/linux/highmem.h > @@ -319,6 +319,30 @@ static inline void copy_user_highpage(struct page *to, struct page *from, > > #endif > > +#ifdef copy_mc_to_kernel > +static inline int copy_mc_user_highpage(struct page *to, struct page *from, > + unsigned long vaddr, struct vm_area_struct *vma) > +{ > + unsigned long ret; > + char *vfrom, *vto; > + > + vfrom = kmap_local_page(from); > + vto = kmap_local_page(to); > + ret = copy_mc_to_kernel(vto, vfrom, PAGE_SIZE); In copy_user_highpage(), kmsan_unpoison_memory(page_address(to), PAGE_SIZE) is done after the copy when __HAVE_ARCH_COPY_USER_HIGHPAGE isn't defined. Do we need to do something similar here? But I'm not familiar with kmsan, so I can easy be wrong. Anyway, this patch looks good to me. Thanks. Reviewed-by: Miaohe Lin <linmiaohe@xxxxxxxxxx> Thanks, Miaohe Lin