Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753099AbcDNWaw (ORCPT ); Thu, 14 Apr 2016 18:30:52 -0400 Received: from mail-pf0-f180.google.com ([209.85.192.180]:36622 "EHLO mail-pf0-f180.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752646AbcDNW3e (ORCPT ); Thu, 14 Apr 2016 18:29:34 -0400 From: Kees Cook To: Ingo Molnar Cc: Kees Cook , Baoquan He , Yinghai Lu , Ard Biesheuvel , Matt Redfearn , x86@kernel.org, "H. Peter Anvin" , Ingo Molnar , Borislav Petkov , Vivek Goyal , Andy Lutomirski , lasse.collin@tukaani.org, Andrew Morton , Dave Young , kernel-hardening@lists.openwall.com, LKML Subject: [PATCH v5 16/21] x86, KASLR: Add virtual address choosing function Date: Thu, 14 Apr 2016 15:29:09 -0700 Message-Id: <1460672954-32567-17-git-send-email-keescook@chromium.org> X-Mailer: git-send-email 2.6.3 In-Reply-To: <1460672954-32567-1-git-send-email-keescook@chromium.org> References: <1460672954-32567-1-git-send-email-keescook@chromium.org> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 1872 Lines: 53 From: Baoquan He To support randomizing the kernel virtual address separately from the physical address, this patch adds find_random_virt_offset() to choose a slot anywhere between LOAD_PHYSICAL_ADDR and KERNEL_IMAGE_SIZE. Since this address is virtual, not physical, we can place the kernel anywhere in this region, as long as it is aligned and (in the case of kernel being larger than the slot size) placed with enough room to load the entire kernel image. Signed-off-by: Baoquan He [kees: rewrote changelog, refactor slot calculation for readability] Signed-off-by: Kees Cook --- arch/x86/boot/compressed/aslr.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/arch/x86/boot/compressed/aslr.c b/arch/x86/boot/compressed/aslr.c index b06618000732..b527ff10372a 100644 --- a/arch/x86/boot/compressed/aslr.c +++ b/arch/x86/boot/compressed/aslr.c @@ -407,6 +407,29 @@ static unsigned long find_random_addr(unsigned long minimum, return slots_fetch_random(); } +static unsigned long find_random_virt_offset(unsigned long minimum, + unsigned long image_size) +{ + unsigned long slots, random; + + /* Make sure minimum is aligned. */ + minimum = ALIGN(minimum, CONFIG_PHYSICAL_ALIGN); + /* Align image_size for easy slot calculations. */ + image_size = ALIGN(image_size, CONFIG_PHYSICAL_ALIGN); + + /* + * There are how many CONFIG_PHYSICAL_ALIGN-sized slots + * that can hold image_size within the range of minimum to + * KERNEL_IMAGE_SIZE? + */ + slots = (KERNEL_IMAGE_SIZE - minimum - image_size) / + CONFIG_PHYSICAL_ALIGN + 1; + + random = get_random_long() % slots; + + return random * CONFIG_PHYSICAL_ALIGN + minimum; +} + unsigned char *choose_kernel_location(unsigned char *input, unsigned long input_size, unsigned char *output, -- 2.6.3