Re: [PATCH v4 2/3] KASLR: Handle memory limit specified by memmap and mem option

2017-05-11 Thread Baoquan He
On 05/12/17 at 01:15pm, Masayoshi Mizuma wrote:
> Hi Baoquan,
> 
> Thank you for fixing!
> I confirmed that the kernel is located within mem= address.
> 
> Tested-by: Masayoshi Mizuma 

Thanks for your testing!

I will post v5 according to comments from Thomas and Kees. Since no
functionality code change, will add your Tested-by.

Thanks
Baoquan

> 
> On Tue, 9 May 2017 13:57:51 +0800 Baoquan He wrote:
> 
> > Option mem= will limit the max address a system can use and any memory
> > region above the limit will be removed.
> > 
> > Furthermore, memmap=nn[KMG] which has no offset specified has the same
> > behaviour as mem=.
> > 
> > KASLR needs to consider this when choosing the random position for
> > decompressing the kernel.
> > 
> > This patch implements that.
> > 
> > Signed-off-by: Baoquan He 
> > ---
> >  arch/x86/boot/compressed/kaslr.c | 69 
> > +---
> >  1 file changed, 51 insertions(+), 18 deletions(-)
> > 
> > diff --git a/arch/x86/boot/compressed/kaslr.c 
> > b/arch/x86/boot/compressed/kaslr.c
> > index 106e13b..0637e85 100644
> > --- a/arch/x86/boot/compressed/kaslr.c
> > +++ b/arch/x86/boot/compressed/kaslr.c
> > @@ -88,6 +88,10 @@ struct mem_vector {
> >  static bool memmap_too_large;
> >  
> >  
> > +/* Store memory limit specified by "mem=nn[KMG]" or "memmap=nn[KMG]" */
> > +unsigned long long mem_limit = ULLONG_MAX;
> > +
> > +
> >  enum mem_avoid_index {
> > MEM_AVOID_ZO_RANGE = 0,
> > MEM_AVOID_INITRD,
> > @@ -138,16 +142,24 @@ parse_memmap(char *p, unsigned long long *start, 
> > unsigned long long *size)
> > return -EINVAL;
> >  
> > switch (*p) {
> > -   case '@':
> > -   /* Skip this region, usable */
> > -   *start = 0;
> > -   *size = 0;
> > -   return 0;
> > case '#':
> > case '$':
> > case '!':
> > *start = memparse(p + 1, );
> > return 0;
> > +   case '@':   /* Fall through: */
> > +   /*
> > +* memmap=nn@ss specifies usable region, should be skipped
> > +*/
> > +   *size = 0;
> > +   default:
> > +   /*
> > +* If w/o offset, only size specified, memmap=nn[KMG] has the
> > +* same behaviour as mem=nn[KMG]. It limits the max address
> > +* system can use. Region above the limit should be avoided.
> > +*/
> > +   *start = 0;
> > +   return 0;
> > }
> >  
> > return -EINVAL;
> > @@ -173,9 +185,14 @@ static void mem_avoid_memmap(char *str)
> > if (rc < 0)
> > break;
> > str = k;
> > -   /* A usable region that should not be skipped */
> > -   if (size == 0)
> > +
> > +   if (start == 0) {
> > +   /* Store the specified memory limit if size > 0 */
> > +   if (size > 0)
> > +   mem_limit = size;
> > +
> > continue;
> > +   }
> >  
> > mem_avoid[MEM_AVOID_MEMMAP_BEGIN + i].start = start;
> > mem_avoid[MEM_AVOID_MEMMAP_BEGIN + i].size = size;
> > @@ -187,19 +204,15 @@ static void mem_avoid_memmap(char *str)
> > memmap_too_large = true;
> >  }
> >  
> > -
> > -/*
> > - * handle_mem_memmap will also cover 'mem=' issue in next patch. Will 
> > remove
> > - * this note later.
> > - */
> >  static int handle_mem_memmap(void)
> >  {
> > char *args = (char *)get_cmd_line_ptr();
> > size_t len = strlen((char *)args);
> > char *tmp_cmdline;
> > char *param, *val;
> > +   u64 mem_size;
> >  
> > -   if (!strstr(args, "memmap="))
> > +   if (!strstr(args, "memmap=") && !strstr(args, "mem="))
> > return 0;
> >  
> > tmp_cmdline = malloc(len + 1);
> > @@ -222,8 +235,20 @@ static int handle_mem_memmap(void)
> > return -1;
> > }
> >  
> > -   if (!strcmp(param, "memmap"))
> > +   if (!strcmp(param, "memmap")) {
> > mem_avoid_memmap(val);
> > +   } else if (!strcmp(param, "mem")) {
> > +   char *p = val;
> > +
> > +   if (!strcmp(p, "nopentium"))
> > +   continue;
> > +   mem_size = memparse(p, );
> > +   if (mem_size == 0) {
> > +   free(tmp_cmdline);
> > +   return -EINVAL;
> > +   }
> > +   mem_limit = mem_size;
> > +   }
> > }
> >  
> > free(tmp_cmdline);
> > @@ -460,7 +485,8 @@ static void process_e820_entry(struct boot_e820_entry 
> > *entry,
> >  {
> > struct mem_vector region, overlap;
> > struct slot_area slot_area;
> > -   unsigned long start_orig;
> > +   unsigned long start_orig, end;
> > +   struct boot_e820_entry cur_entry;
> >  
> > /* Skip non-RAM entries. */
> > if (entry->type != E820_TYPE_RAM)
> > @@ -474,8 

Re: [PATCH v4 2/3] KASLR: Handle memory limit specified by memmap and mem option

2017-05-11 Thread Baoquan He
On 05/12/17 at 01:15pm, Masayoshi Mizuma wrote:
> Hi Baoquan,
> 
> Thank you for fixing!
> I confirmed that the kernel is located within mem= address.
> 
> Tested-by: Masayoshi Mizuma 

Thanks for your testing!

I will post v5 according to comments from Thomas and Kees. Since no
functionality code change, will add your Tested-by.

Thanks
Baoquan

> 
> On Tue, 9 May 2017 13:57:51 +0800 Baoquan He wrote:
> 
> > Option mem= will limit the max address a system can use and any memory
> > region above the limit will be removed.
> > 
> > Furthermore, memmap=nn[KMG] which has no offset specified has the same
> > behaviour as mem=.
> > 
> > KASLR needs to consider this when choosing the random position for
> > decompressing the kernel.
> > 
> > This patch implements that.
> > 
> > Signed-off-by: Baoquan He 
> > ---
> >  arch/x86/boot/compressed/kaslr.c | 69 
> > +---
> >  1 file changed, 51 insertions(+), 18 deletions(-)
> > 
> > diff --git a/arch/x86/boot/compressed/kaslr.c 
> > b/arch/x86/boot/compressed/kaslr.c
> > index 106e13b..0637e85 100644
> > --- a/arch/x86/boot/compressed/kaslr.c
> > +++ b/arch/x86/boot/compressed/kaslr.c
> > @@ -88,6 +88,10 @@ struct mem_vector {
> >  static bool memmap_too_large;
> >  
> >  
> > +/* Store memory limit specified by "mem=nn[KMG]" or "memmap=nn[KMG]" */
> > +unsigned long long mem_limit = ULLONG_MAX;
> > +
> > +
> >  enum mem_avoid_index {
> > MEM_AVOID_ZO_RANGE = 0,
> > MEM_AVOID_INITRD,
> > @@ -138,16 +142,24 @@ parse_memmap(char *p, unsigned long long *start, 
> > unsigned long long *size)
> > return -EINVAL;
> >  
> > switch (*p) {
> > -   case '@':
> > -   /* Skip this region, usable */
> > -   *start = 0;
> > -   *size = 0;
> > -   return 0;
> > case '#':
> > case '$':
> > case '!':
> > *start = memparse(p + 1, );
> > return 0;
> > +   case '@':   /* Fall through: */
> > +   /*
> > +* memmap=nn@ss specifies usable region, should be skipped
> > +*/
> > +   *size = 0;
> > +   default:
> > +   /*
> > +* If w/o offset, only size specified, memmap=nn[KMG] has the
> > +* same behaviour as mem=nn[KMG]. It limits the max address
> > +* system can use. Region above the limit should be avoided.
> > +*/
> > +   *start = 0;
> > +   return 0;
> > }
> >  
> > return -EINVAL;
> > @@ -173,9 +185,14 @@ static void mem_avoid_memmap(char *str)
> > if (rc < 0)
> > break;
> > str = k;
> > -   /* A usable region that should not be skipped */
> > -   if (size == 0)
> > +
> > +   if (start == 0) {
> > +   /* Store the specified memory limit if size > 0 */
> > +   if (size > 0)
> > +   mem_limit = size;
> > +
> > continue;
> > +   }
> >  
> > mem_avoid[MEM_AVOID_MEMMAP_BEGIN + i].start = start;
> > mem_avoid[MEM_AVOID_MEMMAP_BEGIN + i].size = size;
> > @@ -187,19 +204,15 @@ static void mem_avoid_memmap(char *str)
> > memmap_too_large = true;
> >  }
> >  
> > -
> > -/*
> > - * handle_mem_memmap will also cover 'mem=' issue in next patch. Will 
> > remove
> > - * this note later.
> > - */
> >  static int handle_mem_memmap(void)
> >  {
> > char *args = (char *)get_cmd_line_ptr();
> > size_t len = strlen((char *)args);
> > char *tmp_cmdline;
> > char *param, *val;
> > +   u64 mem_size;
> >  
> > -   if (!strstr(args, "memmap="))
> > +   if (!strstr(args, "memmap=") && !strstr(args, "mem="))
> > return 0;
> >  
> > tmp_cmdline = malloc(len + 1);
> > @@ -222,8 +235,20 @@ static int handle_mem_memmap(void)
> > return -1;
> > }
> >  
> > -   if (!strcmp(param, "memmap"))
> > +   if (!strcmp(param, "memmap")) {
> > mem_avoid_memmap(val);
> > +   } else if (!strcmp(param, "mem")) {
> > +   char *p = val;
> > +
> > +   if (!strcmp(p, "nopentium"))
> > +   continue;
> > +   mem_size = memparse(p, );
> > +   if (mem_size == 0) {
> > +   free(tmp_cmdline);
> > +   return -EINVAL;
> > +   }
> > +   mem_limit = mem_size;
> > +   }
> > }
> >  
> > free(tmp_cmdline);
> > @@ -460,7 +485,8 @@ static void process_e820_entry(struct boot_e820_entry 
> > *entry,
> >  {
> > struct mem_vector region, overlap;
> > struct slot_area slot_area;
> > -   unsigned long start_orig;
> > +   unsigned long start_orig, end;
> > +   struct boot_e820_entry cur_entry;
> >  
> > /* Skip non-RAM entries. */
> > if (entry->type != E820_TYPE_RAM)
> > @@ -474,8 +500,15 @@ static void 

Re: [PATCH v4 2/3] KASLR: Handle memory limit specified by memmap and mem option

2017-05-11 Thread Masayoshi Mizuma
Hi Baoquan,

Thank you for fixing!
I confirmed that the kernel is located within mem= address.

Tested-by: Masayoshi Mizuma 

Regards,
Masayoshi Mizuma

On Tue, 9 May 2017 13:57:51 +0800 Baoquan He wrote:

> Option mem= will limit the max address a system can use and any memory
> region above the limit will be removed.
> 
> Furthermore, memmap=nn[KMG] which has no offset specified has the same
> behaviour as mem=.
> 
> KASLR needs to consider this when choosing the random position for
> decompressing the kernel.
> 
> This patch implements that.
> 
> Signed-off-by: Baoquan He 
> ---
>  arch/x86/boot/compressed/kaslr.c | 69 
> +---
>  1 file changed, 51 insertions(+), 18 deletions(-)
> 
> diff --git a/arch/x86/boot/compressed/kaslr.c 
> b/arch/x86/boot/compressed/kaslr.c
> index 106e13b..0637e85 100644
> --- a/arch/x86/boot/compressed/kaslr.c
> +++ b/arch/x86/boot/compressed/kaslr.c
> @@ -88,6 +88,10 @@ struct mem_vector {
>  static bool memmap_too_large;
>  
>  
> +/* Store memory limit specified by "mem=nn[KMG]" or "memmap=nn[KMG]" */
> +unsigned long long mem_limit = ULLONG_MAX;
> +
> +
>  enum mem_avoid_index {
>   MEM_AVOID_ZO_RANGE = 0,
>   MEM_AVOID_INITRD,
> @@ -138,16 +142,24 @@ parse_memmap(char *p, unsigned long long *start, 
> unsigned long long *size)
>   return -EINVAL;
>  
>   switch (*p) {
> - case '@':
> - /* Skip this region, usable */
> - *start = 0;
> - *size = 0;
> - return 0;
>   case '#':
>   case '$':
>   case '!':
>   *start = memparse(p + 1, );
>   return 0;
> + case '@':   /* Fall through: */
> + /*
> +  * memmap=nn@ss specifies usable region, should be skipped
> +  */
> + *size = 0;
> + default:
> + /*
> +  * If w/o offset, only size specified, memmap=nn[KMG] has the
> +  * same behaviour as mem=nn[KMG]. It limits the max address
> +  * system can use. Region above the limit should be avoided.
> +  */
> + *start = 0;
> + return 0;
>   }
>  
>   return -EINVAL;
> @@ -173,9 +185,14 @@ static void mem_avoid_memmap(char *str)
>   if (rc < 0)
>   break;
>   str = k;
> - /* A usable region that should not be skipped */
> - if (size == 0)
> +
> + if (start == 0) {
> + /* Store the specified memory limit if size > 0 */
> + if (size > 0)
> + mem_limit = size;
> +
>   continue;
> + }
>  
>   mem_avoid[MEM_AVOID_MEMMAP_BEGIN + i].start = start;
>   mem_avoid[MEM_AVOID_MEMMAP_BEGIN + i].size = size;
> @@ -187,19 +204,15 @@ static void mem_avoid_memmap(char *str)
>   memmap_too_large = true;
>  }
>  
> -
> -/*
> - * handle_mem_memmap will also cover 'mem=' issue in next patch. Will remove
> - * this note later.
> - */
>  static int handle_mem_memmap(void)
>  {
>   char *args = (char *)get_cmd_line_ptr();
>   size_t len = strlen((char *)args);
>   char *tmp_cmdline;
>   char *param, *val;
> + u64 mem_size;
>  
> - if (!strstr(args, "memmap="))
> + if (!strstr(args, "memmap=") && !strstr(args, "mem="))
>   return 0;
>  
>   tmp_cmdline = malloc(len + 1);
> @@ -222,8 +235,20 @@ static int handle_mem_memmap(void)
>   return -1;
>   }
>  
> - if (!strcmp(param, "memmap"))
> + if (!strcmp(param, "memmap")) {
>   mem_avoid_memmap(val);
> + } else if (!strcmp(param, "mem")) {
> + char *p = val;
> +
> + if (!strcmp(p, "nopentium"))
> + continue;
> + mem_size = memparse(p, );
> + if (mem_size == 0) {
> + free(tmp_cmdline);
> + return -EINVAL;
> + }
> + mem_limit = mem_size;
> + }
>   }
>  
>   free(tmp_cmdline);
> @@ -460,7 +485,8 @@ static void process_e820_entry(struct boot_e820_entry 
> *entry,
>  {
>   struct mem_vector region, overlap;
>   struct slot_area slot_area;
> - unsigned long start_orig;
> + unsigned long start_orig, end;
> + struct boot_e820_entry cur_entry;
>  
>   /* Skip non-RAM entries. */
>   if (entry->type != E820_TYPE_RAM)
> @@ -474,8 +500,15 @@ static void process_e820_entry(struct boot_e820_entry 
> *entry,
>   if (entry->addr + entry->size < minimum)
>   return;
>  
> - region.start = entry->addr;
> - region.size = entry->size;
> + /* Ignore entries above memory limit */
> + end = min(entry->size + entry->addr, 

Re: [PATCH v4 2/3] KASLR: Handle memory limit specified by memmap and mem option

2017-05-11 Thread Masayoshi Mizuma
Hi Baoquan,

Thank you for fixing!
I confirmed that the kernel is located within mem= address.

Tested-by: Masayoshi Mizuma 

Regards,
Masayoshi Mizuma

On Tue, 9 May 2017 13:57:51 +0800 Baoquan He wrote:

> Option mem= will limit the max address a system can use and any memory
> region above the limit will be removed.
> 
> Furthermore, memmap=nn[KMG] which has no offset specified has the same
> behaviour as mem=.
> 
> KASLR needs to consider this when choosing the random position for
> decompressing the kernel.
> 
> This patch implements that.
> 
> Signed-off-by: Baoquan He 
> ---
>  arch/x86/boot/compressed/kaslr.c | 69 
> +---
>  1 file changed, 51 insertions(+), 18 deletions(-)
> 
> diff --git a/arch/x86/boot/compressed/kaslr.c 
> b/arch/x86/boot/compressed/kaslr.c
> index 106e13b..0637e85 100644
> --- a/arch/x86/boot/compressed/kaslr.c
> +++ b/arch/x86/boot/compressed/kaslr.c
> @@ -88,6 +88,10 @@ struct mem_vector {
>  static bool memmap_too_large;
>  
>  
> +/* Store memory limit specified by "mem=nn[KMG]" or "memmap=nn[KMG]" */
> +unsigned long long mem_limit = ULLONG_MAX;
> +
> +
>  enum mem_avoid_index {
>   MEM_AVOID_ZO_RANGE = 0,
>   MEM_AVOID_INITRD,
> @@ -138,16 +142,24 @@ parse_memmap(char *p, unsigned long long *start, 
> unsigned long long *size)
>   return -EINVAL;
>  
>   switch (*p) {
> - case '@':
> - /* Skip this region, usable */
> - *start = 0;
> - *size = 0;
> - return 0;
>   case '#':
>   case '$':
>   case '!':
>   *start = memparse(p + 1, );
>   return 0;
> + case '@':   /* Fall through: */
> + /*
> +  * memmap=nn@ss specifies usable region, should be skipped
> +  */
> + *size = 0;
> + default:
> + /*
> +  * If w/o offset, only size specified, memmap=nn[KMG] has the
> +  * same behaviour as mem=nn[KMG]. It limits the max address
> +  * system can use. Region above the limit should be avoided.
> +  */
> + *start = 0;
> + return 0;
>   }
>  
>   return -EINVAL;
> @@ -173,9 +185,14 @@ static void mem_avoid_memmap(char *str)
>   if (rc < 0)
>   break;
>   str = k;
> - /* A usable region that should not be skipped */
> - if (size == 0)
> +
> + if (start == 0) {
> + /* Store the specified memory limit if size > 0 */
> + if (size > 0)
> + mem_limit = size;
> +
>   continue;
> + }
>  
>   mem_avoid[MEM_AVOID_MEMMAP_BEGIN + i].start = start;
>   mem_avoid[MEM_AVOID_MEMMAP_BEGIN + i].size = size;
> @@ -187,19 +204,15 @@ static void mem_avoid_memmap(char *str)
>   memmap_too_large = true;
>  }
>  
> -
> -/*
> - * handle_mem_memmap will also cover 'mem=' issue in next patch. Will remove
> - * this note later.
> - */
>  static int handle_mem_memmap(void)
>  {
>   char *args = (char *)get_cmd_line_ptr();
>   size_t len = strlen((char *)args);
>   char *tmp_cmdline;
>   char *param, *val;
> + u64 mem_size;
>  
> - if (!strstr(args, "memmap="))
> + if (!strstr(args, "memmap=") && !strstr(args, "mem="))
>   return 0;
>  
>   tmp_cmdline = malloc(len + 1);
> @@ -222,8 +235,20 @@ static int handle_mem_memmap(void)
>   return -1;
>   }
>  
> - if (!strcmp(param, "memmap"))
> + if (!strcmp(param, "memmap")) {
>   mem_avoid_memmap(val);
> + } else if (!strcmp(param, "mem")) {
> + char *p = val;
> +
> + if (!strcmp(p, "nopentium"))
> + continue;
> + mem_size = memparse(p, );
> + if (mem_size == 0) {
> + free(tmp_cmdline);
> + return -EINVAL;
> + }
> + mem_limit = mem_size;
> + }
>   }
>  
>   free(tmp_cmdline);
> @@ -460,7 +485,8 @@ static void process_e820_entry(struct boot_e820_entry 
> *entry,
>  {
>   struct mem_vector region, overlap;
>   struct slot_area slot_area;
> - unsigned long start_orig;
> + unsigned long start_orig, end;
> + struct boot_e820_entry cur_entry;
>  
>   /* Skip non-RAM entries. */
>   if (entry->type != E820_TYPE_RAM)
> @@ -474,8 +500,15 @@ static void process_e820_entry(struct boot_e820_entry 
> *entry,
>   if (entry->addr + entry->size < minimum)
>   return;
>  
> - region.start = entry->addr;
> - region.size = entry->size;
> + /* Ignore entries above memory limit */
> + end = min(entry->size + entry->addr, mem_limit);
> + if (entry->addr >= end)
> +  

Re: [PATCH v4 2/3] KASLR: Handle memory limit specified by memmap and mem option

2017-05-09 Thread Baoquan He
On 05/09/17 at 10:39am, Kees Cook wrote:
> On Mon, May 8, 2017 at 10:57 PM, Baoquan He  wrote:
> > Option mem= will limit the max address a system can use and any memory
> > region above the limit will be removed.
> >
> > Furthermore, memmap=nn[KMG] which has no offset specified has the same
> > behaviour as mem=.
> >
> > KASLR needs to consider this when choosing the random position for
> > decompressing the kernel.
> >
> > This patch implements that.
> >
> > Signed-off-by: Baoquan He 
> > ---
> >  arch/x86/boot/compressed/kaslr.c | 69 
> > +---
> >  1 file changed, 51 insertions(+), 18 deletions(-)
> >
> > diff --git a/arch/x86/boot/compressed/kaslr.c 
> > b/arch/x86/boot/compressed/kaslr.c
> > index 106e13b..0637e85 100644
> > --- a/arch/x86/boot/compressed/kaslr.c
> > +++ b/arch/x86/boot/compressed/kaslr.c
> > @@ -88,6 +88,10 @@ struct mem_vector {
> >  static bool memmap_too_large;
> >
> >
> > +/* Store memory limit specified by "mem=nn[KMG]" or "memmap=nn[KMG]" */
> > +unsigned long long mem_limit = ULLONG_MAX;
> > +
> > +
> >  enum mem_avoid_index {
> > MEM_AVOID_ZO_RANGE = 0,
> > MEM_AVOID_INITRD,
> > @@ -138,16 +142,24 @@ parse_memmap(char *p, unsigned long long *start, 
> > unsigned long long *size)
> > return -EINVAL;
> >
> > switch (*p) {
> > -   case '@':
> > -   /* Skip this region, usable */
> > -   *start = 0;
> > -   *size = 0;
> > -   return 0;
> > case '#':
> > case '$':
> > case '!':
> > *start = memparse(p + 1, );
> > return 0;
> > +   case '@':   /* Fall through: */
> > +   /*
> > +* memmap=nn@ss specifies usable region, should be skipped
> > +*/
> > +   *size = 0;
> 
> The "fall through" comment should go here (where the break is "missing").

Ah, OK, will change and repost after patch 1/3 reviewing. Thanks a lot!

> 
> > +   default:
> > +   /*
> > +* If w/o offset, only size specified, memmap=nn[KMG] has 
> > the
> > +* same behaviour as mem=nn[KMG]. It limits the max address
> > +* system can use. Region above the limit should be avoided.
> > +*/
> > +   *start = 0;
> > +   return 0;
> > }
> >
> > return -EINVAL;
> > @@ -173,9 +185,14 @@ static void mem_avoid_memmap(char *str)
> > if (rc < 0)
> > break;
> > str = k;
> > -   /* A usable region that should not be skipped */
> > -   if (size == 0)
> > +
> > +   if (start == 0) {
> > +   /* Store the specified memory limit if size > 0 */
> > +   if (size > 0)
> > +   mem_limit = size;
> > +
> > continue;
> > +   }
> >
> > mem_avoid[MEM_AVOID_MEMMAP_BEGIN + i].start = start;
> > mem_avoid[MEM_AVOID_MEMMAP_BEGIN + i].size = size;
> > @@ -187,19 +204,15 @@ static void mem_avoid_memmap(char *str)
> > memmap_too_large = true;
> >  }
> >
> > -
> > -/*
> > - * handle_mem_memmap will also cover 'mem=' issue in next patch. Will 
> > remove
> > - * this note later.
> > - */
> >  static int handle_mem_memmap(void)
> >  {
> > char *args = (char *)get_cmd_line_ptr();
> > size_t len = strlen((char *)args);
> > char *tmp_cmdline;
> > char *param, *val;
> > +   u64 mem_size;
> >
> > -   if (!strstr(args, "memmap="))
> > +   if (!strstr(args, "memmap=") && !strstr(args, "mem="))
> > return 0;
> >
> > tmp_cmdline = malloc(len + 1);
> > @@ -222,8 +235,20 @@ static int handle_mem_memmap(void)
> > return -1;
> > }
> >
> > -   if (!strcmp(param, "memmap"))
> > +   if (!strcmp(param, "memmap")) {
> > mem_avoid_memmap(val);
> > +   } else if (!strcmp(param, "mem")) {
> > +   char *p = val;
> > +
> > +   if (!strcmp(p, "nopentium"))
> > +   continue;
> > +   mem_size = memparse(p, );
> > +   if (mem_size == 0) {
> > +   free(tmp_cmdline);
> > +   return -EINVAL;
> > +   }
> > +   mem_limit = mem_size;
> > +   }
> > }
> >
> > free(tmp_cmdline);
> > @@ -460,7 +485,8 @@ static void process_e820_entry(struct boot_e820_entry 
> > *entry,
> >  {
> > struct mem_vector region, overlap;
> > struct slot_area slot_area;
> > -   unsigned long start_orig;
> > +   unsigned long start_orig, end;
> > +   struct 

Re: [PATCH v4 2/3] KASLR: Handle memory limit specified by memmap and mem option

2017-05-09 Thread Baoquan He
On 05/09/17 at 10:39am, Kees Cook wrote:
> On Mon, May 8, 2017 at 10:57 PM, Baoquan He  wrote:
> > Option mem= will limit the max address a system can use and any memory
> > region above the limit will be removed.
> >
> > Furthermore, memmap=nn[KMG] which has no offset specified has the same
> > behaviour as mem=.
> >
> > KASLR needs to consider this when choosing the random position for
> > decompressing the kernel.
> >
> > This patch implements that.
> >
> > Signed-off-by: Baoquan He 
> > ---
> >  arch/x86/boot/compressed/kaslr.c | 69 
> > +---
> >  1 file changed, 51 insertions(+), 18 deletions(-)
> >
> > diff --git a/arch/x86/boot/compressed/kaslr.c 
> > b/arch/x86/boot/compressed/kaslr.c
> > index 106e13b..0637e85 100644
> > --- a/arch/x86/boot/compressed/kaslr.c
> > +++ b/arch/x86/boot/compressed/kaslr.c
> > @@ -88,6 +88,10 @@ struct mem_vector {
> >  static bool memmap_too_large;
> >
> >
> > +/* Store memory limit specified by "mem=nn[KMG]" or "memmap=nn[KMG]" */
> > +unsigned long long mem_limit = ULLONG_MAX;
> > +
> > +
> >  enum mem_avoid_index {
> > MEM_AVOID_ZO_RANGE = 0,
> > MEM_AVOID_INITRD,
> > @@ -138,16 +142,24 @@ parse_memmap(char *p, unsigned long long *start, 
> > unsigned long long *size)
> > return -EINVAL;
> >
> > switch (*p) {
> > -   case '@':
> > -   /* Skip this region, usable */
> > -   *start = 0;
> > -   *size = 0;
> > -   return 0;
> > case '#':
> > case '$':
> > case '!':
> > *start = memparse(p + 1, );
> > return 0;
> > +   case '@':   /* Fall through: */
> > +   /*
> > +* memmap=nn@ss specifies usable region, should be skipped
> > +*/
> > +   *size = 0;
> 
> The "fall through" comment should go here (where the break is "missing").

Ah, OK, will change and repost after patch 1/3 reviewing. Thanks a lot!

> 
> > +   default:
> > +   /*
> > +* If w/o offset, only size specified, memmap=nn[KMG] has 
> > the
> > +* same behaviour as mem=nn[KMG]. It limits the max address
> > +* system can use. Region above the limit should be avoided.
> > +*/
> > +   *start = 0;
> > +   return 0;
> > }
> >
> > return -EINVAL;
> > @@ -173,9 +185,14 @@ static void mem_avoid_memmap(char *str)
> > if (rc < 0)
> > break;
> > str = k;
> > -   /* A usable region that should not be skipped */
> > -   if (size == 0)
> > +
> > +   if (start == 0) {
> > +   /* Store the specified memory limit if size > 0 */
> > +   if (size > 0)
> > +   mem_limit = size;
> > +
> > continue;
> > +   }
> >
> > mem_avoid[MEM_AVOID_MEMMAP_BEGIN + i].start = start;
> > mem_avoid[MEM_AVOID_MEMMAP_BEGIN + i].size = size;
> > @@ -187,19 +204,15 @@ static void mem_avoid_memmap(char *str)
> > memmap_too_large = true;
> >  }
> >
> > -
> > -/*
> > - * handle_mem_memmap will also cover 'mem=' issue in next patch. Will 
> > remove
> > - * this note later.
> > - */
> >  static int handle_mem_memmap(void)
> >  {
> > char *args = (char *)get_cmd_line_ptr();
> > size_t len = strlen((char *)args);
> > char *tmp_cmdline;
> > char *param, *val;
> > +   u64 mem_size;
> >
> > -   if (!strstr(args, "memmap="))
> > +   if (!strstr(args, "memmap=") && !strstr(args, "mem="))
> > return 0;
> >
> > tmp_cmdline = malloc(len + 1);
> > @@ -222,8 +235,20 @@ static int handle_mem_memmap(void)
> > return -1;
> > }
> >
> > -   if (!strcmp(param, "memmap"))
> > +   if (!strcmp(param, "memmap")) {
> > mem_avoid_memmap(val);
> > +   } else if (!strcmp(param, "mem")) {
> > +   char *p = val;
> > +
> > +   if (!strcmp(p, "nopentium"))
> > +   continue;
> > +   mem_size = memparse(p, );
> > +   if (mem_size == 0) {
> > +   free(tmp_cmdline);
> > +   return -EINVAL;
> > +   }
> > +   mem_limit = mem_size;
> > +   }
> > }
> >
> > free(tmp_cmdline);
> > @@ -460,7 +485,8 @@ static void process_e820_entry(struct boot_e820_entry 
> > *entry,
> >  {
> > struct mem_vector region, overlap;
> > struct slot_area slot_area;
> > -   unsigned long start_orig;
> > +   unsigned long start_orig, end;
> > +   struct boot_e820_entry cur_entry;
> >
> > 

Re: [PATCH v4 2/3] KASLR: Handle memory limit specified by memmap and mem option

2017-05-09 Thread Kees Cook
On Mon, May 8, 2017 at 10:57 PM, Baoquan He  wrote:
> Option mem= will limit the max address a system can use and any memory
> region above the limit will be removed.
>
> Furthermore, memmap=nn[KMG] which has no offset specified has the same
> behaviour as mem=.
>
> KASLR needs to consider this when choosing the random position for
> decompressing the kernel.
>
> This patch implements that.
>
> Signed-off-by: Baoquan He 
> ---
>  arch/x86/boot/compressed/kaslr.c | 69 
> +---
>  1 file changed, 51 insertions(+), 18 deletions(-)
>
> diff --git a/arch/x86/boot/compressed/kaslr.c 
> b/arch/x86/boot/compressed/kaslr.c
> index 106e13b..0637e85 100644
> --- a/arch/x86/boot/compressed/kaslr.c
> +++ b/arch/x86/boot/compressed/kaslr.c
> @@ -88,6 +88,10 @@ struct mem_vector {
>  static bool memmap_too_large;
>
>
> +/* Store memory limit specified by "mem=nn[KMG]" or "memmap=nn[KMG]" */
> +unsigned long long mem_limit = ULLONG_MAX;
> +
> +
>  enum mem_avoid_index {
> MEM_AVOID_ZO_RANGE = 0,
> MEM_AVOID_INITRD,
> @@ -138,16 +142,24 @@ parse_memmap(char *p, unsigned long long *start, 
> unsigned long long *size)
> return -EINVAL;
>
> switch (*p) {
> -   case '@':
> -   /* Skip this region, usable */
> -   *start = 0;
> -   *size = 0;
> -   return 0;
> case '#':
> case '$':
> case '!':
> *start = memparse(p + 1, );
> return 0;
> +   case '@':   /* Fall through: */
> +   /*
> +* memmap=nn@ss specifies usable region, should be skipped
> +*/
> +   *size = 0;

The "fall through" comment should go here (where the break is "missing").

> +   default:
> +   /*
> +* If w/o offset, only size specified, memmap=nn[KMG] has the
> +* same behaviour as mem=nn[KMG]. It limits the max address
> +* system can use. Region above the limit should be avoided.
> +*/
> +   *start = 0;
> +   return 0;
> }
>
> return -EINVAL;
> @@ -173,9 +185,14 @@ static void mem_avoid_memmap(char *str)
> if (rc < 0)
> break;
> str = k;
> -   /* A usable region that should not be skipped */
> -   if (size == 0)
> +
> +   if (start == 0) {
> +   /* Store the specified memory limit if size > 0 */
> +   if (size > 0)
> +   mem_limit = size;
> +
> continue;
> +   }
>
> mem_avoid[MEM_AVOID_MEMMAP_BEGIN + i].start = start;
> mem_avoid[MEM_AVOID_MEMMAP_BEGIN + i].size = size;
> @@ -187,19 +204,15 @@ static void mem_avoid_memmap(char *str)
> memmap_too_large = true;
>  }
>
> -
> -/*
> - * handle_mem_memmap will also cover 'mem=' issue in next patch. Will remove
> - * this note later.
> - */
>  static int handle_mem_memmap(void)
>  {
> char *args = (char *)get_cmd_line_ptr();
> size_t len = strlen((char *)args);
> char *tmp_cmdline;
> char *param, *val;
> +   u64 mem_size;
>
> -   if (!strstr(args, "memmap="))
> +   if (!strstr(args, "memmap=") && !strstr(args, "mem="))
> return 0;
>
> tmp_cmdline = malloc(len + 1);
> @@ -222,8 +235,20 @@ static int handle_mem_memmap(void)
> return -1;
> }
>
> -   if (!strcmp(param, "memmap"))
> +   if (!strcmp(param, "memmap")) {
> mem_avoid_memmap(val);
> +   } else if (!strcmp(param, "mem")) {
> +   char *p = val;
> +
> +   if (!strcmp(p, "nopentium"))
> +   continue;
> +   mem_size = memparse(p, );
> +   if (mem_size == 0) {
> +   free(tmp_cmdline);
> +   return -EINVAL;
> +   }
> +   mem_limit = mem_size;
> +   }
> }
>
> free(tmp_cmdline);
> @@ -460,7 +485,8 @@ static void process_e820_entry(struct boot_e820_entry 
> *entry,
>  {
> struct mem_vector region, overlap;
> struct slot_area slot_area;
> -   unsigned long start_orig;
> +   unsigned long start_orig, end;
> +   struct boot_e820_entry cur_entry;
>
> /* Skip non-RAM entries. */
> if (entry->type != E820_TYPE_RAM)
> @@ -474,8 +500,15 @@ static void process_e820_entry(struct boot_e820_entry 
> *entry,
> if (entry->addr + entry->size < minimum)
> return;
>
> -   region.start = entry->addr;
> -   region.size = entry->size;
> +   /* Ignore entries above memory limit */
> +

Re: [PATCH v4 2/3] KASLR: Handle memory limit specified by memmap and mem option

2017-05-09 Thread Kees Cook
On Mon, May 8, 2017 at 10:57 PM, Baoquan He  wrote:
> Option mem= will limit the max address a system can use and any memory
> region above the limit will be removed.
>
> Furthermore, memmap=nn[KMG] which has no offset specified has the same
> behaviour as mem=.
>
> KASLR needs to consider this when choosing the random position for
> decompressing the kernel.
>
> This patch implements that.
>
> Signed-off-by: Baoquan He 
> ---
>  arch/x86/boot/compressed/kaslr.c | 69 
> +---
>  1 file changed, 51 insertions(+), 18 deletions(-)
>
> diff --git a/arch/x86/boot/compressed/kaslr.c 
> b/arch/x86/boot/compressed/kaslr.c
> index 106e13b..0637e85 100644
> --- a/arch/x86/boot/compressed/kaslr.c
> +++ b/arch/x86/boot/compressed/kaslr.c
> @@ -88,6 +88,10 @@ struct mem_vector {
>  static bool memmap_too_large;
>
>
> +/* Store memory limit specified by "mem=nn[KMG]" or "memmap=nn[KMG]" */
> +unsigned long long mem_limit = ULLONG_MAX;
> +
> +
>  enum mem_avoid_index {
> MEM_AVOID_ZO_RANGE = 0,
> MEM_AVOID_INITRD,
> @@ -138,16 +142,24 @@ parse_memmap(char *p, unsigned long long *start, 
> unsigned long long *size)
> return -EINVAL;
>
> switch (*p) {
> -   case '@':
> -   /* Skip this region, usable */
> -   *start = 0;
> -   *size = 0;
> -   return 0;
> case '#':
> case '$':
> case '!':
> *start = memparse(p + 1, );
> return 0;
> +   case '@':   /* Fall through: */
> +   /*
> +* memmap=nn@ss specifies usable region, should be skipped
> +*/
> +   *size = 0;

The "fall through" comment should go here (where the break is "missing").

> +   default:
> +   /*
> +* If w/o offset, only size specified, memmap=nn[KMG] has the
> +* same behaviour as mem=nn[KMG]. It limits the max address
> +* system can use. Region above the limit should be avoided.
> +*/
> +   *start = 0;
> +   return 0;
> }
>
> return -EINVAL;
> @@ -173,9 +185,14 @@ static void mem_avoid_memmap(char *str)
> if (rc < 0)
> break;
> str = k;
> -   /* A usable region that should not be skipped */
> -   if (size == 0)
> +
> +   if (start == 0) {
> +   /* Store the specified memory limit if size > 0 */
> +   if (size > 0)
> +   mem_limit = size;
> +
> continue;
> +   }
>
> mem_avoid[MEM_AVOID_MEMMAP_BEGIN + i].start = start;
> mem_avoid[MEM_AVOID_MEMMAP_BEGIN + i].size = size;
> @@ -187,19 +204,15 @@ static void mem_avoid_memmap(char *str)
> memmap_too_large = true;
>  }
>
> -
> -/*
> - * handle_mem_memmap will also cover 'mem=' issue in next patch. Will remove
> - * this note later.
> - */
>  static int handle_mem_memmap(void)
>  {
> char *args = (char *)get_cmd_line_ptr();
> size_t len = strlen((char *)args);
> char *tmp_cmdline;
> char *param, *val;
> +   u64 mem_size;
>
> -   if (!strstr(args, "memmap="))
> +   if (!strstr(args, "memmap=") && !strstr(args, "mem="))
> return 0;
>
> tmp_cmdline = malloc(len + 1);
> @@ -222,8 +235,20 @@ static int handle_mem_memmap(void)
> return -1;
> }
>
> -   if (!strcmp(param, "memmap"))
> +   if (!strcmp(param, "memmap")) {
> mem_avoid_memmap(val);
> +   } else if (!strcmp(param, "mem")) {
> +   char *p = val;
> +
> +   if (!strcmp(p, "nopentium"))
> +   continue;
> +   mem_size = memparse(p, );
> +   if (mem_size == 0) {
> +   free(tmp_cmdline);
> +   return -EINVAL;
> +   }
> +   mem_limit = mem_size;
> +   }
> }
>
> free(tmp_cmdline);
> @@ -460,7 +485,8 @@ static void process_e820_entry(struct boot_e820_entry 
> *entry,
>  {
> struct mem_vector region, overlap;
> struct slot_area slot_area;
> -   unsigned long start_orig;
> +   unsigned long start_orig, end;
> +   struct boot_e820_entry cur_entry;
>
> /* Skip non-RAM entries. */
> if (entry->type != E820_TYPE_RAM)
> @@ -474,8 +500,15 @@ static void process_e820_entry(struct boot_e820_entry 
> *entry,
> if (entry->addr + entry->size < minimum)
> return;
>
> -   region.start = entry->addr;
> -   region.size = entry->size;
> +   /* Ignore entries above memory limit */
> +   end = min(entry->size +