If a uaccess in USER_DS mode faults on a kernel address, it is
reasonably like to be an exploitable bug.  Make it more obvious in
testing and make it harder to exploit in practice by letting it
OOPS.

Signed-off-by: Andy Lutomirski <l...@kernel.org>
---
 arch/x86/mm/extable.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c
index c1933471fce7..818cc7ffef79 100644
--- a/arch/x86/mm/extable.c
+++ b/arch/x86/mm/extable.c
@@ -29,6 +29,8 @@ EXPORT_SYMBOL(ex_handler_default);
 static bool uaccess_fault_okay(int trapnr, unsigned long error_code,
                               unsigned long extra)
 {
+       bool is_user_ds;
+
        /*
         * For uaccess, only page faults should be fixed up.  I can't see
         * any exploit mitigation value in OOPSing on other types of faults,
@@ -42,6 +44,22 @@ static bool uaccess_fault_okay(int trapnr, unsigned long 
error_code,
                      trapnr))
                return true;  /* no good reason to OOPS. */
 
+       /*
+        * This is a page fault, so extra contains the address we failed to
+        * access.
+        */
+       is_user_ds = segment_eq(get_fs(), USER_DS);
+
+       if (unlikely(is_user_ds && extra >= TASK_SIZE_MAX)) {
+               /*
+                * We accessed out out-of-range address with USER_DS.  Force
+                * an OOPS: if we just warned, then an attacker could trigger
+                * this repeatedly to learn the kernel memory layout.
+                */
+               pr_crit("BUG: uaccess to bad address 0x%lx (missing access_ok 
check)\n", extra);
+               return false;
+       }
+
        return true;
 }
 
-- 
2.5.5

Reply via email to