From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752988Ab3KKWKg (ORCPT ); Mon, 11 Nov 2013 17:10:36 -0500 Received: from terminus.zytor.com ([198.137.202.10]:49875 "EHLO mail.zytor.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751531Ab3KKWKa (ORCPT ); Mon, 11 Nov 2013 17:10:30 -0500 User-Agent: K-9 Mail for Android In-Reply-To: <20131111213619.GA3230@www.outflux.net> References: <20131111213619.GA3230@www.outflux.net> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Subject: Re: [PATCH v3] x86, kaslr: mix entropy sources together as needed From: "H. Peter Anvin" Date: Mon, 11 Nov 2013 14:10:06 -0800 To: Kees Cook , Ingo Molnar CC: Thomas Gleixner , linux-kernel@vger.kernel.org, x86@kernel.org Message-ID: <19e05481-b28e-4ee8-ae5b-be62a36c0492@email.android.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org You probably want to rotate by an odd number of bits... the point is to spread out any pattern in the bytes. Kees Cook wrote: >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 >--- >v3: > - do not limit ourself to the low 32 bits of TSC; Ingo Molnar. >v2: > - added build-time string to add to starting entropy; Ingo Molnar. >--- > arch/x86/Kconfig | 14 +++++--- >arch/x86/boot/compressed/aslr.c | 73 >++++++++++++++++++++++++++++++--------- > 2 files changed, 65 insertions(+), 22 deletions(-) > >diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig >index ee3b38363063..119455802d57 100644 >--- a/arch/x86/Kconfig >+++ b/arch/x86/Kconfig >@@ -1736,13 +1736,17 @@ config RANDOMIZE_BASE > deters exploit attempts relying on knowledge of the location > of kernel internals. > >- Entropy is generated using the RDRAND instruction if it >- is supported. If not, then RDTSC is used, if supported. If >- neither RDRAND nor RDTSC are supported, then no randomness >- is introduced. >+ Entropy is generated using the RDRAND instruction if it is >+ supported. If RDTSC is supported, it is used as well. If >+ neither RDRAND nor RDTSC are supported, then randomness is >+ read from the i8254 timer. > > The kernel will be offset by up to RANDOMIZE_BASE_MAX_OFFSET, >- and aligned according to PHYSICAL_ALIGN. >+ and aligned according to PHYSICAL_ALIGN. Since the kernel is >+ built using 2GiB addressing, and PHYSICAL_ALGIN must be at a >+ minimum of 2MiB, only 10 bits of entropy is theoretically >+ possible. At best, due to page table layouts, 64-bit can use >+ 9 bits of entropy and 32-bit uses 8 bits. > > config RANDOMIZE_BASE_MAX_OFFSET > hex "Maximum ASLR offset allowed" >diff --git a/arch/x86/boot/compressed/aslr.c >b/arch/x86/boot/compressed/aslr.c >index 05957986d123..0981227bc3f0 100644 >--- a/arch/x86/boot/compressed/aslr.c >+++ b/arch/x86/boot/compressed/aslr.c >@@ -5,6 +5,17 @@ > #include > #include > >+#include >+#include >+#include >+#include >+#include >+#include >+ >+/* Simplified build-specific string for starting entropy. */ >+static const char *build_str = UTS_RELEASE " (" LINUX_COMPILE_BY "@" >+ LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION; >+ > #define I8254_PORT_CONTROL 0x43 > #define I8254_PORT_COUNTER0 0x40 > #define I8254_CMD_READBACK 0xC0 >@@ -25,34 +36,62 @@ static inline u16 i8254(void) > return timer; > } > >+static unsigned long rotate_xor(unsigned long hash, const void *area, >+ size_t size) >+{ >+ size_t i; >+ unsigned long *ptr = (unsigned long *)area; >+ >+ for (i = 0; i < size / sizeof(hash); i++) { >+ /* Rotate and XOR */ >+ hash = (hash << ((sizeof(hash) - 1) * 8)) | (hash >> 8); >+ hash ^= ptr[i]; >+ } >+ >+ return hash; >+} >+ >+/* Attempt to create a simple but unpredictable starting entropy. */ >+static unsigned long get_random_boot(void) >+{ >+ unsigned long hash = 0; >+ >+ hash = rotate_xor(hash, build_str, sizeof(build_str)); >+ hash = rotate_xor(hash, real_mode, sizeof(*real_mode)); >+ >+ return hash; >+} >+ > static unsigned long get_random_long(void) > { >- unsigned long random; >+ unsigned long raw, random = get_random_boot(); >+ bool use_i8254 = true; >+ >+ debug_putstr("KASLR using"); > > if (has_cpuflag(X86_FEATURE_RDRAND)) { >- debug_putstr("KASLR using RDRAND...\n"); >- if (rdrand_long(&random)) >- return random; >+ debug_putstr(" RDRAND"); >+ if (rdrand_long(&raw)) { >+ random ^= raw; >+ use_i8254 = false; >+ } > } > > if (has_cpuflag(X86_FEATURE_TSC)) { >- uint32_t raw; >+ debug_putstr(" RDTSC"); >+ rdtscll(raw); > >- debug_putstr("KASLR using RDTSC...\n"); >- rdtscl(raw); >+ random ^= raw; >+ use_i8254 = false; >+ } > >- /* Only use the low bits of rdtsc. */ >- random = raw & 0xffff; >- } else { >- debug_putstr("KASLR using i8254...\n"); >- random = i8254(); >+ if (use_i8254) { >+ debug_putstr(" i8254"); >+ random ^= i8254(); > } > >- /* Extend timer bits poorly... */ >- random |= (random << 16); >-#ifdef CONFIG_X86_64 >- random |= (random << 32); >-#endif >+ debug_putstr("...\n"); >+ > return random; > } > -- Sent from my mobile phone. Please pardon brevity and lack of formatting.