diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-07-25 20:32:28 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-07-25 20:32:28 -0400 |
commit | 77cd3d0c43b7e6c0bb49ca641cf936891f6e1766 (patch) | |
tree | 44885bb7ec9def5a34b8e9f2073a166f78bddcf9 /arch/x86/lib | |
parent | 0f657262d5f99ad86b9a63fb5dcd29036c2ed916 (diff) | |
parent | 6a79296cb15d947bcb4558011fe066e5d8252b35 (diff) |
Merge branch 'x86-boot-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 boot updates from Ingo Molnar:
"The main changes:
- add initial commits to randomize kernel memory section virtual
addresses, enabled via a new kernel option: RANDOMIZE_MEMORY
(Thomas Garnier, Kees Cook, Baoquan He, Yinghai Lu)
- enhance KASLR (RANDOMIZE_BASE) physical memory randomization (Kees
Cook)
- EBDA/BIOS region boot quirk cleanups (Andy Lutomirski, Ingo Molnar)
- misc cleanups/fixes"
* 'x86-boot-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
x86/boot: Simplify EBDA-vs-BIOS reservation logic
x86/boot: Clarify what x86_legacy_features.reserve_bios_regions does
x86/boot: Reorganize and clean up the BIOS area reservation code
x86/mm: Do not reference phys addr beyond kernel
x86/mm: Add memory hotplug support for KASLR memory randomization
x86/mm: Enable KASLR for vmalloc memory regions
x86/mm: Enable KASLR for physical mapping memory regions
x86/mm: Implement ASLR for kernel memory regions
x86/mm: Separate variable for trampoline PGD
x86/mm: Add PUD VA support for physical mapping
x86/mm: Update physical mapping variable names
x86/mm: Refactor KASLR entropy functions
x86/KASLR: Fix boot crash with certain memory configurations
x86/boot/64: Add forgotten end of function marker
x86/KASLR: Allow randomization below the load address
x86/KASLR: Extend kernel image physical address randomization to addresses larger than 4G
x86/KASLR: Randomize virtual address separately
x86/KASLR: Clarify identity map interface
x86/boot: Refuse to build with data relocations
x86/KASLR, x86/power: Remove x86 hibernation restrictions
Diffstat (limited to 'arch/x86/lib')
-rw-r--r-- | arch/x86/lib/Makefile | 1 | ||||
-rw-r--r-- | arch/x86/lib/kaslr.c | 90 |
2 files changed, 91 insertions, 0 deletions
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index ec969cc3eb20..34a74131a12c 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile | |||
@@ -24,6 +24,7 @@ lib-y += usercopy_$(BITS).o usercopy.o getuser.o putuser.o | |||
24 | lib-y += memcpy_$(BITS).o | 24 | lib-y += memcpy_$(BITS).o |
25 | lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o | 25 | lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o |
26 | lib-$(CONFIG_INSTRUCTION_DECODER) += insn.o inat.o | 26 | lib-$(CONFIG_INSTRUCTION_DECODER) += insn.o inat.o |
27 | lib-$(CONFIG_RANDOMIZE_BASE) += kaslr.o | ||
27 | 28 | ||
28 | obj-y += msr.o msr-reg.o msr-reg-export.o hweight.o | 29 | obj-y += msr.o msr-reg.o msr-reg-export.o hweight.o |
29 | 30 | ||
diff --git a/arch/x86/lib/kaslr.c b/arch/x86/lib/kaslr.c new file mode 100644 index 000000000000..f7dfeda83e5c --- /dev/null +++ b/arch/x86/lib/kaslr.c | |||
@@ -0,0 +1,90 @@ | |||
1 | /* | ||
2 | * Entropy functions used on early boot for KASLR base and memory | ||
3 | * randomization. The base randomization is done in the compressed | ||
4 | * kernel and memory randomization is done early when the regular | ||
5 | * kernel starts. This file is included in the compressed kernel and | ||
6 | * normally linked in the regular. | ||
7 | */ | ||
8 | #include <asm/kaslr.h> | ||
9 | #include <asm/msr.h> | ||
10 | #include <asm/archrandom.h> | ||
11 | #include <asm/e820.h> | ||
12 | #include <asm/io.h> | ||
13 | |||
14 | /* | ||
15 | * When built for the regular kernel, several functions need to be stubbed out | ||
16 | * or changed to their regular kernel equivalent. | ||
17 | */ | ||
18 | #ifndef KASLR_COMPRESSED_BOOT | ||
19 | #include <asm/cpufeature.h> | ||
20 | #include <asm/setup.h> | ||
21 | |||
22 | #define debug_putstr(v) early_printk(v) | ||
23 | #define has_cpuflag(f) boot_cpu_has(f) | ||
24 | #define get_boot_seed() kaslr_offset() | ||
25 | #endif | ||
26 | |||
27 | #define I8254_PORT_CONTROL 0x43 | ||
28 | #define I8254_PORT_COUNTER0 0x40 | ||
29 | #define I8254_CMD_READBACK 0xC0 | ||
30 | #define I8254_SELECT_COUNTER0 0x02 | ||
31 | #define I8254_STATUS_NOTREADY 0x40 | ||
32 | static inline u16 i8254(void) | ||
33 | { | ||
34 | u16 status, timer; | ||
35 | |||
36 | do { | ||
37 | outb(I8254_PORT_CONTROL, | ||
38 | I8254_CMD_READBACK | I8254_SELECT_COUNTER0); | ||
39 | status = inb(I8254_PORT_COUNTER0); | ||
40 | timer = inb(I8254_PORT_COUNTER0); | ||
41 | timer |= inb(I8254_PORT_COUNTER0) << 8; | ||
42 | } while (status & I8254_STATUS_NOTREADY); | ||
43 | |||
44 | return timer; | ||
45 | } | ||
46 | |||
47 | unsigned long kaslr_get_random_long(const char *purpose) | ||
48 | { | ||
49 | #ifdef CONFIG_X86_64 | ||
50 | const unsigned long mix_const = 0x5d6008cbf3848dd3UL; | ||
51 | #else | ||
52 | const unsigned long mix_const = 0x3f39e593UL; | ||
53 | #endif | ||
54 | unsigned long raw, random = get_boot_seed(); | ||
55 | bool use_i8254 = true; | ||
56 | |||
57 | debug_putstr(purpose); | ||
58 | debug_putstr(" KASLR using"); | ||
59 | |||
60 | if (has_cpuflag(X86_FEATURE_RDRAND)) { | ||
61 | debug_putstr(" RDRAND"); | ||
62 | if (rdrand_long(&raw)) { | ||
63 | random ^= raw; | ||
64 | use_i8254 = false; | ||
65 | } | ||
66 | } | ||
67 | |||
68 | if (has_cpuflag(X86_FEATURE_TSC)) { | ||
69 | debug_putstr(" RDTSC"); | ||
70 | raw = rdtsc(); | ||
71 | |||
72 | random ^= raw; | ||
73 | use_i8254 = false; | ||
74 | } | ||
75 | |||
76 | if (use_i8254) { | ||
77 | debug_putstr(" i8254"); | ||
78 | random ^= i8254(); | ||
79 | } | ||
80 | |||
81 | /* Circular multiply for better bit diffusion */ | ||
82 | asm("mul %3" | ||
83 | : "=a" (random), "=d" (raw) | ||
84 | : "a" (random), "rm" (mix_const)); | ||
85 | random += raw; | ||
86 | |||
87 | debug_putstr("...\n"); | ||
88 | |||
89 | return random; | ||
90 | } | ||