[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <1306278525.1921.14.camel@dan>
Date: Tue, 24 May 2011 19:08:45 -0400
From: Dan Rosenberg <drosenberg@...curity.com>
To: Tony Luck <tony.luck@...il.com>
Cc: linux-kernel@...r.kernel.org, davej@...hat.com,
kees.cook@...onical.com, davem@...emloft.net, eranian@...gle.com,
torvalds@...ux-foundation.org, adobriyan@...il.com,
penberg@...nel.org, hpa@...or.com,
Arjan van de Ven <arjan@...radead.org>,
Andrew Morton <akpm@...ux-foundation.org>,
Valdis.Kletnieks@...edu, Ingo Molnar <mingo@...e.hu>,
pageexec@...email.hu
Subject: Re: [RFC][PATCH] Randomize kernel base address on boot
On Tue, 2011-05-24 at 16:31 -0400, Dan Rosenberg wrote:
> This introduces CONFIG_RANDOMIZE_BASE, which randomizes the address at
> which the kernel is decompressed at boot as a security feature that
> deters exploit attempts relying on knowledge of the location of kernel
> internals. The default values of the kptr_restrict and dmesg_restrict
> sysctls are set to (1) when this is enabled, since hiding kernel
> pointers is necessary to preserve the secrecy of the randomized base
> address.
> diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S
> index 67a655a..2680db0 100644
> --- a/arch/x86/boot/compressed/head_32.S
> +++ b/arch/x86/boot/compressed/head_32.S
> @@ -69,12 +69,75 @@ ENTRY(startup_32)
> */
>
> #ifdef CONFIG_RELOCATABLE
> +#ifdef CONFIG_RANDOMIZE_BASE
> +
> + /* Standard check for cpuid */
> + pushfl
> + popl %eax
> + movl %eax, %ebx
> + xorl $0x200000, %eax
> + pushl %eax
> + popfl
> + pushfl
> + popl %eax
> + cmpl %eax, %ebx
> + jz 4f
> +
> + /* Check for cpuid 1 */
> + movl $0x0, %eax
> + cpuid
> + cmpl $0x1, %eax
> + jb 4f
> +
> + movl $0x1, %eax
> + cpuid
> + xor %eax, %eax
> +
> + /* RDRAND is bit 30 */
> + testl $0x4000000, %ecx
> + jnz 1f
> +
> + /* RDTSC is bit 4 */
> + testl $0x10, %edx
> + jnz 3f
> +
> + /* Nothing is supported */
> + jmp 4f
> +1:
> + /* RDRAND sets carry bit on success, otherwise we should try
> + * again. */
> + movl $0x10, %ecx
> +2:
> + /* rdrand %eax */
> + .byte 0x0f, 0xc7, 0xf0
> + jc 4f
> + loop 2b
> +
> + /* Fall through: if RDRAND is supported but fails, use RDTSC,
> + * which is guaranteed to be supported. */
> +3:
> + rdtsc
> + shll $0xc, %eax
> +4:
> + /* Maximum offset at 64mb to be safe */
> + andl $0x3ffffff, %eax
> + movl %ebp, %ebx
> + addl %eax, %ebx
> +#else
> movl %ebp, %ebx
> +#endif
> movl BP_kernel_alignment(%esi), %eax
> decl %eax
> addl %eax, %ebx
> notl %eax
> andl %eax, %ebx
> +
> + /* LOAD_PHSYICAL_ADDR is the minimum safe address we can
> + * decompress at. */
> + cmpl $LOAD_PHYSICAL_ADDR, %ebx
> + jae 1f
> + movl $LOAD_PHYSICAL_ADDR, %ebx
> +1:
> #else
> movl $LOAD_PHYSICAL_ADDR, %ebx
> #endif
> diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
> index 35af09d..6a05219 100644
> --- a/arch/x86/boot/compressed/head_64.S
> +++ b/arch/x86/boot/compressed/head_64.S
> @@ -90,6 +90,13 @@ ENTRY(startup_32)
> addl %eax, %ebx
> notl %eax
> andl %eax, %ebx
> +
> + /* LOAD_PHYSICAL_ADDR is the minimum safe address we can
> + * decompress at. */
> + cmpl $LOAD_PHYSICAL_ADDR, %ebx
> + jae 1f
> + movl $LOAD_PHYSICAL_ADDR, %ebx
> +1:
> #else
> movl $LOAD_PHYSICAL_ADDR, %ebx
> #endif
> @@ -191,7 +198,7 @@ no_longmode:
> * it may change in the future.
> */
> .code64
> - .org 0x200
> + .org 0x300
> ENTRY(startup_64)
> /*
> * We come here either from startup_32 or directly from a
> @@ -232,6 +239,13 @@ ENTRY(startup_64)
> addq %rax, %rbp
> notq %rax
> andq %rax, %rbp
> +
> + /* LOAD_PHYSICAL_ADDR is the minimum safe address we can
> + * decompress at. */
> + cmpq $LOAD_PHYSICAL_ADDR, %rbp
> + jae 1f
> + movq $LOAD_PHYSICAL_ADDR, %rbp
> +1:
> #else
> movq $LOAD_PHYSICAL_ADDR, %rbp
> #endif
Thanks to Kees Cook for noticing that I didn't clear %eax before jumping
to my "nothing supported" (4) label. This would have just used the
flags as "randomness", but it's still wrong and I'll fix it. Next
version will have a fallback of using the BIOS signature instead anyway.
-Dan
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists