lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <cae3c5b69836931311f3c3c3722a05e854cd9a35.1464129798.git.luto@kernel.org>
Date:	Tue, 24 May 2016 15:48:43 -0700
From:	Andy Lutomirski <luto@...nel.org>
To:	x86@...nel.org
Cc:	linux-kernel@...r.kernel.org, Borislav Petkov <bp@...en8.de>,
	Kees Cook <keescook@...omium.org>,
	Brian Gerst <brgerst@...il.com>,
	Andy Lutomirski <luto@...nel.org>
Subject: [PATCH 6/7] x86/uaccess: Don't fix up USER_DS uaccess faults to kernel addresses

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 <luto@...nel.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

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ