diff options
author | Kees Cook | 2013-02-07 11:44:13 -0600 |
---|---|---|
committer | Greg Kroah-Hartman | 2013-03-03 16:09:06 -0600 |
commit | f39edfbf6dbf8e29cfbafd67d93fa1e30196701c (patch) | |
tree | 3093dd34200fb1f0b4418494554bc62a0d3c796d | |
parent | 43f514598ad16af1c6dd08dd429631eaafef7849 (diff) | |
download | kernel-common-f39edfbf6dbf8e29cfbafd67d93fa1e30196701c.tar.gz kernel-common-f39edfbf6dbf8e29cfbafd67d93fa1e30196701c.tar.xz kernel-common-f39edfbf6dbf8e29cfbafd67d93fa1e30196701c.zip |
x86: Do not leak kernel page mapping locations
commit e575a86fdc50d013bf3ad3aa81d9100e8e6cc60d upstream.
Without this patch, it is trivial to determine kernel page
mappings by examining the error code reported to dmesg[1].
Instead, declare the entire kernel memory space as a violation
of a present page.
Additionally, since show_unhandled_signals is enabled by
default, switch branch hinting to the more realistic
expectation, and unobfuscate the setting of the PF_PROT bit to
improve readability.
[1] http://vulnfactory.org/blog/2013/02/06/a-linux-memory-trick/
Reported-by: Dan Rosenberg <dan.j.rosenberg@gmail.com>
Suggested-by: Brad Spengler <spender@grsecurity.net>
Signed-off-by: Kees Cook <keescook@chromium.org>
Acked-by: H. Peter Anvin <hpa@zytor.com>
Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Eric W. Biederman <ebiederm@xmission.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/20130207174413.GA12485@www.outflux.net
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: CAI Qian <caiqian@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | arch/x86/mm/fault.c | 9 |
1 files changed, 6 insertions, 3 deletions
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 2dbf6bf4c7e..3b2ad913d6c 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c | |||
@@ -720,12 +720,15 @@ __bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code, | |||
720 | if (is_errata100(regs, address)) | 720 | if (is_errata100(regs, address)) |
721 | return; | 721 | return; |
722 | 722 | ||
723 | if (unlikely(show_unhandled_signals)) | 723 | /* Kernel addresses are always protection faults: */ |
724 | if (address >= TASK_SIZE) | ||
725 | error_code |= PF_PROT; | ||
726 | |||
727 | if (likely(show_unhandled_signals)) | ||
724 | show_signal_msg(regs, error_code, address, tsk); | 728 | show_signal_msg(regs, error_code, address, tsk); |
725 | 729 | ||
726 | /* Kernel addresses are always protection faults: */ | ||
727 | tsk->thread.cr2 = address; | 730 | tsk->thread.cr2 = address; |
728 | tsk->thread.error_code = error_code | (address >= TASK_SIZE); | 731 | tsk->thread.error_code = error_code; |
729 | tsk->thread.trap_no = 14; | 732 | tsk->thread.trap_no = 14; |
730 | 733 | ||
731 | force_sig_info_fault(SIGSEGV, si_code, address, tsk, 0); | 734 | force_sig_info_fault(SIGSEGV, si_code, address, tsk, 0); |