Merge branch 'siginfo-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebieder...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 30 Jan 2018 22:18:52 +0000 (14:18 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 30 Jan 2018 22:18:52 +0000 (14:18 -0800)
Pull siginfo cleanups from Eric Biederman:
 "Long ago when 2.4 was just a testing release copy_siginfo_to_user was
  made to copy individual fields to userspace, possibly for efficiency
  and to ensure initialized values were not copied to userspace.

  Unfortunately the design was complex, it's assumptions unstated, and
  humans are fallible and so while it worked much of the time that
  design failed to ensure unitialized memory is not copied to userspace.

  This set of changes is part of a new design to clean up siginfo and
  simplify things, and hopefully make the siginfo handling robust enough
  that a simple inspection of the code can be made to ensure we don't
  copy any unitializied fields to userspace.

  The design is to unify struct siginfo and struct compat_siginfo into a
  single definition that is shared between all architectures so that
  anyone adding to the set of information shared with struct siginfo can
  see the whole picture. Hopefully ensuring all future si_code
  assignments are arch independent.

  The design is to unify copy_siginfo_to_user32 and
  copy_siginfo_from_user32 so that those function are complete and cope
  with all of the different cases documented in signinfo_layout. I don't
  think there was a single implementation of either of those functions
  that was complete and correct before my changes unified them.

  The design is to introduce a series of helpers including
  force_siginfo_fault that take the values that are needed in struct
  siginfo and build the siginfo structure for their callers. Ensuring
  struct siginfo is built correctly.

  The remaining work for 4.17 (unless someone thinks it is post -rc1
  material) is to push usage of those helpers down into the
  architectures so that architecture specific code will not need to deal
  with the fiddly work of intializing struct siginfo, and then when
  struct siginfo is guaranteed to be fully initialized change copy
  siginfo_to_user into a simple wrapper around copy_to_user.

  Further there is work in progress on the issues that have been
  documented requires arch specific knowledge to sort out.

  The changes below fix or at least document all of the issues that have
  been found with siginfo generation. Then proceed to unify struct
  siginfo the 32 bit helpers that copy siginfo to and from userspace,
  and generally clean up anything that is not arch specific with regards
  to siginfo generation.

  It is a lot but with the unification you can of siginfo you can
  already see the code reduction in the kernel"

* 'siginfo-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace: (45 commits)
  signal/memory-failure: Use force_sig_mceerr and send_sig_mceerr
  mm/memory_failure: Remove unused trapno from memory_failure
  signal/ptrace: Add force_sig_ptrace_errno_trap and use it where needed
  signal/powerpc: Remove unnecessary signal_code parameter of do_send_trap
  signal: Helpers for faults with specialized siginfo layouts
  signal: Add send_sig_fault and force_sig_fault
  signal: Replace memset(info,...) with clear_siginfo for clarity
  signal: Don't use structure initializers for struct siginfo
  signal/arm64: Better isolate the COMPAT_TASK portion of ptrace_hbptriggered
  ptrace: Use copy_siginfo in setsiginfo and getsiginfo
  signal: Unify and correct copy_siginfo_to_user32
  signal: Remove the code to clear siginfo before calling copy_siginfo_from_user32
  signal: Unify and correct copy_siginfo_from_user32
  signal/blackfin: Remove pointless UID16_SIGINFO_COMPAT_NEEDED
  signal/blackfin: Move the blackfin specific si_codes to asm-generic/siginfo.h
  signal/tile: Move the tile specific si_codes to asm-generic/siginfo.h
  signal/frv: Move the frv specific si_codes to asm-generic/siginfo.h
  signal/ia64: Move the ia64 specific si_codes to asm-generic/siginfo.h
  signal/powerpc: Remove redefinition of NSIGTRAP on powerpc
  signal: Move addr_lsb into the _sigfault union for clarity
  ...

1  2 
arch/arc/kernel/traps.c
arch/arm64/kernel/fpsimd.c
arch/arm64/kernel/signal32.c
arch/arm64/mm/fault.c
arch/powerpc/kernel/mce.c
arch/x86/kernel/cpu/mcheck/mce.c
drivers/acpi/apei/ghes.c

diff --combined arch/arc/kernel/traps.c
index 133a4dae41fe7d73b07b0d2365a899b943bc4779,c7206789e9ced175c3c57f2c42e4a3f2da7b8035..b123558bf0bb4ee83ce78f3a814be78b9356de2a
@@@ -65,12 -65,14 +65,14 @@@ unhandled_exception(const char *str, st
  #define DO_ERROR_INFO(signr, str, name, sicode) \
  int name(unsigned long address, struct pt_regs *regs) \
  {                                             \
-       siginfo_t info = {                      \
-               .si_signo = signr,              \
-               .si_errno = 0,                  \
-               .si_code  = sicode,             \
-               .si_addr = (void __user *)address,      \
-       };                                      \
+       siginfo_t info;                         \
+                                               \
+       clear_siginfo(&info);                   \
+       info.si_signo = signr;                  \
+       info.si_errno = 0;                      \
+       info.si_code  = sicode;                 \
+       info.si_addr = (void __user *)address;  \
+                                               \
        return unhandled_exception(str, regs, &info);\
  }
  
@@@ -83,7 -85,6 +85,7 @@@ DO_ERROR_INFO(SIGILL, "Illegal Insn (o
  DO_ERROR_INFO(SIGBUS, "Invalid Mem Access", __weak do_memory_error, BUS_ADRERR)
  DO_ERROR_INFO(SIGTRAP, "Breakpoint Set", trap_is_brkpt, TRAP_BRKPT)
  DO_ERROR_INFO(SIGBUS, "Misaligned Access", do_misaligned_error, BUS_ADRALN)
 +DO_ERROR_INFO(SIGSEGV, "gcc generated __builtin_trap", do_trap5_error, 0)
  
  /*
   * Entry Point for Misaligned Data access Exception, for emulating in software
@@@ -116,8 -117,6 +118,8 @@@ void do_machine_check_fault(unsigned lo
   * Thus TRAP_S <n> can be used for specific purpose
   *  -1 used for software breakpointing (gdb)
   *  -2 used by kprobes
 + *  -5 __builtin_trap() generated by gcc (2018.03 onwards) for toggle such as
 + *     -fno-isolate-erroneous-paths-dereference
   */
  void do_non_swi_trap(unsigned long address, struct pt_regs *regs)
  {
                kgdb_trap(regs);
                break;
  
 +      case 5:
 +              do_trap5_error(address, regs);
 +              break;
        default:
                break;
        }
@@@ -161,11 -157,3 +163,11 @@@ void do_insterror_or_kprobe(unsigned lo
  
        insterror_is_error(address, regs);
  }
 +
 +/*
 + * abort() call generated by older gcc for __builtin_trap()
 + */
 +void abort(void)
 +{
 +      __asm__ __volatile__("trap_s  5\n");
 +}
index 55fb544072f603d0ce59a5f0d0832dd8f0e15368,ad0edf31e24773d4c111e64dcd64f9149c55432b..e7226c4c7493d90e6320e64dc0d141bb947a035c
@@@ -867,7 -867,7 +867,7 @@@ asmlinkage void do_fpsimd_acc(unsigned 
  asmlinkage void do_fpsimd_exc(unsigned int esr, struct pt_regs *regs)
  {
        siginfo_t info;
-       unsigned int si_code = 0;
+       unsigned int si_code = FPE_FIXME;
  
        if (esr & FPEXC_IOF)
                si_code = FPE_FLTINV;
@@@ -1036,14 -1036,14 +1036,14 @@@ void fpsimd_restore_current_state(void
   * flag that indicates that the FPSIMD register contents are the most recent
   * FPSIMD state of 'current'
   */
 -void fpsimd_update_current_state(struct fpsimd_state *state)
 +void fpsimd_update_current_state(struct user_fpsimd_state const *state)
  {
        if (!system_supports_fpsimd())
                return;
  
        local_bh_disable();
  
 -      current->thread.fpsimd_state.user_fpsimd = state->user_fpsimd;
 +      current->thread.fpsimd_state.user_fpsimd = *state;
        if (system_supports_sve() && test_thread_flag(TIF_SVE))
                fpsimd_to_sve(current);
  
index a124140c0926c51ab7fd2d9f9dd3ba3e099f6090,cbc4edd1b1ebb6d766b0e0d4ccaedc796c8d9360..79feb861929b93828a619ff0df941d01aa02b270
@@@ -125,86 -125,6 +125,6 @@@ static inline int get_sigset_t(sigset_
        return 0;
  }
  
- int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
- {
-       int err;
-       if (!access_ok(VERIFY_WRITE, to, sizeof(*to)))
-               return -EFAULT;
-       /* If you change siginfo_t structure, please be sure
-        * this code is fixed accordingly.
-        * It should never copy any pad contained in the structure
-        * to avoid security leaks, but must copy the generic
-        * 3 ints plus the relevant union member.
-        * This routine must convert siginfo from 64bit to 32bit as well
-        * at the same time.
-        */
-       err = __put_user(from->si_signo, &to->si_signo);
-       err |= __put_user(from->si_errno, &to->si_errno);
-       err |= __put_user(from->si_code, &to->si_code);
-       if (from->si_code < 0)
-               err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad,
-                                     SI_PAD_SIZE);
-       else switch (siginfo_layout(from->si_signo, from->si_code)) {
-       case SIL_KILL:
-               err |= __put_user(from->si_pid, &to->si_pid);
-               err |= __put_user(from->si_uid, &to->si_uid);
-               break;
-       case SIL_TIMER:
-                err |= __put_user(from->si_tid, &to->si_tid);
-                err |= __put_user(from->si_overrun, &to->si_overrun);
-                err |= __put_user(from->si_int, &to->si_int);
-               break;
-       case SIL_POLL:
-               err |= __put_user(from->si_band, &to->si_band);
-               err |= __put_user(from->si_fd, &to->si_fd);
-               break;
-       case SIL_FAULT:
-               err |= __put_user((compat_uptr_t)(unsigned long)from->si_addr,
-                                 &to->si_addr);
- #ifdef BUS_MCEERR_AO
-               /*
-                * Other callers might not initialize the si_lsb field,
-                * so check explicitly for the right codes here.
-                */
-               if (from->si_signo == SIGBUS &&
-                   (from->si_code == BUS_MCEERR_AR || from->si_code == BUS_MCEERR_AO))
-                       err |= __put_user(from->si_addr_lsb, &to->si_addr_lsb);
- #endif
-               break;
-       case SIL_CHLD:
-               err |= __put_user(from->si_pid, &to->si_pid);
-               err |= __put_user(from->si_uid, &to->si_uid);
-               err |= __put_user(from->si_status, &to->si_status);
-               err |= __put_user(from->si_utime, &to->si_utime);
-               err |= __put_user(from->si_stime, &to->si_stime);
-               break;
-       case SIL_RT:
-               err |= __put_user(from->si_pid, &to->si_pid);
-               err |= __put_user(from->si_uid, &to->si_uid);
-               err |= __put_user(from->si_int, &to->si_int);
-               break;
-       case SIL_SYS:
-               err |= __put_user((compat_uptr_t)(unsigned long)
-                               from->si_call_addr, &to->si_call_addr);
-               err |= __put_user(from->si_syscall, &to->si_syscall);
-               err |= __put_user(from->si_arch, &to->si_arch);
-               break;
-       }
-       return err;
- }
- int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
- {
-       if (copy_from_user(to, from, __ARCH_SI_PREAMBLE_SIZE) ||
-           copy_from_user(to->_sifields._pad,
-                          from->_sifields._pad, SI_PAD_SIZE))
-               return -EFAULT;
-       return 0;
- }
  /*
   * VFP save/restore code.
   *
@@@ -228,8 -148,7 +148,8 @@@ union __fpsimd_vreg 
  
  static int compat_preserve_vfp_context(struct compat_vfp_sigframe __user *frame)
  {
 -      struct fpsimd_state *fpsimd = &current->thread.fpsimd_state;
 +      struct user_fpsimd_state const *fpsimd =
 +              &current->thread.fpsimd_state.user_fpsimd;
        compat_ulong_t magic = VFP_MAGIC;
        compat_ulong_t size = VFP_STORAGE_SIZE;
        compat_ulong_t fpscr, fpexc;
  
  static int compat_restore_vfp_context(struct compat_vfp_sigframe __user *frame)
  {
 -      struct fpsimd_state fpsimd;
 +      struct user_fpsimd_state fpsimd;
        compat_ulong_t magic = VFP_MAGIC;
        compat_ulong_t size = VFP_STORAGE_SIZE;
        compat_ulong_t fpscr;
diff --combined arch/arm64/mm/fault.c
index 6c30cf92f49268e3abcf35161dd0eccbf4e68131,abe200587334978521493b470942a65d012ed87d..ce441d29e7f6ed797b74228ff6284a6224baef9b
@@@ -596,7 -596,7 +596,7 @@@ static int do_sea(unsigned long addr, u
  
        info.si_signo = SIGBUS;
        info.si_errno = 0;
-       info.si_code  = 0;
+       info.si_code  = BUS_FIXME;
        if (esr & ESR_ELx_FnV)
                info.si_addr = NULL;
        else
  }
  
  static const struct fault_info fault_info[] = {
-       { do_bad,               SIGBUS,  0,             "ttbr address size fault"       },
-       { do_bad,               SIGBUS,  0,             "level 1 address size fault"    },
-       { do_bad,               SIGBUS,  0,             "level 2 address size fault"    },
-       { do_bad,               SIGBUS,  0,             "level 3 address size fault"    },
+       { do_bad,               SIGBUS,  BUS_FIXME,     "ttbr address size fault"       },
+       { do_bad,               SIGBUS,  BUS_FIXME,     "level 1 address size fault"    },
+       { do_bad,               SIGBUS,  BUS_FIXME,     "level 2 address size fault"    },
+       { do_bad,               SIGBUS,  BUS_FIXME,     "level 3 address size fault"    },
        { do_translation_fault, SIGSEGV, SEGV_MAPERR,   "level 0 translation fault"     },
        { do_translation_fault, SIGSEGV, SEGV_MAPERR,   "level 1 translation fault"     },
        { do_translation_fault, SIGSEGV, SEGV_MAPERR,   "level 2 translation fault"     },
        { do_translation_fault, SIGSEGV, SEGV_MAPERR,   "level 3 translation fault"     },
-       { do_bad,               SIGBUS,  0,             "unknown 8"                     },
+       { do_bad,               SIGBUS,  BUS_FIXME,     "unknown 8"                     },
        { do_page_fault,        SIGSEGV, SEGV_ACCERR,   "level 1 access flag fault"     },
        { do_page_fault,        SIGSEGV, SEGV_ACCERR,   "level 2 access flag fault"     },
        { do_page_fault,        SIGSEGV, SEGV_ACCERR,   "level 3 access flag fault"     },
-       { do_bad,               SIGBUS,  0,             "unknown 12"                    },
+       { do_bad,               SIGBUS,  BUS_FIXME,     "unknown 12"                    },
        { do_page_fault,        SIGSEGV, SEGV_ACCERR,   "level 1 permission fault"      },
        { do_page_fault,        SIGSEGV, SEGV_ACCERR,   "level 2 permission fault"      },
        { do_page_fault,        SIGSEGV, SEGV_ACCERR,   "level 3 permission fault"      },
-       { do_sea,               SIGBUS,  0,             "synchronous external abort"    },
-       { do_bad,               SIGBUS,  0,             "unknown 17"                    },
-       { do_bad,               SIGBUS,  0,             "unknown 18"                    },
-       { do_bad,               SIGBUS,  0,             "unknown 19"                    },
-       { do_sea,               SIGBUS,  0,             "level 0 (translation table walk)"      },
-       { do_sea,               SIGBUS,  0,             "level 1 (translation table walk)"      },
-       { do_sea,               SIGBUS,  0,             "level 2 (translation table walk)"      },
-       { do_sea,               SIGBUS,  0,             "level 3 (translation table walk)"      },
-       { do_sea,               SIGBUS,  0,             "synchronous parity or ECC error" },    // Reserved when RAS is implemented
-       { do_bad,               SIGBUS,  0,             "unknown 25"                    },
-       { do_bad,               SIGBUS,  0,             "unknown 26"                    },
-       { do_bad,               SIGBUS,  0,             "unknown 27"                    },
-       { do_sea,               SIGBUS,  0,             "level 0 synchronous parity error (translation table walk)"     },      // Reserved when RAS is implemented
-       { do_sea,               SIGBUS,  0,             "level 1 synchronous parity error (translation table walk)"     },      // Reserved when RAS is implemented
-       { do_sea,               SIGBUS,  0,             "level 2 synchronous parity error (translation table walk)"     },      // Reserved when RAS is implemented
-       { do_sea,               SIGBUS,  0,             "level 3 synchronous parity error (translation table walk)"     },      // Reserved when RAS is implemented
-       { do_bad,               SIGBUS,  0,             "unknown 32"                    },
+       { do_sea,               SIGBUS,  BUS_FIXME,     "synchronous external abort"    },
+       { do_bad,               SIGBUS,  BUS_FIXME,     "unknown 17"                    },
+       { do_bad,               SIGBUS,  BUS_FIXME,     "unknown 18"                    },
+       { do_bad,               SIGBUS,  BUS_FIXME,     "unknown 19"                    },
+       { do_sea,               SIGBUS,  BUS_FIXME,     "level 0 (translation table walk)"      },
+       { do_sea,               SIGBUS,  BUS_FIXME,     "level 1 (translation table walk)"      },
+       { do_sea,               SIGBUS,  BUS_FIXME,     "level 2 (translation table walk)"      },
+       { do_sea,               SIGBUS,  BUS_FIXME,     "level 3 (translation table walk)"      },
+       { do_sea,               SIGBUS,  BUS_FIXME,     "synchronous parity or ECC error" },    // Reserved when RAS is implemented
+       { do_bad,               SIGBUS,  BUS_FIXME,     "unknown 25"                    },
+       { do_bad,               SIGBUS,  BUS_FIXME,     "unknown 26"                    },
+       { do_bad,               SIGBUS,  BUS_FIXME,     "unknown 27"                    },
+       { do_sea,               SIGBUS,  BUS_FIXME,     "level 0 synchronous parity error (translation table walk)"     },      // Reserved when RAS is implemented
+       { do_sea,               SIGBUS,  BUS_FIXME,     "level 1 synchronous parity error (translation table walk)"     },      // Reserved when RAS is implemented
+       { do_sea,               SIGBUS,  BUS_FIXME,     "level 2 synchronous parity error (translation table walk)"     },      // Reserved when RAS is implemented
+       { do_sea,               SIGBUS,  BUS_FIXME,     "level 3 synchronous parity error (translation table walk)"     },      // Reserved when RAS is implemented
+       { do_bad,               SIGBUS,  BUS_FIXME,     "unknown 32"                    },
        { do_alignment_fault,   SIGBUS,  BUS_ADRALN,    "alignment fault"               },
-       { do_bad,               SIGBUS,  0,             "unknown 34"                    },
-       { do_bad,               SIGBUS,  0,             "unknown 35"                    },
-       { do_bad,               SIGBUS,  0,             "unknown 36"                    },
-       { do_bad,               SIGBUS,  0,             "unknown 37"                    },
-       { do_bad,               SIGBUS,  0,             "unknown 38"                    },
-       { do_bad,               SIGBUS,  0,             "unknown 39"                    },
-       { do_bad,               SIGBUS,  0,             "unknown 40"                    },
-       { do_bad,               SIGBUS,  0,             "unknown 41"                    },
-       { do_bad,               SIGBUS,  0,             "unknown 42"                    },
-       { do_bad,               SIGBUS,  0,             "unknown 43"                    },
-       { do_bad,               SIGBUS,  0,             "unknown 44"                    },
-       { do_bad,               SIGBUS,  0,             "unknown 45"                    },
-       { do_bad,               SIGBUS,  0,             "unknown 46"                    },
-       { do_bad,               SIGBUS,  0,             "unknown 47"                    },
-       { do_bad,               SIGBUS,  0,             "TLB conflict abort"            },
-       { do_bad,               SIGBUS,  0,             "Unsupported atomic hardware update fault"      },
-       { do_bad,               SIGBUS,  0,             "unknown 50"                    },
-       { do_bad,               SIGBUS,  0,             "unknown 51"                    },
-       { do_bad,               SIGBUS,  0,             "implementation fault (lockdown abort)" },
-       { do_bad,               SIGBUS,  0,             "implementation fault (unsupported exclusive)" },
-       { do_bad,               SIGBUS,  0,             "unknown 54"                    },
-       { do_bad,               SIGBUS,  0,             "unknown 55"                    },
-       { do_bad,               SIGBUS,  0,             "unknown 56"                    },
-       { do_bad,               SIGBUS,  0,             "unknown 57"                    },
-       { do_bad,               SIGBUS,  0,             "unknown 58"                    },
-       { do_bad,               SIGBUS,  0,             "unknown 59"                    },
-       { do_bad,               SIGBUS,  0,             "unknown 60"                    },
-       { do_bad,               SIGBUS,  0,             "section domain fault"          },
-       { do_bad,               SIGBUS,  0,             "page domain fault"             },
-       { do_bad,               SIGBUS,  0,             "unknown 63"                    },
+       { do_bad,               SIGBUS,  BUS_FIXME,     "unknown 34"                    },
+       { do_bad,               SIGBUS,  BUS_FIXME,     "unknown 35"                    },
+       { do_bad,               SIGBUS,  BUS_FIXME,     "unknown 36"                    },
+       { do_bad,               SIGBUS,  BUS_FIXME,     "unknown 37"                    },
+       { do_bad,               SIGBUS,  BUS_FIXME,     "unknown 38"                    },
+       { do_bad,               SIGBUS,  BUS_FIXME,     "unknown 39"                    },
+       { do_bad,               SIGBUS,  BUS_FIXME,     "unknown 40"                    },
+       { do_bad,               SIGBUS,  BUS_FIXME,     "unknown 41"                    },
+       { do_bad,               SIGBUS,  BUS_FIXME,     "unknown 42"                    },
+       { do_bad,               SIGBUS,  BUS_FIXME,     "unknown 43"                    },
+       { do_bad,               SIGBUS,  BUS_FIXME,     "unknown 44"                    },
+       { do_bad,               SIGBUS,  BUS_FIXME,     "unknown 45"                    },
+       { do_bad,               SIGBUS,  BUS_FIXME,     "unknown 46"                    },
+       { do_bad,               SIGBUS,  BUS_FIXME,     "unknown 47"                    },
+       { do_bad,               SIGBUS,  BUS_FIXME,     "TLB conflict abort"            },
+       { do_bad,               SIGBUS,  BUS_FIXME,     "Unsupported atomic hardware update fault"      },
+       { do_bad,               SIGBUS,  BUS_FIXME,     "unknown 50"                    },
+       { do_bad,               SIGBUS,  BUS_FIXME,     "unknown 51"                    },
+       { do_bad,               SIGBUS,  BUS_FIXME,     "implementation fault (lockdown abort)" },
+       { do_bad,               SIGBUS,  BUS_FIXME,     "implementation fault (unsupported exclusive)" },
+       { do_bad,               SIGBUS,  BUS_FIXME,     "unknown 54"                    },
+       { do_bad,               SIGBUS,  BUS_FIXME,     "unknown 55"                    },
+       { do_bad,               SIGBUS,  BUS_FIXME,     "unknown 56"                    },
+       { do_bad,               SIGBUS,  BUS_FIXME,     "unknown 57"                    },
+       { do_bad,               SIGBUS,  BUS_FIXME,     "unknown 58"                    },
+       { do_bad,               SIGBUS,  BUS_FIXME,     "unknown 59"                    },
+       { do_bad,               SIGBUS,  BUS_FIXME,     "unknown 60"                    },
+       { do_bad,               SIGBUS,  BUS_FIXME,     "section domain fault"          },
+       { do_bad,               SIGBUS,  BUS_FIXME,     "page domain fault"             },
+       { do_bad,               SIGBUS,  BUS_FIXME,     "unknown 63"                    },
  };
  
  int handle_guest_sea(phys_addr_t addr, unsigned int esr)
@@@ -707,23 -707,6 +707,23 @@@ asmlinkage void __exception do_mem_abor
        arm64_notify_die("", regs, &info, esr);
  }
  
 +asmlinkage void __exception do_el0_ia_bp_hardening(unsigned long addr,
 +                                                 unsigned int esr,
 +                                                 struct pt_regs *regs)
 +{
 +      /*
 +       * We've taken an instruction abort from userspace and not yet
 +       * re-enabled IRQs. If the address is a kernel address, apply
 +       * BP hardening prior to enabling IRQs and pre-emption.
 +       */
 +      if (addr > TASK_SIZE)
 +              arm64_apply_bp_hardening();
 +
 +      local_irq_enable();
 +      do_mem_abort(addr, esr, regs);
 +}
 +
 +
  asmlinkage void __exception do_sp_pc_abort(unsigned long addr,
                                           unsigned int esr,
                                           struct pt_regs *regs)
@@@ -756,11 -739,11 +756,11 @@@ static struct fault_info __refdata debu
        { do_bad,       SIGTRAP,        TRAP_HWBKPT,    "hardware breakpoint"   },
        { do_bad,       SIGTRAP,        TRAP_HWBKPT,    "hardware single-step"  },
        { do_bad,       SIGTRAP,        TRAP_HWBKPT,    "hardware watchpoint"   },
-       { do_bad,       SIGBUS,         0,              "unknown 3"             },
+       { do_bad,       SIGBUS,         BUS_FIXME,      "unknown 3"             },
        { do_bad,       SIGTRAP,        TRAP_BRKPT,     "aarch32 BKPT"          },
-       { do_bad,       SIGTRAP,        0,              "aarch32 vector catch"  },
+       { do_bad,       SIGTRAP,        TRAP_FIXME,     "aarch32 vector catch"  },
        { early_brk64,  SIGTRAP,        TRAP_BRKPT,     "aarch64 BRK"           },
-       { do_bad,       SIGBUS,         0,              "unknown 7"             },
+       { do_bad,       SIGBUS,         BUS_FIXME,      "unknown 7"             },
  };
  
  void __init hook_debug_fault_code(int nr,
index 742e4658c5dc1d4ec2df625eb82ea34473f24e39,742e4658c5dc1d4ec2df625eb82ea34473f24e39..71e8a1b8c86ed851800098a6258d8a55fd5b3e8c
@@@ -273,7 -273,7 +273,7 @@@ static void machine_process_ue_event(st
  
                                pfn = evt->u.ue_error.physical_address >>
                                        PAGE_SHIFT;
--                              memory_failure(pfn, SIGBUS, 0);
++                              memory_failure(pfn, 0);
                        } else
                                pr_warn("Failed to identify bad address from "
                                        "where the uncorrectable error (UE) "
index c3655e0fc15677ebb09d1a4ef3debb60b2649c1f,3b7319e25168a00c316153c4ffeed63bbcaa4904..ba1f9555fbc5dca8bb0ea5e2c0fc7870ae2b7663
@@@ -503,8 -503,10 +503,8 @@@ static int mce_usable_address(struct mc
  bool mce_is_memory_error(struct mce *m)
  {
        if (m->cpuvendor == X86_VENDOR_AMD) {
 -              /* ErrCodeExt[20:16] */
 -              u8 xec = (m->status >> 16) & 0x1f;
 +              return amd_mce_is_memory_error(m);
  
 -              return (xec == 0x0 || xec == 0x8);
        } else if (m->cpuvendor == X86_VENDOR_INTEL) {
                /*
                 * Intel SDM Volume 3B - 15.9.2 Compound Error Codes
  }
  EXPORT_SYMBOL_GPL(mce_is_memory_error);
  
 +static bool mce_is_correctable(struct mce *m)
 +{
 +      if (m->cpuvendor == X86_VENDOR_AMD && m->status & MCI_STATUS_DEFERRED)
 +              return false;
 +
 +      if (m->status & MCI_STATUS_UC)
 +              return false;
 +
 +      return true;
 +}
 +
  static bool cec_add_mce(struct mce *m)
  {
        if (!m)
  
        /* We eat only correctable DRAM errors with usable addresses. */
        if (mce_is_memory_error(m) &&
 -          !(m->status & MCI_STATUS_UC) &&
 +          mce_is_correctable(m)  &&
            mce_usable_address(m))
                if (!cec_add_elem(m->addr >> PAGE_SHIFT))
                        return true;
@@@ -591,7 -582,7 +591,7 @@@ static int srao_decode_notifier(struct 
  
        if (mce_usable_address(mce) && (mce->severity == MCE_AO_SEVERITY)) {
                pfn = mce->addr >> PAGE_SHIFT;
-               memory_failure(pfn, MCE_VECTOR, 0);
+               memory_failure(pfn, 0);
        }
  
        return NOTIFY_OK;
@@@ -1055,7 -1046,7 +1055,7 @@@ static int do_memory_failure(struct mc
        pr_err("Uncorrected hardware memory error in user-access at %llx", m->addr);
        if (!(m->mcgstatus & MCG_STATUS_RIPV))
                flags |= MF_MUST_KILL;
-       ret = memory_failure(m->addr >> PAGE_SHIFT, MCE_VECTOR, flags);
+       ret = memory_failure(m->addr >> PAGE_SHIFT, flags);
        if (ret)
                pr_err("Memory error not recovered");
        return ret;
@@@ -1334,7 -1325,7 +1334,7 @@@ out_ist
  EXPORT_SYMBOL_GPL(do_machine_check);
  
  #ifndef CONFIG_MEMORY_FAILURE
- int memory_failure(unsigned long pfn, int vector, int flags)
+ int memory_failure(unsigned long pfn, int flags)
  {
        /* mce_severity() should not hand us an ACTION_REQUIRED error */
        BUG_ON(flags & MF_ACTION_REQUIRED);
@@@ -1794,11 -1785,6 +1794,11 @@@ static void unexpected_machine_check(st
  void (*machine_check_vector)(struct pt_regs *, long error_code) =
                                                unexpected_machine_check;
  
 +dotraplinkage void do_mce(struct pt_regs *regs, long error_code)
 +{
 +      machine_check_vector(regs, error_code);
 +}
 +
  /*
   * Called for each booted CPU to set up machine checks.
   * Must be called with preempt off:
diff --combined drivers/acpi/apei/ghes.c
index 16c4a10b75069e3f1d8ad6a2ed34c5af69f49437,bb5f9c643e0e04115ddf97c9fa80ca44892893a8..1efefe919555f7e70aef1e0fea59c94390c21497
@@@ -410,55 -410,10 +410,55 @@@ static void ghes_handle_memory_failure(
                flags = 0;
  
        if (flags != -1)
-               memory_failure_queue(pfn, 0, flags);
+               memory_failure_queue(pfn, flags);
  #endif
  }
  
 +/*
 + * PCIe AER errors need to be sent to the AER driver for reporting and
 + * recovery. The GHES severities map to the following AER severities and
 + * require the following handling:
 + *
 + * GHES_SEV_CORRECTABLE -> AER_CORRECTABLE
 + *     These need to be reported by the AER driver but no recovery is
 + *     necessary.
 + * GHES_SEV_RECOVERABLE -> AER_NONFATAL
 + * GHES_SEV_RECOVERABLE && CPER_SEC_RESET -> AER_FATAL
 + *     These both need to be reported and recovered from by the AER driver.
 + * GHES_SEV_PANIC does not make it to this handling since the kernel must
 + *     panic.
 + */
 +static void ghes_handle_aer(struct acpi_hest_generic_data *gdata)
 +{
 +#ifdef CONFIG_ACPI_APEI_PCIEAER
 +      struct cper_sec_pcie *pcie_err = acpi_hest_get_payload(gdata);
 +
 +      if (pcie_err->validation_bits & CPER_PCIE_VALID_DEVICE_ID &&
 +          pcie_err->validation_bits & CPER_PCIE_VALID_AER_INFO) {
 +              unsigned int devfn;
 +              int aer_severity;
 +
 +              devfn = PCI_DEVFN(pcie_err->device_id.device,
 +                                pcie_err->device_id.function);
 +              aer_severity = cper_severity_to_aer(gdata->error_severity);
 +
 +              /*
 +               * If firmware reset the component to contain
 +               * the error, we must reinitialize it before
 +               * use, so treat it as a fatal AER error.
 +               */
 +              if (gdata->flags & CPER_SEC_RESET)
 +                      aer_severity = AER_FATAL;
 +
 +              aer_recover_queue(pcie_err->device_id.segment,
 +                                pcie_err->device_id.bus,
 +                                devfn, aer_severity,
 +                                (struct aer_capability_regs *)
 +                                pcie_err->aer_info);
 +      }
 +#endif
 +}
 +
  static void ghes_do_proc(struct ghes *ghes,
                         const struct acpi_hest_generic_status *estatus)
  {
                        arch_apei_report_mem_error(sev, mem_err);
                        ghes_handle_memory_failure(gdata, sev);
                }
 -#ifdef CONFIG_ACPI_APEI_PCIEAER
                else if (guid_equal(sec_type, &CPER_SEC_PCIE)) {
 -                      struct cper_sec_pcie *pcie_err = acpi_hest_get_payload(gdata);
 -
 -                      if (sev == GHES_SEV_RECOVERABLE &&
 -                          sec_sev == GHES_SEV_RECOVERABLE &&
 -                          pcie_err->validation_bits & CPER_PCIE_VALID_DEVICE_ID &&
 -                          pcie_err->validation_bits & CPER_PCIE_VALID_AER_INFO) {
 -                              unsigned int devfn;
 -                              int aer_severity;
 -
 -                              devfn = PCI_DEVFN(pcie_err->device_id.device,
 -                                                pcie_err->device_id.function);
 -                              aer_severity = cper_severity_to_aer(gdata->error_severity);
 -
 -                              /*
 -                               * If firmware reset the component to contain
 -                               * the error, we must reinitialize it before
 -                               * use, so treat it as a fatal AER error.
 -                               */
 -                              if (gdata->flags & CPER_SEC_RESET)
 -                                      aer_severity = AER_FATAL;
 -
 -                              aer_recover_queue(pcie_err->device_id.segment,
 -                                                pcie_err->device_id.bus,
 -                                                devfn, aer_severity,
 -                                                (struct aer_capability_regs *)
 -                                                pcie_err->aer_info);
 -                      }
 -
 +                      ghes_handle_aer(gdata);
                }
 -#endif
                else if (guid_equal(sec_type, &CPER_SEC_PROC_ARM)) {
                        struct cper_sec_proc_arm *err = acpi_hest_get_payload(gdata);
  
@@@ -886,6 -870,7 +886,6 @@@ static void ghes_print_queued_estatus(v
        struct ghes_estatus_node *estatus_node;
        struct acpi_hest_generic *generic;
        struct acpi_hest_generic_status *estatus;
 -      u32 len, node_len;
  
        llnode = llist_del_all(&ghes_estatus_llist);
        /*
                estatus_node = llist_entry(llnode, struct ghes_estatus_node,
                                           llnode);
                estatus = GHES_ESTATUS_FROM_NODE(estatus_node);
 -              len = cper_estatus_len(estatus);
 -              node_len = GHES_ESTATUS_NODE_LEN(len);
                generic = estatus_node->generic;
                ghes_print_estatus(NULL, generic, estatus);
                llnode = llnode->next;