aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKees Cook <keescook@chromium.org>2013-04-10 15:24:22 -0400
committerH. Peter Anvin <hpa@linux.intel.com>2013-04-11 16:53:19 -0400
commit4eefbe792baedb474e256d35370849992fcf1c79 (patch)
tree03a95dab4a014a7f36133f9660ca180b01df62d4
parent31880c37c11e28cb81c70757e38392b42e695dc6 (diff)
x86: Use a read-only IDT alias on all CPUs
Make a copy of the IDT (as seen via the "sidt" instruction) read-only. This primarily removes the IDT from being a target for arbitrary memory write attacks, and has the added benefit of also not leaking the kernel base offset, if it has been relocated. We already did this on vendor == Intel and family == 5 because of the F0 0F bug -- regardless of if a particular CPU had the F0 0F bug or not. Since the workaround was so cheap, there simply was no reason to be very specific. This patch extends the readonly alias to all CPUs, but does not activate the #PF to #UD conversion code needed to deliver the proper exception in the F0 0F case except on Intel family 5 processors. Signed-off-by: Kees Cook <keescook@chromium.org> Link: http://lkml.kernel.org/r/20130410192422.GA17344@www.outflux.net Cc: Eric Northup <digitaleric@google.com> Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
-rw-r--r--arch/x86/include/asm/fixmap.h4
-rw-r--r--arch/x86/kernel/cpu/intel.c18
-rw-r--r--arch/x86/kernel/traps.c9
-rw-r--r--arch/x86/xen/mmu.c4
4 files changed, 12 insertions, 23 deletions
diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h
index a09c28571064..51b9e322cb8f 100644
--- a/arch/x86/include/asm/fixmap.h
+++ b/arch/x86/include/asm/fixmap.h
@@ -104,9 +104,7 @@ enum fixed_addresses {
104 FIX_LI_PCIA, /* Lithium PCI Bridge A */ 104 FIX_LI_PCIA, /* Lithium PCI Bridge A */
105 FIX_LI_PCIB, /* Lithium PCI Bridge B */ 105 FIX_LI_PCIB, /* Lithium PCI Bridge B */
106#endif 106#endif
107#ifdef CONFIG_X86_F00F_BUG 107 FIX_RO_IDT, /* Virtual mapping for read-only IDT */
108 FIX_F00F_IDT, /* Virtual mapping for IDT */
109#endif
110#ifdef CONFIG_X86_CYCLONE_TIMER 108#ifdef CONFIG_X86_CYCLONE_TIMER
111 FIX_CYCLONE_TIMER, /*cyclone timer register*/ 109 FIX_CYCLONE_TIMER, /*cyclone timer register*/
112#endif 110#endif
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index 1905ce98bee0..71700247a5d7 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -164,20 +164,6 @@ int __cpuinit ppro_with_ram_bug(void)
164 return 0; 164 return 0;
165} 165}
166 166
167#ifdef CONFIG_X86_F00F_BUG
168static void __cpuinit trap_init_f00f_bug(void)
169{
170 __set_fixmap(FIX_F00F_IDT, __pa_symbol(idt_table), PAGE_KERNEL_RO);
171
172 /*
173 * Update the IDT descriptor and reload the IDT so that
174 * it uses the read-only mapped virtual address.
175 */
176 idt_descr.address = fix_to_virt(FIX_F00F_IDT);
177 load_idt(&idt_descr);
178}
179#endif
180
181static void __cpuinit intel_smp_check(struct cpuinfo_x86 *c) 167static void __cpuinit intel_smp_check(struct cpuinfo_x86 *c)
182{ 168{
183 /* calling is from identify_secondary_cpu() ? */ 169 /* calling is from identify_secondary_cpu() ? */
@@ -206,8 +192,7 @@ static void __cpuinit intel_workarounds(struct cpuinfo_x86 *c)
206 /* 192 /*
207 * All current models of Pentium and Pentium with MMX technology CPUs 193 * All current models of Pentium and Pentium with MMX technology CPUs
208 * have the F0 0F bug, which lets nonprivileged users lock up the 194 * have the F0 0F bug, which lets nonprivileged users lock up the
209 * system. 195 * system. Announce that the fault handler will be checking for it.
210 * Note that the workaround only should be initialized once...
211 */ 196 */
212 c->f00f_bug = 0; 197 c->f00f_bug = 0;
213 if (!paravirt_enabled() && c->x86 == 5) { 198 if (!paravirt_enabled() && c->x86 == 5) {
@@ -215,7 +200,6 @@ static void __cpuinit intel_workarounds(struct cpuinfo_x86 *c)
215 200
216 c->f00f_bug = 1; 201 c->f00f_bug = 1;
217 if (!f00f_workaround_enabled) { 202 if (!f00f_workaround_enabled) {
218 trap_init_f00f_bug();
219 printk(KERN_NOTICE "Intel Pentium with F0 0F bug - workaround enabled.\n"); 203 printk(KERN_NOTICE "Intel Pentium with F0 0F bug - workaround enabled.\n");
220 f00f_workaround_enabled = 1; 204 f00f_workaround_enabled = 1;
221 } 205 }
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index 68bda7a84159..10e24462c058 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -56,6 +56,7 @@
56#include <asm/fpu-internal.h> 56#include <asm/fpu-internal.h>
57#include <asm/mce.h> 57#include <asm/mce.h>
58#include <asm/context_tracking.h> 58#include <asm/context_tracking.h>
59#include <asm/fixmap.h>
59 60
60#include <asm/mach_traps.h> 61#include <asm/mach_traps.h>
61 62
@@ -753,6 +754,14 @@ void __init trap_init(void)
753#endif 754#endif
754 755
755 /* 756 /*
757 * Set the IDT descriptor to a fixed read-only location, so that the
758 * "sidt" instruction will not leak the location of the kernel, and
759 * to defend the IDT against arbitrary memory write vulnerabilities.
760 * It will be reloaded in cpu_init() */
761 __set_fixmap(FIX_RO_IDT, __pa_symbol(idt_table), PAGE_KERNEL_RO);
762 idt_descr.address = fix_to_virt(FIX_RO_IDT);
763
764 /*
756 * Should be a barrier for any external CPU state: 765 * Should be a barrier for any external CPU state:
757 */ 766 */
758 cpu_init(); 767 cpu_init();
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index 6afbb2ca9a0a..8bc4decb14ca 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -2039,9 +2039,7 @@ static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot)
2039 2039
2040 switch (idx) { 2040 switch (idx) {
2041 case FIX_BTMAP_END ... FIX_BTMAP_BEGIN: 2041 case FIX_BTMAP_END ... FIX_BTMAP_BEGIN:
2042#ifdef CONFIG_X86_F00F_BUG 2042 case FIX_RO_IDT:
2043 case FIX_F00F_IDT:
2044#endif
2045#ifdef CONFIG_X86_32 2043#ifdef CONFIG_X86_32
2046 case FIX_WP_TEST: 2044 case FIX_WP_TEST:
2047 case FIX_VDSO: 2045 case FIX_VDSO: