diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-05 10:46:15 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-05 10:46:15 -0400 |
| commit | 2071b3e34fd33e496ebd7b90331ac5b3b0ac3b81 (patch) | |
| tree | aeee17f8994ffaa234354cfe70d664f85b331247 | |
| parent | 9df0fe64ebbdd85dd871cb8d52c16efe5ec45319 (diff) | |
| parent | e6ab9a20e73e790d47e6aa231fcf66f27b6ce3d4 (diff) | |
Merge branch 'x86/espfix' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip into next
Pull x86-64 espfix changes from Peter Anvin:
"This is the espfix64 code, which fixes the IRET information leak as
well as the associated functionality problem. With this code applied,
16-bit stack segments finally work as intended even on a 64-bit
kernel.
Consequently, this patchset also removes the runtime option that we
added as an interim measure.
To help the people working on Linux kernels for very small systems,
this patchset also makes these compile-time configurable features"
* 'x86/espfix' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
Revert "x86-64, modify_ldt: Make support for 16-bit segments a runtime option"
x86, espfix: Make it possible to disable 16-bit support
x86, espfix: Make espfix64 a Kconfig option, fix UML
x86, espfix: Fix broken header guard
x86, espfix: Move espfix definitions into a separate header file
x86-32, espfix: Remove filter for espfix32 due to race
x86-64, espfix: Don't leak bits 31:16 of %esp returning to 16-bit stack
| -rw-r--r-- | Documentation/x86/x86_64/mm.txt | 2 | ||||
| -rw-r--r-- | arch/x86/Kconfig | 25 | ||||
| -rw-r--r-- | arch/x86/include/asm/espfix.h | 16 | ||||
| -rw-r--r-- | arch/x86/include/asm/pgtable_64_types.h | 2 | ||||
| -rw-r--r-- | arch/x86/include/asm/setup.h | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/Makefile | 1 | ||||
| -rw-r--r-- | arch/x86/kernel/entry_32.S | 17 | ||||
| -rw-r--r-- | arch/x86/kernel/entry_64.S | 81 | ||||
| -rw-r--r-- | arch/x86/kernel/espfix_64.c | 209 | ||||
| -rw-r--r-- | arch/x86/kernel/ldt.c | 10 | ||||
| -rw-r--r-- | arch/x86/kernel/smpboot.c | 7 | ||||
| -rw-r--r-- | arch/x86/mm/dump_pagetables.c | 44 | ||||
| -rw-r--r-- | arch/x86/vdso/vdso32-setup.c | 8 | ||||
| -rw-r--r-- | init/main.c | 4 |
14 files changed, 387 insertions, 41 deletions
diff --git a/Documentation/x86/x86_64/mm.txt b/Documentation/x86/x86_64/mm.txt index c584a51add15..afe68ddbe6a4 100644 --- a/Documentation/x86/x86_64/mm.txt +++ b/Documentation/x86/x86_64/mm.txt | |||
| @@ -12,6 +12,8 @@ ffffc90000000000 - ffffe8ffffffffff (=45 bits) vmalloc/ioremap space | |||
| 12 | ffffe90000000000 - ffffe9ffffffffff (=40 bits) hole | 12 | ffffe90000000000 - ffffe9ffffffffff (=40 bits) hole |
| 13 | ffffea0000000000 - ffffeaffffffffff (=40 bits) virtual memory map (1TB) | 13 | ffffea0000000000 - ffffeaffffffffff (=40 bits) virtual memory map (1TB) |
| 14 | ... unused hole ... | 14 | ... unused hole ... |
| 15 | ffffff0000000000 - ffffff7fffffffff (=39 bits) %esp fixup stacks | ||
| 16 | ... unused hole ... | ||
| 15 | ffffffff80000000 - ffffffffa0000000 (=512 MB) kernel text mapping, from phys 0 | 17 | ffffffff80000000 - ffffffffa0000000 (=512 MB) kernel text mapping, from phys 0 |
| 16 | ffffffffa0000000 - ffffffffff5fffff (=1525 MB) module mapping space | 18 | ffffffffa0000000 - ffffffffff5fffff (=1525 MB) module mapping space |
| 17 | ffffffffff600000 - ffffffffffdfffff (=8 MB) vsyscalls | 19 | ffffffffff600000 - ffffffffffdfffff (=8 MB) vsyscalls |
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 272b493ea1bf..b660088c220d 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
| @@ -912,10 +912,27 @@ config VM86 | |||
| 912 | default y | 912 | default y |
| 913 | depends on X86_32 | 913 | depends on X86_32 |
| 914 | ---help--- | 914 | ---help--- |
| 915 | This option is required by programs like DOSEMU to run 16-bit legacy | 915 | This option is required by programs like DOSEMU to run |
| 916 | code on X86 processors. It also may be needed by software like | 916 | 16-bit real mode legacy code on x86 processors. It also may |
| 917 | XFree86 to initialize some video cards via BIOS. Disabling this | 917 | be needed by software like XFree86 to initialize some video |
| 918 | option saves about 6k. | 918 | cards via BIOS. Disabling this option saves about 6K. |
| 919 | |||
| 920 | config X86_16BIT | ||
| 921 | bool "Enable support for 16-bit segments" if EXPERT | ||
| 922 | default y | ||
| 923 | ---help--- | ||
| 924 | This option is required by programs like Wine to run 16-bit | ||
| 925 | protected mode legacy code on x86 processors. Disabling | ||
| 926 | this option saves about 300 bytes on i386, or around 6K text | ||
| 927 | plus 16K runtime memory on x86-64, | ||
| 928 | |||
| 929 | config X86_ESPFIX32 | ||
| 930 | def_bool y | ||
| 931 | depends on X86_16BIT && X86_32 | ||
| 932 | |||
| 933 | config X86_ESPFIX64 | ||
| 934 | def_bool y | ||
| 935 | depends on X86_16BIT && X86_64 | ||
| 919 | 936 | ||
| 920 | config TOSHIBA | 937 | config TOSHIBA |
| 921 | tristate "Toshiba Laptop support" | 938 | tristate "Toshiba Laptop support" |
diff --git a/arch/x86/include/asm/espfix.h b/arch/x86/include/asm/espfix.h new file mode 100644 index 000000000000..99efebb2f69d --- /dev/null +++ b/arch/x86/include/asm/espfix.h | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | #ifndef _ASM_X86_ESPFIX_H | ||
| 2 | #define _ASM_X86_ESPFIX_H | ||
| 3 | |||
| 4 | #ifdef CONFIG_X86_64 | ||
| 5 | |||
| 6 | #include <asm/percpu.h> | ||
| 7 | |||
| 8 | DECLARE_PER_CPU_READ_MOSTLY(unsigned long, espfix_stack); | ||
| 9 | DECLARE_PER_CPU_READ_MOSTLY(unsigned long, espfix_waddr); | ||
| 10 | |||
| 11 | extern void init_espfix_bsp(void); | ||
| 12 | extern void init_espfix_ap(void); | ||
| 13 | |||
| 14 | #endif /* CONFIG_X86_64 */ | ||
| 15 | |||
| 16 | #endif /* _ASM_X86_ESPFIX_H */ | ||
diff --git a/arch/x86/include/asm/pgtable_64_types.h b/arch/x86/include/asm/pgtable_64_types.h index c883bf726398..7166e25ecb57 100644 --- a/arch/x86/include/asm/pgtable_64_types.h +++ b/arch/x86/include/asm/pgtable_64_types.h | |||
| @@ -61,6 +61,8 @@ typedef struct { pteval_t pte; } pte_t; | |||
| 61 | #define MODULES_VADDR (__START_KERNEL_map + KERNEL_IMAGE_SIZE) | 61 | #define MODULES_VADDR (__START_KERNEL_map + KERNEL_IMAGE_SIZE) |
| 62 | #define MODULES_END _AC(0xffffffffff000000, UL) | 62 | #define MODULES_END _AC(0xffffffffff000000, UL) |
| 63 | #define MODULES_LEN (MODULES_END - MODULES_VADDR) | 63 | #define MODULES_LEN (MODULES_END - MODULES_VADDR) |
| 64 | #define ESPFIX_PGD_ENTRY _AC(-2, UL) | ||
| 65 | #define ESPFIX_BASE_ADDR (ESPFIX_PGD_ENTRY << PGDIR_SHIFT) | ||
| 64 | 66 | ||
| 65 | #define EARLY_DYNAMIC_PAGE_TABLES 64 | 67 | #define EARLY_DYNAMIC_PAGE_TABLES 64 |
| 66 | 68 | ||
diff --git a/arch/x86/include/asm/setup.h b/arch/x86/include/asm/setup.h index 9264f04a4c55..ff4e7b236e21 100644 --- a/arch/x86/include/asm/setup.h +++ b/arch/x86/include/asm/setup.h | |||
| @@ -59,6 +59,8 @@ static inline void x86_ce4100_early_setup(void) { } | |||
| 59 | 59 | ||
| 60 | #ifndef _SETUP | 60 | #ifndef _SETUP |
| 61 | 61 | ||
| 62 | #include <asm/espfix.h> | ||
| 63 | |||
| 62 | /* | 64 | /* |
| 63 | * This is set up by the setup-routine at boot-time | 65 | * This is set up by the setup-routine at boot-time |
| 64 | */ | 66 | */ |
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index f4d96000d33a..491ef3e59850 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile | |||
| @@ -29,6 +29,7 @@ obj-$(CONFIG_X86_64) += sys_x86_64.o x8664_ksyms_64.o | |||
| 29 | obj-y += syscall_$(BITS).o vsyscall_gtod.o | 29 | obj-y += syscall_$(BITS).o vsyscall_gtod.o |
| 30 | obj-$(CONFIG_X86_64) += vsyscall_64.o | 30 | obj-$(CONFIG_X86_64) += vsyscall_64.o |
| 31 | obj-$(CONFIG_X86_64) += vsyscall_emu_64.o | 31 | obj-$(CONFIG_X86_64) += vsyscall_emu_64.o |
| 32 | obj-$(CONFIG_X86_ESPFIX64) += espfix_64.o | ||
| 32 | obj-$(CONFIG_SYSFS) += ksysfs.o | 33 | obj-$(CONFIG_SYSFS) += ksysfs.o |
| 33 | obj-y += bootflag.o e820.o | 34 | obj-y += bootflag.o e820.o |
| 34 | obj-y += pci-dma.o quirks.o topology.o kdebugfs.o | 35 | obj-y += pci-dma.o quirks.o topology.o kdebugfs.o |
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S index a2a4f4697889..98313ffaae6a 100644 --- a/arch/x86/kernel/entry_32.S +++ b/arch/x86/kernel/entry_32.S | |||
| @@ -527,6 +527,7 @@ syscall_exit: | |||
| 527 | restore_all: | 527 | restore_all: |
| 528 | TRACE_IRQS_IRET | 528 | TRACE_IRQS_IRET |
| 529 | restore_all_notrace: | 529 | restore_all_notrace: |
| 530 | #ifdef CONFIG_X86_ESPFIX32 | ||
| 530 | movl PT_EFLAGS(%esp), %eax # mix EFLAGS, SS and CS | 531 | movl PT_EFLAGS(%esp), %eax # mix EFLAGS, SS and CS |
| 531 | # Warning: PT_OLDSS(%esp) contains the wrong/random values if we | 532 | # Warning: PT_OLDSS(%esp) contains the wrong/random values if we |
| 532 | # are returning to the kernel. | 533 | # are returning to the kernel. |
| @@ -537,6 +538,7 @@ restore_all_notrace: | |||
| 537 | cmpl $((SEGMENT_LDT << 8) | USER_RPL), %eax | 538 | cmpl $((SEGMENT_LDT << 8) | USER_RPL), %eax |
| 538 | CFI_REMEMBER_STATE | 539 | CFI_REMEMBER_STATE |
| 539 | je ldt_ss # returning to user-space with LDT SS | 540 | je ldt_ss # returning to user-space with LDT SS |
| 541 | #endif | ||
| 540 | restore_nocheck: | 542 | restore_nocheck: |
| 541 | RESTORE_REGS 4 # skip orig_eax/error_code | 543 | RESTORE_REGS 4 # skip orig_eax/error_code |
| 542 | irq_return: | 544 | irq_return: |
| @@ -549,13 +551,9 @@ ENTRY(iret_exc) | |||
| 549 | .previous | 551 | .previous |
| 550 | _ASM_EXTABLE(irq_return,iret_exc) | 552 | _ASM_EXTABLE(irq_return,iret_exc) |
| 551 | 553 | ||
| 554 | #ifdef CONFIG_X86_ESPFIX32 | ||
| 552 | CFI_RESTORE_STATE | 555 | CFI_RESTORE_STATE |
| 553 | ldt_ss: | 556 | ldt_ss: |
| 554 | larl PT_OLDSS(%esp), %eax | ||
| 555 | jnz restore_nocheck | ||
| 556 | testl $0x00400000, %eax # returning to 32bit stack? | ||
| 557 | jnz restore_nocheck # allright, normal return | ||
| 558 | |||
| 559 | #ifdef CONFIG_PARAVIRT | 557 | #ifdef CONFIG_PARAVIRT |
| 560 | /* | 558 | /* |
| 561 | * The kernel can't run on a non-flat stack if paravirt mode | 559 | * The kernel can't run on a non-flat stack if paravirt mode |
| @@ -597,6 +595,7 @@ ldt_ss: | |||
| 597 | lss (%esp), %esp /* switch to espfix segment */ | 595 | lss (%esp), %esp /* switch to espfix segment */ |
| 598 | CFI_ADJUST_CFA_OFFSET -8 | 596 | CFI_ADJUST_CFA_OFFSET -8 |
| 599 | jmp restore_nocheck | 597 | jmp restore_nocheck |
| 598 | #endif | ||
| 600 | CFI_ENDPROC | 599 | CFI_ENDPROC |
| 601 | ENDPROC(system_call) | 600 | ENDPROC(system_call) |
| 602 | 601 | ||
| @@ -704,6 +703,7 @@ END(syscall_badsys) | |||
| 704 | * the high word of the segment base from the GDT and swiches to the | 703 | * the high word of the segment base from the GDT and swiches to the |
| 705 | * normal stack and adjusts ESP with the matching offset. | 704 | * normal stack and adjusts ESP with the matching offset. |
| 706 | */ | 705 | */ |
| 706 | #ifdef CONFIG_X86_ESPFIX32 | ||
| 707 | /* fixup the stack */ | 707 | /* fixup the stack */ |
| 708 | mov GDT_ESPFIX_SS + 4, %al /* bits 16..23 */ | 708 | mov GDT_ESPFIX_SS + 4, %al /* bits 16..23 */ |
| 709 | mov GDT_ESPFIX_SS + 7, %ah /* bits 24..31 */ | 709 | mov GDT_ESPFIX_SS + 7, %ah /* bits 24..31 */ |
| @@ -713,8 +713,10 @@ END(syscall_badsys) | |||
