From 6bcb296c42f3161e239039599df49e1bb3477bae Mon Sep 17 00:00:00 2001 From: Tony Luck Date: Sun, 1 Nov 2020 20:53:07 +0800 Subject: [PATCH 2497/2944] x86/mce: Avoid tail copy when machine check terminated a copy from user fix #31317281 commit a2f73400e4dfd13f673c6e1b4b98d180fd1e47b3 upstream Backport summary: Backport to kernel 4.19.57 to enhance MCA-R for copyin In the page fault case it is ok to see if a few more unaligned bytes can be copied from the source address. Worst case is that the page fault will be triggered again. Machine checks are more serious. Just give up at the point where the main copy loop triggered the #MC and return from the copy code as if the copy succeeded. The machine check handler will use task_work_add() to make sure that the task is sent a SIGBUS. Signed-off-by: Tony Luck Signed-off-by: Borislav Petkov Link: https://lkml.kernel.org/r/20201006210910.21062-5-tony.luck@intel.com Signed-off-by: Youquan Song Signed-off-by: Wetp Zhang Reviewed-by: Artie Ding --- arch/x86/lib/copy_user_64.S | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/arch/x86/lib/copy_user_64.S b/arch/x86/lib/copy_user_64.S index f3af7df..a6536f8 100644 --- a/arch/x86/lib/copy_user_64.S +++ b/arch/x86/lib/copy_user_64.S @@ -221,6 +221,7 @@ EXPORT_SYMBOL(copy_user_enhanced_fast_string) * Try to copy last bytes and clear the rest if needed. * Since protection fault in copy_from/to_user is not a normal situation, * it is not necessary to optimize tail handling. + * Don't try to copy the tail if machine check happened * * Input: * rdi destination @@ -233,12 +234,25 @@ EXPORT_SYMBOL(copy_user_enhanced_fast_string) ALIGN; copy_user_handle_tail: movl %edx,%ecx + cmp $18,%eax /* check if X86_TRAP_MC */ + je 3f 1: rep movsb 2: mov %ecx,%eax ASM_CLAC ret - _ASM_EXTABLE_UA(1b, 2b) + /* + * Return zero to pretend that this copy succeeded. This + * is counter-intuitive, but needed to prevent the code + * in lib/iov_iter.c from retrying and running back into + * the poison cache line again. The machine check handler + * will ensure that a SIGBUS is sent to the task. + */ +3: xorl %eax,%eax + ASM_CLAC + ret + + _ASM_EXTABLE_CPY(1b, 2b) ENDPROC(copy_user_handle_tail) /* -- 1.8.3.1