Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Thomas Garnier and committed by
Ingo Molnar
d899a7d1 9e7f7f54

+102 -71
+5 -71
arch/x86/boot/compressed/kaslr.c
··· 12 12 #include "misc.h" 13 13 #include "error.h" 14 14 15 - #include <asm/msr.h> 16 - #include <asm/archrandom.h> 17 - #include <asm/e820.h> 18 - 19 15 #include <generated/compile.h> 20 16 #include <linux/module.h> 21 17 #include <linux/uts.h> ··· 21 25 /* Simplified build-specific string for starting entropy. */ 22 26 static const char build_str[] = UTS_RELEASE " (" LINUX_COMPILE_BY "@" 23 27 LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION; 24 - 25 - #define I8254_PORT_CONTROL 0x43 26 - #define I8254_PORT_COUNTER0 0x40 27 - #define I8254_CMD_READBACK 0xC0 28 - #define I8254_SELECT_COUNTER0 0x02 29 - #define I8254_STATUS_NOTREADY 0x40 30 - static inline u16 i8254(void) 31 - { 32 - u16 status, timer; 33 - 34 - do { 35 - outb(I8254_PORT_CONTROL, 36 - I8254_CMD_READBACK | I8254_SELECT_COUNTER0); 37 - status = inb(I8254_PORT_COUNTER0); 38 - timer = inb(I8254_PORT_COUNTER0); 39 - timer |= inb(I8254_PORT_COUNTER0) << 8; 40 - } while (status & I8254_STATUS_NOTREADY); 41 - 42 - return timer; 43 - } 44 28 45 29 static unsigned long rotate_xor(unsigned long hash, const void *area, 46 30 size_t size) ··· 38 62 } 39 63 40 64 /* Attempt to create a simple but unpredictable starting entropy. */ 41 - static unsigned long get_random_boot(void) 65 + static unsigned long get_boot_seed(void) 42 66 { 43 67 unsigned long hash = 0; 44 68 ··· 48 72 return hash; 49 73 } 50 74 51 - static unsigned long get_random_long(const char *purpose) 52 - { 53 - #ifdef CONFIG_X86_64 54 - const unsigned long mix_const = 0x5d6008cbf3848dd3UL; 55 - #else 56 - const unsigned long mix_const = 0x3f39e593UL; 57 - #endif 58 - unsigned long raw, random = get_random_boot(); 59 - bool use_i8254 = true; 60 - 61 - debug_putstr(purpose); 62 - debug_putstr(" KASLR using"); 63 - 64 - if (has_cpuflag(X86_FEATURE_RDRAND)) { 65 - debug_putstr(" RDRAND"); 66 - if (rdrand_long(&raw)) { 67 - random ^= raw; 68 - use_i8254 = false; 69 - } 70 - } 71 - 72 - if (has_cpuflag(X86_FEATURE_TSC)) { 73 - debug_putstr(" RDTSC"); 74 - raw = rdtsc(); 75 - 76 - random ^= raw; 77 - use_i8254 = false; 78 - } 79 - 80 - if (use_i8254) { 81 - debug_putstr(" i8254"); 82 - random ^= i8254(); 83 - } 84 - 85 - /* Circular multiply for better bit diffusion */ 86 - asm("mul %3" 87 - : "=a" (random), "=d" (raw) 88 - : "a" (random), "rm" (mix_const)); 89 - random += raw; 90 - 91 - debug_putstr("...\n"); 92 - 93 - return random; 94 - } 75 + #define KASLR_COMPRESSED_BOOT 76 + #include "../../lib/kaslr.c" 95 77 96 78 struct mem_vector { 97 79 unsigned long start; ··· 283 349 if (slot_max == 0) 284 350 return 0; 285 351 286 - slot = get_random_long("Physical") % slot_max; 352 + slot = kaslr_get_random_long("Physical") % slot_max; 287 353 288 354 for (i = 0; i < slot_area_index; i++) { 289 355 if (slot >= slot_areas[i].num) { ··· 413 479 slots = (KERNEL_IMAGE_SIZE - minimum - image_size) / 414 480 CONFIG_PHYSICAL_ALIGN + 1; 415 481 416 - random_addr = get_random_long("Virtual") % slots; 482 + random_addr = kaslr_get_random_long("Virtual") % slots; 417 483 418 484 return random_addr * CONFIG_PHYSICAL_ALIGN + minimum; 419 485 }
+6
arch/x86/include/asm/kaslr.h
··· 1 + #ifndef _ASM_KASLR_H_ 2 + #define _ASM_KASLR_H_ 3 + 4 + unsigned long kaslr_get_random_long(const char *purpose); 5 + 6 + #endif
+1
arch/x86/lib/Makefile
··· 24 24 lib-y += memcpy_$(BITS).o 25 25 lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o 26 26 lib-$(CONFIG_INSTRUCTION_DECODER) += insn.o inat.o 27 + lib-$(CONFIG_RANDOMIZE_BASE) += kaslr.o 27 28 28 29 obj-y += msr.o msr-reg.o msr-reg-export.o 29 30
+90
arch/x86/lib/kaslr.c
··· 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 + }