提交 8a9bc410 编写于 作者: T Tong Tiangen 提交者: Ma Wupeng

arm64: add support for machine check error safe

hulk inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I5GB28
CVE: NA

-------------------------------

During the processing of arm64 kernel hardware memory errors(do_sea()), if
the errors is consumed in the kernel, the current processing is panic.
However, it is not optimal.

Take uaccess for example, if the uaccess operation fails due to memory
error, only the user process will be affected, kill the user process
and isolate the user page with hardware memory errors is a better choice.

This patch only enable machine error check framework, it add exception
fixup before kernel panic in do_sea() and only limit the consumption of
hardware memory errors in kernel mode triggered by user mode processes.
If fixup successful, panic can be avoided.
Signed-off-by: NTong Tiangen <tongtiangen@huawei.com>
上级 bab26fe2
...@@ -11,6 +11,7 @@ config ARM64 ...@@ -11,6 +11,7 @@ config ARM64
select ACPI_PPTT if ACPI select ACPI_PPTT if ACPI
select ARCH_HAS_DEBUG_WX select ARCH_HAS_DEBUG_WX
select ARCH_BINFMT_ELF_STATE select ARCH_BINFMT_ELF_STATE
select ARCH_HAS_COPY_MC if ACPI_APEI_GHES
select ARCH_HAS_DEBUG_VIRTUAL select ARCH_HAS_DEBUG_VIRTUAL
select ARCH_HAS_DEBUG_VM_PGTABLE select ARCH_HAS_DEBUG_VM_PGTABLE
select ARCH_HAS_DEVMEM_IS_ALLOWED select ARCH_HAS_DEVMEM_IS_ALLOWED
...@@ -22,6 +23,7 @@ config ARM64 ...@@ -22,6 +23,7 @@ config ARM64
select ARCH_HAS_GIGANTIC_PAGE select ARCH_HAS_GIGANTIC_PAGE
select ARCH_HAS_KCOV select ARCH_HAS_KCOV
select ARCH_HAS_KEEPINITRD select ARCH_HAS_KEEPINITRD
select ARCH_HAS_MC_EXTABLE if ARCH_HAS_COPY_MC
select ARCH_HAS_MEMBARRIER_SYNC_CORE select ARCH_HAS_MEMBARRIER_SYNC_CORE
select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
select ARCH_HAS_PTE_DEVMAP select ARCH_HAS_PTE_DEVMAP
......
...@@ -44,4 +44,5 @@ int arm64_bpf_fixup_exception(const struct exception_table_entry *ex, ...@@ -44,4 +44,5 @@ int arm64_bpf_fixup_exception(const struct exception_table_entry *ex,
#endif /* !CONFIG_BPF_JIT */ #endif /* !CONFIG_BPF_JIT */
extern int fixup_exception(struct pt_regs *regs); extern int fixup_exception(struct pt_regs *regs);
extern int fixup_exception_mc(struct pt_regs *regs);
#endif #endif
...@@ -20,3 +20,15 @@ int fixup_exception(struct pt_regs *regs) ...@@ -20,3 +20,15 @@ int fixup_exception(struct pt_regs *regs)
regs->pc = (unsigned long)&fixup->fixup + fixup->fixup; regs->pc = (unsigned long)&fixup->fixup + fixup->fixup;
return 1; return 1;
} }
int fixup_exception_mc(struct pt_regs *regs)
{
const struct exception_table_entry *fixup;
fixup = search_mc_exception_tables(instruction_pointer(regs));
if (!fixup)
return 0;
regs->pc = (unsigned long)&fixup->fixup + fixup->fixup;
return 1;
}
...@@ -634,6 +634,31 @@ static int do_bad(unsigned long addr, unsigned int esr, struct pt_regs *regs) ...@@ -634,6 +634,31 @@ static int do_bad(unsigned long addr, unsigned int esr, struct pt_regs *regs)
return 1; /* "fault" */ return 1; /* "fault" */
} }
static bool arm64_do_kernel_sea(void __user *addr, unsigned int esr,
struct pt_regs *regs, int sig, int code)
{
if (!IS_ENABLED(CONFIG_ARCH_HAS_COPY_MC))
return false;
if (user_mode(regs))
return false;
if (apei_claim_sea(regs) < 0)
return false;
if (!fixup_exception_mc(regs))
return false;
if (current->flags & PF_KTHREAD)
return true;
set_thread_esr(0, esr);
arm64_force_sig_fault(sig, code, addr,
"Uncorrected memory error on access to user memory\n");
return true;
}
static int do_sea(unsigned long addr, unsigned int esr, struct pt_regs *regs) static int do_sea(unsigned long addr, unsigned int esr, struct pt_regs *regs)
{ {
const struct fault_info *inf; const struct fault_info *inf;
...@@ -653,6 +678,8 @@ static int do_sea(unsigned long addr, unsigned int esr, struct pt_regs *regs) ...@@ -653,6 +678,8 @@ static int do_sea(unsigned long addr, unsigned int esr, struct pt_regs *regs)
siaddr = NULL; siaddr = NULL;
else else
siaddr = (void __user *)addr; siaddr = (void __user *)addr;
if (!arm64_do_kernel_sea(siaddr, esr, regs, inf->sig, inf->code))
arm64_notify_die(inf->name, regs, inf->sig, inf->code, siaddr, esr); arm64_notify_die(inf->name, regs, inf->sig, inf->code, siaddr, esr);
return 0; return 0;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册