aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Garnier <thgarnie@google.com>2016-06-21 20:46:58 -0400
committerIngo Molnar <mingo@kernel.org>2016-07-08 11:33:45 -0400
commitd899a7d146a2ed8a7e6c2f61bcd232908bcbaabc (patch)
tree3ee4dd7bca76a3b0d51a96b15edcd84bdb14a1a8
parent9e7f7f5425e6d1492109a537ee88c99b29580655 (diff)
x86/mm: Refactor KASLR entropy functions
Move the KASLR entropy functions into arch/x86/lib to be used in early kernel boot for KASLR memory randomization. Signed-off-by: Thomas Garnier <thgarnie@google.com> Signed-off-by: Kees Cook <keescook@chromium.org> Cc: Alexander Kuleshov <kuleshovmail@gmail.com> Cc: Alexander Popov <alpopov@ptsecurity.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Andy Lutomirski <luto@kernel.org> Cc: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> Cc: Baoquan He <bhe@redhat.com> Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com> Cc: Borislav Petkov <bp@alien8.de> Cc: Borislav Petkov <bp@suse.de> Cc: Brian Gerst <brgerst@gmail.com> Cc: Christian Borntraeger <borntraeger@de.ibm.com> Cc: Dan Williams <dan.j.williams@intel.com> Cc: Dave Hansen <dave.hansen@linux.intel.com> Cc: Dave Young <dyoung@redhat.com> Cc: Denys Vlasenko <dvlasenk@redhat.com> Cc: Dmitry Vyukov <dvyukov@google.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Jan Beulich <JBeulich@suse.com> Cc: Joerg Roedel <jroedel@suse.de> Cc: Jonathan Corbet <corbet@lwn.net> Cc: Josh Poimboeuf <jpoimboe@redhat.com> Cc: Juergen Gross <jgross@suse.com> Cc: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Lv Zheng <lv.zheng@intel.com> Cc: Mark Salter <msalter@redhat.com> Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> Cc: Matt Fleming <matt@codeblueprint.co.uk> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephen Smalley <sds@tycho.nsa.gov> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Toshi Kani <toshi.kani@hpe.com> Cc: Xiao Guangrong <guangrong.xiao@linux.intel.com> Cc: Yinghai Lu <yinghai@kernel.org> Cc: kernel-hardening@lists.openwall.com Cc: linux-doc@vger.kernel.org Link: http://lkml.kernel.org/r/1466556426-32664-2-git-send-email-keescook@chromium.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--arch/x86/boot/compressed/kaslr.c76
-rw-r--r--arch/x86/include/asm/kaslr.h6
-rw-r--r--arch/x86/lib/Makefile1
-rw-r--r--arch/x86/lib/kaslr.c90
4 files changed, 102 insertions, 71 deletions
diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c
index 010ea16e5f77..a66854d99ee1 100644
--- a/arch/x86/boot/compressed/kaslr.c
+++ b/arch/x86/boot/compressed/kaslr.c
@@ -12,10 +12,6 @@
12#include "misc.h" 12#include "misc.h"
13#include "error.h" 13#include "error.h"
14 14
15#include <asm/msr.h>
16#include <asm/archrandom.h>
17#include <asm/e820.h>
18
19#include <generated/compile.h> 15#include <generated/compile.h>
20#include <linux/module.h> 16#include <linux/module.h>
21#include <linux/uts.h> 17#include <linux/uts.h>
@@ -26,26 +22,6 @@
26static const char build_str[] = UTS_RELEASE " (" LINUX_COMPILE_BY "@" 22static const char build_str[] = UTS_RELEASE " (" LINUX_COMPILE_BY "@"
27 LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION; 23 LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION;
28 24
29#define I8254_PORT_CONTROL 0x43
30#define I8254_PORT_COUNTER0 0x40
31#define I8254_CMD_READBACK 0xC0
32#define I8254_SELECT_COUNTER0 0x02
33#define I8254_STATUS_NOTREADY 0x40
34static inline u16 i8254(void)
35{
36 u16 status, timer;
37
38 do {
39 outb(I8254_PORT_CONTROL,
40 I8254_CMD_READBACK | I8254_SELECT_COUNTER0);
41 status = inb(I8254_PORT_COUNTER0);
42 timer = inb(I8254_PORT_COUNTER0);
43 timer |= inb(I8254_PORT_COUNTER0) << 8;
44 } while (status & I8254_STATUS_NOTREADY);
45
46 return timer;
47}
48
49static unsigned long rotate_xor(unsigned long hash, const void *area, 25static unsigned long rotate_xor(unsigned long hash, const void *area,
50 size_t size) 26 size_t size)
51{ 27{
@@ -62,7 +38,7 @@ static unsigned long rotate_xor(unsigned long hash, const void *area,
62} 38}
63 39
64/* Attempt to create a simple but unpredictable starting entropy. */ 40/* Attempt to create a simple but unpredictable starting entropy. */
65static unsigned long get_random_boot(void) 41static unsigned long get_boot_seed(void)
66{ 42{
67 unsigned long hash = 0; 43 unsigned long hash = 0;
68 44
@@ -72,50 +48,8 @@ static unsigned long get_random_boot(void)
72 return hash; 48 return hash;
73} 49}
74 50
75static unsigned long get_random_long(const char *purpose) 51#define KASLR_COMPRESSED_BOOT
76{ 52#include "../../lib/kaslr.c"
77#ifdef CONFIG_X86_64
78 const unsigned long mix_const = 0x5d6008cbf3848dd3UL;
79#else
80 const unsigned long mix_const = 0x3f39e593UL;
81#endif
82 unsigned long raw, random = get_random_boot();
83 bool use_i8254 = true;
84
85 debug_putstr(purpose);
86 debug_putstr(" KASLR using");
87
88 if (has_cpuflag(X86_FEATURE_RDRAND)) {
89 debug_putstr(" RDRAND");
90 if (rdrand_long(&raw)) {
91 random ^= raw;
92 use_i8254 = false;
93 }
94 }
95
96 if (has_cpuflag(X86_FEATURE_TSC)) {
97 debug_putstr(" RDTSC");
98 raw = rdtsc();
99
100 random ^= raw;
101 use_i8254 = false;
102 }
103
104 if (use_i8254) {
105 debug_putstr(" i8254");
106 random ^= i8254();
107 }
108
109 /* Circular multiply for better bit diffusion */
110 asm("mul %3"
111 : "=a" (random), "=d" (raw)
112 : "a" (random), "rm" (mix_const));
113 random += raw;
114
115 debug_putstr("...\n");
116
117 return random;
118}
119 53
120struct mem_vector { 54struct mem_vector {
121 unsigned long start; 55 unsigned long start;
@@ -349,7 +283,7 @@ static unsigned long slots_fetch_random(void)
349 if (slot_max == 0) 283 if (slot_max == 0)
350 return 0; 284 return 0;
351 285
352 slot = get_random_long("Physical") % slot_max; 286 slot = kaslr_get_random_long("Physical") % slot_max;
353 287
354 for (i = 0; i < slot_area_index; i++) { 288 for (i = 0; i < slot_area_index; i++) {
355 if (slot >= slot_areas[i].num) { 289 if (slot >= slot_areas[i].num) {
@@ -479,7 +413,7 @@ static unsigned long find_random_virt_addr(unsigned long minimum,
479 slots = (KERNEL_IMAGE_SIZE - minimum - image_size) / 413 slots = (KERNEL_IMAGE_SIZE - minimum - image_size) /
480 CONFIG_PHYSICAL_ALIGN + 1; 414 CONFIG_PHYSICAL_ALIGN + 1;
481 415
482 random_addr = get_random_long("Virtual") % slots; 416 random_addr = kaslr_get_random_long("Virtual") % slots;
483 417
484 return random_addr * CONFIG_PHYSICAL_ALIGN + minimum; 418 return random_addr * CONFIG_PHYSICAL_ALIGN + minimum;
485} 419}
diff --git a/arch/x86/include/asm/kaslr.h b/arch/x86/include/asm/kaslr.h
new file mode 100644
index 000000000000..5547438db5ea
--- /dev/null
+++ b/arch/x86/include/asm/kaslr.h
@@ -0,0 +1,6 @@
1#ifndef _ASM_KASLR_H_
2#define _ASM_KASLR_H_
3
4unsigned long kaslr_get_random_long(const char *purpose);
5
6#endif
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
index 72a576752a7e..cfa6d076f4f2 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
24lib-y += memcpy_$(BITS).o 24lib-y += memcpy_$(BITS).o
25lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o 25lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
26lib-$(CONFIG_INSTRUCTION_DECODER) += insn.o inat.o 26lib-$(CONFIG_INSTRUCTION_DECODER) += insn.o inat.o
27lib-$(CONFIG_RANDOMIZE_BASE) += kaslr.o
27 28
28obj-y += msr.o msr-reg.o msr-reg-export.o 29obj-y += msr.o msr-reg.o msr-reg-export.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
32static 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
47unsigned 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}