From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755280AbcKVIr7 (ORCPT ); Tue, 22 Nov 2016 03:47:59 -0500 Received: from mail-qk0-f194.google.com ([209.85.220.194]:34002 "EHLO mail-qk0-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755219AbcKVIr6 (ORCPT ); Tue, 22 Nov 2016 03:47:58 -0500 Date: Tue, 22 Nov 2016 09:47:54 +0100 From: Ingo Molnar To: Dave Jiang Cc: tglx@linutronix.de, mingo@redhat.com, hpa@zytor.com, dan.j.williams@intel.com, x86@kernel.org, david@fromorbit.com, linux-kernel@vger.kernel.org, linux-nvdimm@ml01.01.org, Kees Cook Subject: Re: [PATCH] x86: fix kaslr and memmap collision Message-ID: <20161122084754.GA25596@gmail.com> References: <147977413859.13657.2181994710415174471.stgit@djiang5-desk3.ch.intel.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <147977413859.13657.2181994710415174471.stgit@djiang5-desk3.ch.intel.com> User-Agent: Mutt/1.5.24 (2015-08-30) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org * Dave Jiang wrote: > CONFIG_RANDOMIZE_BASE relocates the kernel to a random base address. > However it does not take into account the memmap= parameter passed in from > the kernel commandline. memmap= parameters are often used as a list. > [...] This results in the kernel sometimes being put in the middle of the user > memmap. [...] What does this mean? If memmap= is used to re-define the memory map then the kernel getting in the middle of a RAM area is what we want, isn't it? What we don't want is for the kernel to get into reserved areas, right? > [...] Check has been added in the kaslr in order to avoid the region marked by > memmap. What does this mean? > Signed-off-by: Dave Jiang > --- > arch/x86/boot/boot.h | 2 ++ > arch/x86/boot/compressed/kaslr.c | 45 ++++++++++++++++++++++++++++++++++++++ > arch/x86/boot/string.c | 25 +++++++++++++++++++++ > 3 files changed, 72 insertions(+) > > diff --git a/arch/x86/boot/boot.h b/arch/x86/boot/boot.h > index e5612f3..0d5fe5b 100644 > --- a/arch/x86/boot/boot.h > +++ b/arch/x86/boot/boot.h > @@ -332,6 +332,8 @@ int strncmp(const char *cs, const char *ct, size_t count); > size_t strnlen(const char *s, size_t maxlen); > unsigned int atou(const char *s); > unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base); > +unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base); > +long simple_strtol(const char *cp, char **endp, unsigned int base); > size_t strlen(const char *s); > > /* tty.c */ > diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c > index a66854d..6fb8f1ec 100644 > --- a/arch/x86/boot/compressed/kaslr.c > +++ b/arch/x86/boot/compressed/kaslr.c > @@ -11,6 +11,7 @@ > */ > #include "misc.h" > #include "error.h" > +#include "../boot.h" > > #include > #include > @@ -61,6 +62,7 @@ enum mem_avoid_index { > MEM_AVOID_INITRD, > MEM_AVOID_CMDLINE, > MEM_AVOID_BOOTPARAMS, > + MEM_AVOID_MEMMAP, > MEM_AVOID_MAX, > }; > > @@ -77,6 +79,37 @@ static bool mem_overlaps(struct mem_vector *one, struct mem_vector *two) > return true; > } > > +#include "../../../../lib/cmdline.c" > + > +static int > +parse_memmap(char *p, unsigned long long *start, unsigned long long *size) > +{ > + char *oldp; > + > + if (!p) > + return -EINVAL; > + > + /* we don't care about this option here */ > + if (!strncmp(p, "exactmap", 8)) > + return -EINVAL; > + > + oldp = p; > + *size = memparse(p, &p); > + if (p == oldp) > + return -EINVAL; > + > + switch (*p) { > + case '@': > + case '#': > + case '$': > + case '!': > + *start = memparse(p+1, &p); > + return 0; > + } > + > + return -EINVAL; > +} > + > /* > * In theory, KASLR can put the kernel anywhere in the range of [16M, 64T). > * The mem_avoid array is used to store the ranges that need to be avoided > @@ -158,6 +191,8 @@ static void mem_avoid_init(unsigned long input, unsigned long input_size, > u64 initrd_start, initrd_size; > u64 cmd_line, cmd_line_size; > char *ptr; > + char arg[38]; Where does the magic '38' come from? > + unsigned long long memmap_start, memmap_size; > > /* > * Avoid the region that is unsafe to overlap during > @@ -195,6 +230,16 @@ static void mem_avoid_init(unsigned long input, unsigned long input_size, > add_identity_map(mem_avoid[MEM_AVOID_BOOTPARAMS].start, > mem_avoid[MEM_AVOID_BOOTPARAMS].size); > > + /* see if we have any memmap areas */ > + if (cmdline_find_option("memmap", arg, sizeof(arg)) > 0) { > + int rc = parse_memmap(arg, &memmap_start, &memmap_size); > + > + if (!rc) { > + mem_avoid[MEM_AVOID_MEMMAP].start = memmap_start; > + mem_avoid[MEM_AVOID_MEMMAP].size = memmap_size; > + } > + } > + This only handles a single (first) memmap argument, is that sufficient? Thanks, Ingo