Re: [PATCH v6 5/5] kaslr: add kaslr_mem=nn[KMG]!ss[KMG] to avoid memory regions

From: Chao Fan
Date: Mon Jan 15 2018 - 07:50:41 EST


Hi Luiz,

I don't know if this patch is OK for you.
Of coure you can only use kaslr_mem=nn@ss to solve the 1G huge page
issue. Because we know the region [0,1G] is not suitable for 1G huge
page, so you can specify ksalr_mem=1G@0 of kaslr_mem=1G to solve
your problem. But the regions may be too slow and is not good
for the randomness.

So as Kess said, I put the regions suitable for 1G huge page to
mem_avoid, you can use kaslr_mem=1G!1G to solve the problem in your
email.

Thanks,
Chao Fan

On Mon, Jan 15, 2018 at 08:40:16PM +0800, Chao Fan wrote:
>In current code, kaslr choose the only suitable memory region for 1G
>huge page, so the no suitable region for 1G huge page. So add this
>feature to store these regions.
>
>Of coure, we can use memmap= to do this job. But memmap will be handled
>in the later code, but kaslr_mem= only works in this period.
>
>It can help users to avoid more memory regions, not only the 1G huge
>huge page issue.
>
>Signed-off-by: Chao Fan <fanc.fnst@xxxxxxxxxxxxxx>
>---
> arch/x86/boot/compressed/kaslr.c | 56 +++++++++++++++++++++++++++++++++++-----
> 1 file changed, 50 insertions(+), 6 deletions(-)
>
>diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c
>index fc531fa1f10c..c71189cf8d56 100644
>--- a/arch/x86/boot/compressed/kaslr.c
>+++ b/arch/x86/boot/compressed/kaslr.c
>@@ -95,6 +95,18 @@ static bool memmap_too_large;
> /* Store memory limit specified by "mem=nn[KMG]" or "memmap=nn[KMG]" */
> unsigned long long mem_limit = ULLONG_MAX;
>
>+/*
>+ * Only supporting at most 4 unusable memory regions for
>+ * "kaslr_mem=nn[KMG]!ss[KMG]"
>+ */
>+#define MAX_KASLR_MEM_AVOID 4
>+
>+static bool kaslr_mem_avoid_too_large;
>+
>+enum kaslr_mem_type {
>+ CMD_MEM_USABLE = 1,
>+ CMD_MEM_AVOID,
>+};
>
> enum mem_avoid_index {
> MEM_AVOID_ZO_RANGE = 0,
>@@ -103,6 +115,8 @@ enum mem_avoid_index {
> MEM_AVOID_BOOTPARAMS,
> MEM_AVOID_MEMMAP_BEGIN,
> MEM_AVOID_MEMMAP_END = MEM_AVOID_MEMMAP_BEGIN + MAX_MEMMAP_REGIONS - 1,
>+ MEM_AVOID_KASLR_MEM_BEGIN,
>+ MEM_AVOID_KASLR_MEM_END = MEM_AVOID_KASLR_MEM_BEGIN + MAX_KASLR_MEM_AVOID - 1,
> MEM_AVOID_MAX,
> };
>
>@@ -217,7 +231,8 @@ static void mem_avoid_memmap(char *str)
>
> static int parse_kaslr_mem(char *p,
> unsigned long long *start,
>- unsigned long long *size)
>+ unsigned long long *size,
>+ int *cmd_type)
> {
> char *oldp;
>
>@@ -230,8 +245,13 @@ static int parse_kaslr_mem(char *p,
> return -EINVAL;
>
> switch (*p) {
>+ case '!' :
>+ *start = memparse(p + 1, &p);
>+ *cmd_type = CMD_MEM_AVOID;
>+ return 0;
> case '@':
> *start = memparse(p + 1, &p);
>+ *cmd_type = CMD_MEM_USABLE;
> return 0;
> default:
> /*
>@@ -240,6 +260,7 @@ static int parse_kaslr_mem(char *p,
> * the region starts from 0.
> */
> *start = 0;
>+ *cmd_type = CMD_MEM_USABLE;
> return 0;
> }
>
>@@ -248,26 +269,44 @@ static int parse_kaslr_mem(char *p,
>
> static void parse_kaslr_mem_regions(char *str)
> {
>- static int i;
>+ static int i = 0, j = 0;
>+ int cmd_type = 0;
>
> while (str && (i < MAX_KASLR_MEM_USABLE)) {
> int rc;
> unsigned long long start, size;
> char *k = strchr(str, ',');
>
>+ if (i >= MAX_KASLR_MEM_USABLE && j >= MAX_KASLR_MEM_AVOID)
>+ break;
>+
> if (k)
> *k++ = 0;
>
>- rc = parse_kaslr_mem(str, &start, &size);
>+ rc = parse_kaslr_mem(str, &start, &size, &cmd_type);
> if (rc < 0)
> break;
> str = k;
>
>- mem_usable[i].start = start;
>- mem_usable[i].size = size;
>- i++;
>+ if (cmd_type == CMD_MEM_USABLE) {
>+ if (i >= MAX_KASLR_MEM_USABLE)
>+ continue;
>+ mem_usable[i].start = start;
>+ mem_usable[i].size = size;
>+ i++;
>+ } else if (cmd_type == CMD_MEM_AVOID) {
>+ if (j >= MAX_KASLR_MEM_AVOID)
>+ continue;
>+ mem_avoid[MEM_AVOID_KASLR_MEM_BEGIN + j].start = start;
>+ mem_avoid[MEM_AVOID_KASLR_MEM_BEGIN + j].size = size;
>+ j++;
>+ }
> }
> num_usable_region = i;
>+
>+ /* More than 4 kaslr_mem avoid, fail kaslr */
>+ if ((j >= MAX_KASLR_MEM_AVOID) && str)
>+ kaslr_mem_avoid_too_large = true;
> }
>
> static int handle_mem_filter(void)
>@@ -799,6 +838,11 @@ static unsigned long find_random_phys_addr(unsigned long minimum,
> return 0;
> }
>
>+ /* Check if we had too many kaslr_mem avoid. */
>+ if (kaslr_mem_avoid_too_large) {
>+ debug_putstr("Aborted memory entries scan (more than 4 kaslr_mem avoid args)!\n");
>+ return 0;
>+ }
> /* Make sure minimum is aligned. */
> minimum = ALIGN(minimum, CONFIG_PHYSICAL_ALIGN);
>
>--
>2.14.3
>