Merge tag 'char-misc-4.21-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregk...
[linux-2.6-microblaze.git] / arch / powerpc / mm / fault.c
index 1697e90..a6dcfda 100644 (file)
@@ -226,7 +226,9 @@ static int mm_fault_error(struct pt_regs *regs, unsigned long addr,
 static bool bad_kernel_fault(bool is_exec, unsigned long error_code,
                             unsigned long address)
 {
-       if (is_exec && (error_code & (DSISR_NOEXEC_OR_G | DSISR_KEYFAULT))) {
+       /* NX faults set DSISR_PROTFAULT on the 8xx, DSISR_NOEXEC_OR_G on others */
+       if (is_exec && (error_code & (DSISR_NOEXEC_OR_G | DSISR_KEYFAULT |
+                                     DSISR_PROTFAULT))) {
                printk_ratelimited(KERN_CRIT "kernel tried to execute"
                                   " exec-protected page (%lx) -"
                                   "exploit attempt? (uid: %d)\n",
@@ -341,9 +343,20 @@ static inline void cmo_account_page_fault(void)
 static inline void cmo_account_page_fault(void) { }
 #endif /* CONFIG_PPC_SMLPAR */
 
-#ifdef CONFIG_PPC_STD_MMU
-static void sanity_check_fault(bool is_write, unsigned long error_code)
+#ifdef CONFIG_PPC_BOOK3S
+static void sanity_check_fault(bool is_write, bool is_user,
+                              unsigned long error_code, unsigned long address)
 {
+       /*
+        * Userspace trying to access kernel address, we get PROTFAULT for that.
+        */
+       if (is_user && address >= TASK_SIZE) {
+               pr_crit_ratelimited("%s[%d]: User access of kernel address (%lx) - exploit attempt? (uid: %d)\n",
+                                  current->comm, current->pid, address,
+                                  from_kuid(&init_user_ns, current_uid()));
+               return;
+       }
+
        /*
         * For hash translation mode, we should never get a
         * PROTFAULT. Any update to pte to reduce access will result in us
@@ -373,12 +386,15 @@ static void sanity_check_fault(bool is_write, unsigned long error_code)
         * For radix, we can get prot fault for autonuma case, because radix
         * page table will have them marked noaccess for user.
         */
-       if (!radix_enabled() && !is_write)
-               WARN_ON_ONCE(error_code & DSISR_PROTFAULT);
+       if (radix_enabled() || is_write)
+               return;
+
+       WARN_ON_ONCE(error_code & DSISR_PROTFAULT);
 }
 #else
-static void sanity_check_fault(bool is_write, unsigned long error_code) { }
-#endif /* CONFIG_PPC_STD_MMU */
+static void sanity_check_fault(bool is_write, bool is_user,
+                              unsigned long error_code, unsigned long address) { }
+#endif /* CONFIG_PPC_BOOK3S */
 
 /*
  * Define the correct "is_write" bit in error_code based
@@ -435,7 +451,7 @@ static int __do_page_fault(struct pt_regs *regs, unsigned long address,
        }
 
        /* Additional sanity check(s) */
-       sanity_check_fault(is_write, error_code);
+       sanity_check_fault(is_write, is_user, error_code, address);
 
        /*
         * The kernel should never take an execute fault nor should it
@@ -636,21 +652,23 @@ void bad_page_fault(struct pt_regs *regs, unsigned long address, int sig)
        switch (TRAP(regs)) {
        case 0x300:
        case 0x380:
-               printk(KERN_ALERT "Unable to handle kernel paging request for "
-                       "data at address 0x%08lx\n", regs->dar);
+       case 0xe00:
+               pr_alert("BUG: %s at 0x%08lx\n",
+                        regs->dar < PAGE_SIZE ? "Kernel NULL pointer dereference" :
+                        "Unable to handle kernel data access", regs->dar);
                break;
        case 0x400:
        case 0x480:
-               printk(KERN_ALERT "Unable to handle kernel paging request for "
-                       "instruction fetch\n");
+               pr_alert("BUG: Unable to handle kernel instruction fetch%s",
+                        regs->nip < PAGE_SIZE ? " (NULL pointer?)\n" : "\n");
                break;
        case 0x600:
-               printk(KERN_ALERT "Unable to handle kernel paging request for "
-                       "unaligned access at address 0x%08lx\n", regs->dar);
+               pr_alert("BUG: Unable to handle kernel unaligned access at 0x%08lx\n",
+                        regs->dar);
                break;
        default:
-               printk(KERN_ALERT "Unable to handle kernel paging request for "
-                       "unknown fault\n");
+               pr_alert("BUG: Unable to handle unknown paging fault at 0x%08lx\n",
+                        regs->dar);
                break;
        }
        printk(KERN_ALERT "Faulting instruction address: 0x%08lx\n",