Re: [RFC PATCH -next V3 3/6] arm64: add support for machine check error safe

From: Tong Tiangen
Date: Wed Apr 13 2022 - 10:41:33 EST




在 2022/4/12 21:08, Kefeng Wang 写道:
[...]
+
+bool fixup_exception_mc(struct pt_regs *regs)
+{
+    const struct exception_table_entry *ex;
+
+    ex = search_exception_tables(instruction_pointer(regs));
+    if (!ex)
+        return false;
+
+    switch (ex->type) {
+    case EX_TYPE_UACCESS_MC:
+        return ex_handler_fixup(ex, regs);
+    }
+
+    return false;
+}

The definition of EX_TYPE_UACCESS_MC is in patch4, please fix it, and if arm64 exception table

ok, will do next version.


is sorted by exception type, we could drop fixup_exception_mc(), right?

In sort_relative_table_with_data(), it seems sorted by insn and data.


diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index 77341b160aca..56b13cf8bf1d 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -695,6 +695,30 @@ static int do_bad(unsigned long far, unsigned int esr, struct pt_regs *regs)
      return 1; /* "fault" */
  }
+static bool arm64_process_kernel_sea(unsigned long 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) || !current->mm)
+        return false;
+
+    if (apei_claim_sea(regs) < 0)
+        return false;
+
+    current->thread.fault_address = 0;
+    current->thread.fault_code = esr;
+
Use set_thread_esr(0, esr) and move it after fixup_exception_mc();
+    if (!fixup_exception_mc(regs))
+        return false;
+
+    arm64_force_sig_fault(sig, code, addr,
+        "Uncorrected hardware memory error in kernel-access\n");
+
+    return true;
+}
+
  static int do_sea(unsigned long far, unsigned int esr, struct pt_regs *regs)
  {
      const struct fault_info *inf;
@@ -720,6 +744,10 @@ static int do_sea(unsigned long far, unsigned int esr, struct pt_regs *regs)
           */
          siaddr  = untagged_addr(far);
      }
+
+    if (arm64_process_kernel_sea(siaddr, esr, regs, inf->sig, inf->code))
+        return 0;
+

Rename arm64_process_kernel_sea() to arm64_do_kernel_sea()
if (!arm64_do_kernel_sea())

    arm64_notify_die();


Agreed, will do next version.

      arm64_notify_die(inf->name, regs, inf->sig, inf->code, siaddr, esr);
      return 0;
diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h
index 546179418ffa..dd952aeecdc1 100644
--- a/include/linux/uaccess.h
+++ b/include/linux/uaccess.h
@@ -174,6 +174,14 @@ copy_mc_to_kernel(void *dst, const void *src, size_t cnt)
  }
  #endif
+#ifndef copy_mc_to_user
+static inline unsigned long __must_check
+copy_mc_to_user(void *dst, const void *src, size_t cnt)
+{
Add check_object_size(cnt, src, true);  which could make HARDENED_USERCOPY works.

Agreed, will do next version.

Thanks KeFeng,
Tong.

+    return raw_copy_to_user(dst, src, cnt);
+}
+#endif
+
  static __always_inline void pagefault_disabled_inc(void)
  {
      current->pagefault_disabled++;
.