diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 2ff25ad33233..f1f9e19646f5 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -610,8 +610,7 @@ static void show_ldttss(const struct desc_ptr *gdt, const char *name, u16 index) static void err_str_append(unsigned long error_code, char *buf, unsigned long mask, const char *txt) { if (error_code & mask) { - if (buf[0]) - strcat(buf, " "); + strcat(buf, " "); strcat(buf, txt); } } @@ -651,23 +650,30 @@ show_fault_oops(struct pt_regs *regs, unsigned long error_code, unsigned long ad err_txt[0] = 0; /* - * Note: length of these appended strings including the separation space and the - * zero delimiter must fit into err_txt[]. + * Note: length of these appended strings including the separation + * space and the zero delimiter must fit into err_txt[]. */ err_str_append(error_code, err_txt, X86_PF_PROT, "[PROT]" ); err_str_append(error_code, err_txt, X86_PF_WRITE, "[WRITE]"); + if ((error_code & (X86_PF_WRITE | X86_PF_INSTR)) == 0) + strcat(err_txt, " [read]"); err_str_append(error_code, err_txt, X86_PF_USER, "[USER]" ); err_str_append(error_code, err_txt, X86_PF_RSVD, "[RSVD]" ); err_str_append(error_code, err_txt, X86_PF_INSTR, "[INSTR]"); err_str_append(error_code, err_txt, X86_PF_PK, "[PK]" ); - pr_alert("#PF error: %s\n", error_code ? err_txt : "[normal kernel read fault]"); + pr_alert("#PF error: 0x%04lx%s\n", error_code, err_txt); + /* + * The X86_PF_USER bit does *not* mean the same thing as + * user_mode(regs). Make sure that the unusual cases are obvious to + * the reader. + */ if (!(error_code & X86_PF_USER) && user_mode(regs)) { struct desc_ptr idt, gdt; u16 ldtr, tr; - pr_alert("This was a system access from user code\n"); + pr_alert("NB: This was a supervisor-privileged access from user code.\n"); /* * This can happen for quite a few reasons. The more obvious @@ -692,6 +698,14 @@ show_fault_oops(struct pt_regs *regs, unsigned long error_code, unsigned long ad store_tr(tr); show_ldttss(&gdt, "TR", tr); + } else if ((error_code & X86_PF_USER) && !user_mode(regs)) { + /* + * This can happen due to WRUSS. If an ISA extension ever + * gives new instructions to do user memory access from kernel + * mode and we OOPS due to a broken fixup, we'll presumably land + * here as well. + */ + pr_alert("NB: This was a user-privileged access from kernel code.\n"); } dump_pagetable(address);