hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I9GCZS CVE: NA
-------------------------------
Add /proc/sys/kernel/machine_check_safe_enable. Set 1(default value) to enable machine check safe support. Set 0(default) to disable machine check safe support.
Signed-off-by: Tong Tiangen tongtiangen@huawei.com --- Documentation/admin-guide/sysctl/kernel.rst | 14 ++++++++++ arch/arm64/mm/fault.c | 30 ++++++++++++++++++++- 2 files changed, 43 insertions(+), 1 deletion(-)
diff --git a/Documentation/admin-guide/sysctl/kernel.rst b/Documentation/admin-guide/sysctl/kernel.rst index cf33de56da27..3b8953c49183 100644 --- a/Documentation/admin-guide/sysctl/kernel.rst +++ b/Documentation/admin-guide/sysctl/kernel.rst @@ -540,6 +540,20 @@ if leaking kernel pointer values to unprivileged users is a concern. When ``kptr_restrict`` is set to 2, kernel pointers printed using %pK will be replaced with 0s regardless of privileges.
+machine_check_safe (arm64 only) +================================ + +This indicates whether the Machine Check safe memory copy feature enabled +or not���which only exists on arm64 when ARCH_HAS_COPY_MC enabled. + +The value in this file determines the behaviour of the kernel when +synchronous exception from memory copy. + += =================================================================== +0 the kernel will panic immediately. +1 the kernel will recover since a memcpy-variant provided which can + safely fail when accessing to hwpoison. += ===================================================================
modprobe ======== diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index cbe5600912a9..5d040bbfd247 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -25,6 +25,7 @@ #include <linux/perf_event.h> #include <linux/preempt.h> #include <linux/hugetlb.h> +#include <linux/sysctl.h>
#include <asm/acpi.h> #include <asm/bug.h> @@ -43,6 +44,31 @@ #include <asm/tlbflush.h> #include <asm/traps.h>
+static int sysctl_machine_check_safe = IS_ENABLED(CONFIG_ARCH_HAS_COPY_MC); + +#ifdef CONFIG_ARCH_HAS_COPY_MC +static struct ctl_table machine_check_safe_sysctl_table[] = { + { + .procname = "machine_check_safe", + .data = &sysctl_machine_check_safe, + .maxlen = sizeof(sysctl_machine_check_safe), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, + .extra1 = SYSCTL_ZERO, + .extra2 = SYSCTL_ONE, + }, +}; + +static int __init machine_check_safe_sysctl_init(void) +{ + if (!register_sysctl("kernel", machine_check_safe_sysctl_table)) + return -EINVAL; + return 0; +} + +core_initcall(machine_check_safe_sysctl_init); +#endif + struct fault_info { int (*fn)(unsigned long far, unsigned long esr, struct pt_regs *regs); @@ -742,7 +768,9 @@ static bool do_apei_claim_sea(struct pt_regs *regs) if (!apei_claim_sea(regs)) return true; } else if (IS_ENABLED(CONFIG_ARCH_HAS_COPY_MC)) { - if (fixup_exception_me(regs) && !apei_claim_sea(regs)) + if (sysctl_machine_check_safe && + fixup_exception_me(regs) && + !apei_claim_sea(regs)) return true; }