aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKees Cook <keescook@chromium.org>2013-11-11 17:28:39 -0500
committerH. Peter Anvin <hpa@zytor.com>2013-11-12 01:29:44 -0500
commita653f3563c51c7bb7de63d607bef09d3baddaeb8 (patch)
treebb431f947a59f2301aa81e9f347dc8b531b524b4
parentaec58bafaf89279522c44ec8ca9211eabb2b6976 (diff)
x86, kaslr: Mix entropy sources together as needed
Depending on availability, mix the RDRAND and RDTSC entropy together with XOR. Only when neither is available should the i8254 be used. Update the Kconfig documentation to reflect this. Additionally, since bits used for entropy is masked elsewhere, drop the needless masking in the get_random_long(). Similarly, use the entire TSC, not just the low 32 bits. Finally, to improve the starting entropy, do a simple hashing of a build-time versions string and the boot-time boot_params structure for some additional level of unpredictability. Signed-off-by: Kees Cook <keescook@chromium.org> Link: http://lkml.kernel.org/r/20131111222839.GA28616@www.outflux.net Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-rw-r--r--arch/x86/Kconfig14
-rw-r--r--arch/x86/boot/compressed/aslr.c73
2 files changed, 65 insertions, 22 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 51f439953d23..596cd9edeb9c 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1735,13 +1735,17 @@ config RANDOMIZE_BASE
1735 deters exploit attempts relying on knowledge of the location 1735 deters exploit attempts relying on knowledge of the location
1736 of kernel internals. 1736 of kernel internals.
1737 1737
1738 Entropy is generated using the RDRAND instruction if it 1738 Entropy is generated using the RDRAND instruction if it is
1739 is supported. If not, then RDTSC is used, if supported. If 1739 supported. If RDTSC is supported, it is used as well. If
1740 neither RDRAND nor RDTSC are supported, then no randomness 1740 neither RDRAND nor RDTSC are supported, then randomness is
1741 is introduced. 1741 read from the i8254 timer.
1742 1742
1743 The kernel will be offset by up to RANDOMIZE_BASE_MAX_OFFSET, 1743 The kernel will be offset by up to RANDOMIZE_BASE_MAX_OFFSET,
1744 and aligned according to PHYSICAL_ALIGN. 1744 and aligned according to PHYSICAL_ALIGN. Since the kernel is
1745 built using 2GiB addressing, and PHYSICAL_ALGIN must be at a
1746 minimum of 2MiB, only 10 bits of entropy is theoretically
1747 possible. At best, due to page table layouts, 64-bit can use
1748 9 bits of entropy and 32-bit uses 8 bits.
1745 1749
1746config RANDOMIZE_BASE_MAX_OFFSET 1750config RANDOMIZE_BASE_MAX_OFFSET
1747 hex "Maximum ASLR offset allowed" 1751 hex "Maximum ASLR offset allowed"
diff --git a/arch/x86/boot/compressed/aslr.c b/arch/x86/boot/compressed/aslr.c
index 05957986d123..8746487fa916 100644
--- a/arch/x86/boot/compressed/aslr.c
+++ b/arch/x86/boot/compressed/aslr.c
@@ -5,6 +5,17 @@
5#include <asm/archrandom.h> 5#include <asm/archrandom.h>
6#include <asm/e820.h> 6#include <asm/e820.h>
7 7
8#include <generated/compile.h>
9#include <linux/module.h>
10#include <linux/uts.h>
11#include <linux/utsname.h>
12#include <generated/utsrelease.h>
13#include <linux/version.h>
14
15/* Simplified build-specific string for starting entropy. */
16static const char *build_str = UTS_RELEASE " (" LINUX_COMPILE_BY "@"
17 LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION;
18
8#define I8254_PORT_CONTROL 0x43 19#define I8254_PORT_CONTROL 0x43
9#define I8254_PORT_COUNTER0 0x40 20#define I8254_PORT_COUNTER0 0x40
10#define I8254_CMD_READBACK 0xC0 21#define I8254_CMD_READBACK 0xC0
@@ -25,34 +36,62 @@ static inline u16 i8254(void)
25 return timer; 36 return timer;
26} 37}
27 38
39static unsigned long rotate_xor(unsigned long hash, const void *area,
40 size_t size)
41{
42 size_t i;
43 unsigned long *ptr = (unsigned long *)area;
44
45 for (i = 0; i < size / sizeof(hash); i++) {
46 /* Rotate by odd number of bits and XOR. */
47 hash = (hash << ((sizeof(hash) * 8) - 7)) | (hash >> 7);
48 hash ^= ptr[i];
49 }
50
51 return hash;
52}
53
54/* Attempt to create a simple but unpredictable starting entropy. */
55static unsigned long get_random_boot(void)
56{
57 unsigned long hash = 0;
58
59 hash = rotate_xor(hash, build_str, sizeof(build_str));
60 hash = rotate_xor(hash, real_mode, sizeof(*real_mode));
61
62 return hash;
63}
64
28static unsigned long get_random_long(void) 65static unsigned long get_random_long(void)
29{ 66{
30 unsigned long random; 67 unsigned long raw, random = get_random_boot();
68 bool use_i8254 = true;
69
70 debug_putstr("KASLR using");
31 71
32 if (has_cpuflag(X86_FEATURE_RDRAND)) { 72 if (has_cpuflag(X86_FEATURE_RDRAND)) {
33 debug_putstr("KASLR using RDRAND...\n"); 73 debug_putstr(" RDRAND");
34 if (rdrand_long(&random)) 74 if (rdrand_long(&raw)) {
35 return random; 75 random ^= raw;
76 use_i8254 = false;
77 }
36 } 78 }
37 79
38 if (has_cpuflag(X86_FEATURE_TSC)) { 80 if (has_cpuflag(X86_FEATURE_TSC)) {
39 uint32_t raw; 81 debug_putstr(" RDTSC");
82 rdtscll(raw);
40 83
41 debug_putstr("KASLR using RDTSC...\n"); 84 random ^= raw;
42 rdtscl(raw); 85 use_i8254 = false;
86 }
43 87
44 /* Only use the low bits of rdtsc. */ 88 if (use_i8254) {
45 random = raw & 0xffff; 89 debug_putstr(" i8254");
46 } else { 90 random ^= i8254();
47 debug_putstr("KASLR using i8254...\n");
48 random = i8254();
49 } 91 }
50 92
51 /* Extend timer bits poorly... */ 93 debug_putstr("...\n");
52 random |= (random << 16); 94
53#ifdef CONFIG_X86_64
54 random |= (random << 32);
55#endif
56 return random; 95 return random;
57} 96}
58 97