All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v7 0/3] x86/boot/KASLR: Parse ACPI table and limit kaslr in immovable memory
@ 2018-09-13 10:46 ` Chao Fan
  0 siblings, 0 replies; 15+ messages in thread
From: Chao Fan @ 2018-09-13 10:46 UTC (permalink / raw)
  To: linux-efi, linux-acpi, tglx, mingo, hpa, x86, linux-kernel,
	keescook, bhe
  Cc: rjw, lenb, ard.biesheuvel, indou.takao, caoj.fnst, Chao Fan

***Background:
People reported that kaslr may randomly chooses some positions
which are located in movable memory regions. This will break memory
hotplug feature and make the movable memory chosen by KASLR can't be
removed.

***Solutions:
There should be a method to limit kaslr to choosing immovable memory
regions, so there are 2 solutions:
1) Add a kernel parameter to specify the memory regions.
2) Get the information of memory hot-remove, then kaslr will know the
   right regions.
In method 2, information about memory hot-remove is in ACPI
tables, which will be parsed after start_kernel(), kaslr can't get
the information.
In method 1, users should know the regions address and specify in
kernel parameter.

In the earliest time, I tried to dig ACPI tabls to solve this problem.
But I didn't splite the code in 'compressed/' and ACPI code, so the patch
is hard to follow so refused by community.
Somebody suggest to add a kernel parameter to specify the
immovable memory so that limit kaslr in these regions. Then I make
a new patchset. After several versions, Ingo gave a suggestion:
https://www.mail-archive.com/linux-kernel@vger.kernel.org/msg1634024.html
Follow Ingo's suggestion, imitate the ACPI code to parse the acpi
tables, so that the kaslr can get necessary memory information in
ACPI tables.
I think ACPI code is an independent part, so copy the codes
and functions to 'compressed/' directory, so that kaslr won't
influence the initialization of ACPI.

PATCH 1/3 Add acpitb.c to provide functions to parse ACPI code.
PATCH 2/3 If CONFIG_MEMORY_HOTREMOVE enabled, walk all nodes and
          store the information of immovable memory regions.
PATCH 3/3 According to the immovable memory regions, filter the
          immovable regions which KASLR can choose.

***Test results:
 - I did a very simple test, and it can get the memory information in
   bios and efi KVM guest machine, and put it by early printk. But no
   more tests, so it's with RFC tag.

v1->v2:
 -  Simplify some code.
Follow Baoquan He's suggestion:
 - Reuse the head file of acpi code.

v2->v3:
 - Test in more conditions, so remove the 'RFC' tag.
 - Change some comments.

v3->v4:
Follow Thomas Gleixner's suggetsion:
 - Put the whole efi related function into #define CONFIG_EFI and return
   false in the other stub.
 - Simplify two functions in head file.

v4->v5:
Follow Dou Liyang's suggestion:
 - Add more comments about some functions based on kernel code.
 - Change some typo in comments.
 - Clean useless variable.
 - Add check for the boundary of array.
 - Add check for 'movable_node' parameter

v5->v6:
Follow Baoquan He's suggestion:
 - Change some log.
 - Add the check for acpi_rsdp
 - Change some code logical to make code clear

v6->v7:
Follow Rafael's suggestion:
 - Add more comments and patch log.
Follow test robot's suggestion:
 - Add "static" tag for function

Any comments will be welcome.


Chao Fan (3):
  x86/boot: Add acpitb.c to parse acpi tables
  x86/boot/KASLR: Walk srat tables to filter immovable memory
  x86/boot/KASLR: Limit kaslr to choosing the immovable memory

 arch/x86/boot/compressed/Makefile |   4 +
 arch/x86/boot/compressed/acpitb.c | 401 ++++++++++++++++++++++++++++++
 arch/x86/boot/compressed/kaslr.c  |  76 +++++-
 arch/x86/boot/compressed/misc.h   |   8 +
 4 files changed, 478 insertions(+), 11 deletions(-)
 create mode 100644 arch/x86/boot/compressed/acpitb.c

-- 
2.17.1

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v7 0/3] x86/boot/KASLR: Parse ACPI table and limit kaslr in immovable memory
@ 2018-09-13 10:46 ` Chao Fan
  0 siblings, 0 replies; 15+ messages in thread
From: Chao Fan @ 2018-09-13 10:46 UTC (permalink / raw)
  To: linux-efi, linux-acpi, tglx, mingo, hpa, x86, linux-kernel,
	keescook, bhe
  Cc: rjw, lenb, ard.biesheuvel, indou.takao, caoj.fnst, Chao Fan

***Background:
People reported that kaslr may randomly chooses some positions
which are located in movable memory regions. This will break memory
hotplug feature and make the movable memory chosen by KASLR can't be
removed.

***Solutions:
There should be a method to limit kaslr to choosing immovable memory
regions, so there are 2 solutions:
1) Add a kernel parameter to specify the memory regions.
2) Get the information of memory hot-remove, then kaslr will know the
   right regions.
In method 2, information about memory hot-remove is in ACPI
tables, which will be parsed after start_kernel(), kaslr can't get
the information.
In method 1, users should know the regions address and specify in
kernel parameter.

In the earliest time, I tried to dig ACPI tabls to solve this problem.
But I didn't splite the code in 'compressed/' and ACPI code, so the patch
is hard to follow so refused by community.
Somebody suggest to add a kernel parameter to specify the
immovable memory so that limit kaslr in these regions. Then I make
a new patchset. After several versions, Ingo gave a suggestion:
https://www.mail-archive.com/linux-kernel@vger.kernel.org/msg1634024.html
Follow Ingo's suggestion, imitate the ACPI code to parse the acpi
tables, so that the kaslr can get necessary memory information in
ACPI tables.
I think ACPI code is an independent part, so copy the codes
and functions to 'compressed/' directory, so that kaslr won't
influence the initialization of ACPI.

PATCH 1/3 Add acpitb.c to provide functions to parse ACPI code.
PATCH 2/3 If CONFIG_MEMORY_HOTREMOVE enabled, walk all nodes and
          store the information of immovable memory regions.
PATCH 3/3 According to the immovable memory regions, filter the
          immovable regions which KASLR can choose.

***Test results:
 - I did a very simple test, and it can get the memory information in
   bios and efi KVM guest machine, and put it by early printk. But no
   more tests, so it's with RFC tag.

v1->v2:
 -  Simplify some code.
Follow Baoquan He's suggestion:
 - Reuse the head file of acpi code.

v2->v3:
 - Test in more conditions, so remove the 'RFC' tag.
 - Change some comments.

v3->v4:
Follow Thomas Gleixner's suggetsion:
 - Put the whole efi related function into #define CONFIG_EFI and return
   false in the other stub.
 - Simplify two functions in head file.

v4->v5:
Follow Dou Liyang's suggestion:
 - Add more comments about some functions based on kernel code.
 - Change some typo in comments.
 - Clean useless variable.
 - Add check for the boundary of array.
 - Add check for 'movable_node' parameter

v5->v6:
Follow Baoquan He's suggestion:
 - Change some log.
 - Add the check for acpi_rsdp
 - Change some code logical to make code clear

v6->v7:
Follow Rafael's suggestion:
 - Add more comments and patch log.
Follow test robot's suggestion:
 - Add "static" tag for function

Any comments will be welcome.


Chao Fan (3):
  x86/boot: Add acpitb.c to parse acpi tables
  x86/boot/KASLR: Walk srat tables to filter immovable memory
  x86/boot/KASLR: Limit kaslr to choosing the immovable memory

 arch/x86/boot/compressed/Makefile |   4 +
 arch/x86/boot/compressed/acpitb.c | 401 ++++++++++++++++++++++++++++++
 arch/x86/boot/compressed/kaslr.c  |  76 +++++-
 arch/x86/boot/compressed/misc.h   |   8 +
 4 files changed, 478 insertions(+), 11 deletions(-)
 create mode 100644 arch/x86/boot/compressed/acpitb.c

-- 
2.17.1




^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v7 1/3] x86/boot: Add acpitb.c to parse acpi tables
  2018-09-13 10:46 ` Chao Fan
@ 2018-09-13 10:46   ` Chao Fan
  -1 siblings, 0 replies; 15+ messages in thread
From: Chao Fan @ 2018-09-13 10:46 UTC (permalink / raw)
  To: linux-efi, linux-acpi, tglx, mingo, hpa, x86, linux-kernel,
	keescook, bhe
  Cc: rjw, lenb, ard.biesheuvel, indou.takao, caoj.fnst, Chao Fan

There is a bug that kaslr may randomly chooses some positions
which are located in movable memory regions. This will break memory
hotplug feature and make the movable memory chosen by KASLR can't be
removed. So dig SRAT table from ACPI tables to get memory information.

Imitate the ACPI code of parsing ACPI tables to dig and read ACPI
tables. Since some operations are not needed here, functions are
simplified. Functions will be used to dig only SRAT tables to get
information of memory, so that KASLR can the memory in immovable node.

And also, these functions won't influence the initialization of
ACPI after start_kernel().

Since use physical address directely, so acpi_os_map_memory()
and acpi_os_unmap_memory() are not needed.

Signed-off-by: Chao Fan <fanc.fnst@cn.fujitsu.com>
---
 arch/x86/boot/compressed/Makefile |   4 +
 arch/x86/boot/compressed/acpitb.c | 401 ++++++++++++++++++++++++++++++
 arch/x86/boot/compressed/misc.h   |   8 +
 3 files changed, 413 insertions(+)
 create mode 100644 arch/x86/boot/compressed/acpitb.c

diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
index 28764dacf018..394d7d93da7a 100644
--- a/arch/x86/boot/compressed/Makefile
+++ b/arch/x86/boot/compressed/Makefile
@@ -83,6 +83,10 @@ ifdef CONFIG_X86_64
 	vmlinux-objs-y += $(obj)/pgtable_64.o
 endif
 
+ifdef CONFIG_MEMORY_HOTREMOVE
+vmlinux-objs-$(CONFIG_RANDOMIZE_BASE) += $(obj)/acpitb.o
+endif
+
 $(obj)/eboot.o: KBUILD_CFLAGS += -fshort-wchar -mno-red-zone
 
 vmlinux-objs-$(CONFIG_EFI_STUB) += $(obj)/eboot.o $(obj)/efi_stub_$(BITS).o \
diff --git a/arch/x86/boot/compressed/acpitb.c b/arch/x86/boot/compressed/acpitb.c
new file mode 100644
index 000000000000..109c59b82cde
--- /dev/null
+++ b/arch/x86/boot/compressed/acpitb.c
@@ -0,0 +1,401 @@
+// SPDX-License-Identifier: GPL-2.0
+#define BOOT_CTYPE_H
+#include "misc.h"
+#include "error.h"
+
+#include <linux/efi.h>
+#include <asm/efi.h>
+#include <linux/numa.h>
+#include <linux/acpi.h>
+
+extern unsigned long get_cmd_line_ptr(void);
+
+#define STATIC
+#include <linux/decompress/mm.h>
+
+#ifdef CONFIG_MEMORY_HOTREMOVE
+struct mem_vector {
+	unsigned long long start;
+	unsigned long long size;
+};
+/* Store the immovable memory regions */
+struct mem_vector immovable_mem[MAX_NUMNODES*2];
+#endif
+
+#ifdef CONFIG_EFI
+/* Search EFI table for rsdp table. */
+static bool efi_get_rsdp_addr(acpi_physical_address *rsdp_addr)
+{
+	efi_system_table_t *systab;
+	bool find_rsdp = false;
+	bool efi_64 = false;
+	void *config_tables;
+	struct efi_info *e;
+	char *sig;
+	int size;
+	int i;
+
+	e = &boot_params->efi_info;
+	sig = (char *)&e->efi_loader_signature;
+
+	if (!strncmp(sig, EFI64_LOADER_SIGNATURE, 4))
+		efi_64 = true;
+	else if (!strncmp(sig, EFI32_LOADER_SIGNATURE, 4))
+		efi_64 = false;
+	else {
+		debug_putstr("Wrong EFI loader signature.\n");
+		return false;
+	}
+
+	/* Get systab from boot params. Based on efi_init(). */
+#ifdef CONFIG_X86_32
+	if (e->efi_systab_hi || e->efi_memmap_hi) {
+		debug_putstr("Table located above 4GB, disabling EFI.\n");
+		return false;
+	}
+	systab = (efi_system_table_t *)e->efi_systab;
+#else
+	systab = (efi_system_table_t *)(
+			e->efi_systab | ((__u64)e->efi_systab_hi<<32));
+#endif
+
+	if (systab == NULL)
+		return false;
+
+	/*
+	 * Get EFI tables from systab. Based on efi_config_init() and
+	 * efi_config_parse_tables(). Only dig the config_table.
+	 */
+	size = efi_64 ? sizeof(efi_config_table_64_t) :
+			sizeof(efi_config_table_32_t);
+
+	for (i = 0; i < systab->nr_tables; i++) {
+		efi_guid_t guid;
+		unsigned long table;
+
+		config_tables = (void *)(systab->tables + size * i);
+		if (efi_64) {
+			efi_config_table_64_t *tmp_table;
+
+			tmp_table = (efi_config_table_64_t *)config_tables;
+			guid = tmp_table->guid;
+			table = tmp_table->table;
+#ifndef CONFIG_64BIT
+			if (table >> 32) {
+				debug_putstr("Table located above 4G, disabling EFI.\n");
+				return false;
+			}
+#endif
+		} else {
+			efi_config_table_32_t *tmp_table;
+
+			tmp_table = (efi_config_table_32_t *)config_tables;
+			guid = tmp_table->guid;
+			table = tmp_table->table;
+		}
+
+		/*
+		 * Get rsdp from EFI tables.
+		 * If ACPI20 table found, use it and return true.
+		 * If ACPI20 table not found, but ACPI table found,
+		 * use the ACPI table and return true.
+		 * If neither ACPI table nor ACPI20 table found,
+		 * return false.
+		 */
+		if (!(efi_guidcmp(guid, ACPI_TABLE_GUID))) {
+			*rsdp_addr = (acpi_physical_address)table;
+			find_rsdp = true;
+		} else if (!(efi_guidcmp(guid, ACPI_20_TABLE_GUID))) {
+			*rsdp_addr = (acpi_physical_address)table;
+			return true;
+		}
+	}
+	return find_rsdp;
+}
+#else
+static bool efi_get_rsdp_addr(acpi_physical_address *rsdp_addr)
+{
+	return false;
+}
+#endif
+
+static u8 checksum(u8 *buffer, u32 length)
+{
+	u8 sum = 0;
+	u8 *end = buffer + length;
+
+	while (buffer < end)
+		sum = (u8)(sum + *(buffer++));
+
+	return sum;
+}
+
+/*
+ * Used to search a block of memory for the RSDP signature.
+ * Return Pointer to the RSDP if found, otherwise NULL.
+ * Based on acpi_tb_scan_memory_for_rsdp().
+ */
+static u8 *scan_mem_for_rsdp(u8 *start_address, u32 length)
+{
+	struct acpi_table_rsdp *rsdp;
+	u8 *end_address;
+	u8 *mem_rover;
+
+	end_address = start_address + length;
+
+	/* Search from given start address for the requested length */
+	for (mem_rover = start_address; mem_rover < end_address;
+	     mem_rover += ACPI_RSDP_SCAN_STEP) {
+		/*
+		 * The RSDP signature and checksum must both be correct
+		 * Note: Sometimes there exists more than one RSDP in memory;
+		 * the valid RSDP has a valid checksum, all others have an
+		 * invalid checksum.
+		 */
+		rsdp = (struct acpi_table_rsdp *)mem_rover;
+
+		/* Nope, BAD Signature */
+		if (!ACPI_VALIDATE_RSDP_SIG(rsdp->signature))
+			continue;
+
+		/* Check the standard checksum */
+		if (checksum((u8 *) rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0)
+			continue;
+
+		/* Check extended checksum if table version >= 2 */
+		if ((rsdp->revision >= 2) &&
+		    (checksum((u8 *) rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0))
+			continue;
+
+		/* Sig and checksum valid, we have found a real RSDP */
+		return mem_rover;
+	}
+	return NULL;
+}
+
+/*
+ * Used to search RSDP physical address.
+ * Based on acpi_find_root_pointer(). Since only use physical address
+ * in this period, so there is no need to do the memory map jobs.
+ */
+static void bios_get_rsdp_addr(acpi_physical_address *rsdp_addr)
+{
+	struct acpi_table_rsdp *rsdp;
+	u8 *table_ptr;
+	u8 *mem_rover;
+	u32 address;
+
+	/*
+	 * Get the location of the Extended BIOS Data Area (EBDA)
+	 * Since we use physical address directely, so
+	 * acpi_os_map_memory() and acpi_os_unmap_memory() are
+	 * not needed here.
+	 */
+	table_ptr = (u8 *)ACPI_EBDA_PTR_LOCATION;
+	*(u32 *)(void *)&address = *(u16 *)(void *)table_ptr;
+	address <<= 4;
+	table_ptr = (u8 *)address;
+
+	/*
+	 * Search EBDA paragraphs (EBDA is required to be a minimum of
+	 * 1K length)
+	 */
+	if (address > 0x400) {
+		mem_rover = scan_mem_for_rsdp(table_ptr, ACPI_EBDA_WINDOW_SIZE);
+
+		if (mem_rover) {
+			address += (u32)ACPI_PTR_DIFF(mem_rover, table_ptr);
+			*rsdp_addr = (acpi_physical_address)address;
+			return;
+		}
+	}
+
+	table_ptr = (u8 *)ACPI_HI_RSDP_WINDOW_BASE;
+	mem_rover = scan_mem_for_rsdp(table_ptr, ACPI_HI_RSDP_WINDOW_SIZE);
+
+	/*
+	 * Search upper memory: 16-byte boundaries in E0000h-FFFFFh
+	 * Since we use physical address directely, so
+	 * acpi_os_map_memory() and acpi_os_unmap_memory() are
+	 * not needed here.
+	 */
+	if (mem_rover) {
+		address = (u32)(ACPI_HI_RSDP_WINDOW_BASE +
+				ACPI_PTR_DIFF(mem_rover, table_ptr));
+		*rsdp_addr = (acpi_physical_address)address;
+		return;
+	}
+}
+
+#ifdef CONFIG_KEXEC
+static bool get_acpi_rsdp(acpi_physical_address *rsdp_addr)
+{
+	char *args = (char *)get_cmd_line_ptr();
+	size_t len = strlen((char *)args);
+	char *tmp_cmdline, *param, *val;
+	unsigned long long addr = 0;
+	char *endptr;
+
+	if (!strstr(args, "acpi_rsdp="))
+		return false;
+
+	tmp_cmdline = malloc(len+1);
+	if (!tmp_cmdline)
+		error("Failed to allocate space for tmp_cmdline");
+
+	memcpy(tmp_cmdline, args, len);
+	tmp_cmdline[len] = 0;
+	args = tmp_cmdline;
+
+	args = skip_spaces(args);
+
+	while (*args) {
+		args = next_arg(args, &param, &val);
+
+		if (!val && strcmp(param, "--") == 0) {
+			warn("Only '--' specified in cmdline");
+			free(tmp_cmdline);
+			return false;
+		}
+
+		if (!strcmp(param, "acpi_rsdp")) {
+			addr = simple_strtoull(val, &endptr, 0);
+
+			if (addr == 0)
+				return false;
+
+			*rsdp_addr = (acpi_physical_address)addr;
+			return true;
+		}
+	}
+	return false;
+}
+#else
+static bool get_acpi_rsdp(acpi_physical_address *rsdp_addr)
+{
+	return false;
+}
+#endif
+
+/*
+ * Used to dig rsdp table from EFI table or BIOS.
+ * If rsdp table found in EFI table, use it. Or search BIOS.
+ * Based on acpi_os_get_root_pointer().
+ */
+static acpi_physical_address get_rsdp_addr(void)
+{
+	acpi_physical_address pa = 0;
+	bool status = false;
+
+	status = get_acpi_rsdp(&pa);
+
+	if (!status || pa == 0)
+		status = efi_get_rsdp_addr(&pa);
+
+	if (!status || pa == 0)
+		bios_get_rsdp_addr(&pa);
+
+	return pa;
+}
+
+static struct acpi_table_header *get_acpi_srat_table(void)
+{
+	char *args = (char *)get_cmd_line_ptr();
+	acpi_physical_address acpi_table;
+	acpi_physical_address root_table;
+	struct acpi_table_header *header;
+	struct acpi_table_rsdp *rsdp;
+	char *signature;
+	u8 *entry;
+	u32 count;
+	u32 size;
+	int i, j;
+	u32 len;
+
+	rsdp = (struct acpi_table_rsdp *)get_rsdp_addr();
+	if (!rsdp)
+		return NULL;
+
+	/* Get rsdt or xsdt from rsdp. */
+	if (!strstr(args, "acpi=rsdt") &&
+	    rsdp->xsdt_physical_address && rsdp->revision > 1) {
+		root_table = rsdp->xsdt_physical_address;
+		size = ACPI_XSDT_ENTRY_SIZE;
+	} else {
+		root_table = rsdp->rsdt_physical_address;
+		size = ACPI_RSDT_ENTRY_SIZE;
+	}
+
+	/* Get ACPI root table from rsdt or xsdt.*/
+	header = (struct acpi_table_header *)root_table;
+	len = header->length;
+	count = (u32)((len - sizeof(struct acpi_table_header)) / size);
+	entry = ACPI_ADD_PTR(u8, header, sizeof(struct acpi_table_header));
+
+	for (i = 0; i < count; i++) {
+		u64 address64;
+
+		if (size == ACPI_RSDT_ENTRY_SIZE)
+			acpi_table = ((acpi_physical_address)
+				      (*ACPI_CAST_PTR(u32, entry)));
+		else {
+			*(u64 *)(void *)&address64 = *(u64 *)(void *)entry;
+			acpi_table = (acpi_physical_address) address64;
+		}
+
+		if (acpi_table) {
+			header = (struct acpi_table_header *)acpi_table;
+			signature = header->signature;
+
+			if (!strncmp(signature, "SRAT", 4))
+				return header;
+		}
+		entry += size;
+	}
+	return NULL;
+}
+
+#ifdef CONFIG_MEMORY_HOTREMOVE
+/*
+ * According to ACPI table, filter the immvoable memory regions
+ * and store them in immovable_mem[].
+ */
+void get_immovable_mem(void)
+{
+	char *args = (char *)get_cmd_line_ptr();
+	struct acpi_table_header *table_header;
+	struct acpi_subtable_header *table;
+	struct acpi_srat_mem_affinity *ma;
+	unsigned long table_end;
+	int i = 0;
+
+	if (!strstr(args, "movable_node") || strstr(args, "acpi=off"))
+		return;
+
+	table_header = get_acpi_srat_table();
+	if (!table_header)
+		return;
+
+	table_end = (unsigned long)table_header + table_header->length;
+
+	table = (struct acpi_subtable_header *)
+		((unsigned long)table_header + sizeof(struct acpi_table_srat));
+
+	while (((unsigned long)table) + table->length < table_end) {
+		if (table->type == 1) {
+			ma = (struct acpi_srat_mem_affinity *)table;
+			if (!(ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE)) {
+				immovable_mem[i].start = ma->base_address;
+				immovable_mem[i].size = ma->length;
+				i++;
+			}
+
+			if (i >= MAX_NUMNODES*2)
+				break;
+		}
+		table = (struct acpi_subtable_header *)
+			((unsigned long)table + table->length);
+	}
+	num_immovable_mem = i;
+}
+#endif
diff --git a/arch/x86/boot/compressed/misc.h b/arch/x86/boot/compressed/misc.h
index a1d5918765f3..bb395e5f88e3 100644
--- a/arch/x86/boot/compressed/misc.h
+++ b/arch/x86/boot/compressed/misc.h
@@ -116,3 +116,11 @@ static inline void console_init(void)
 void set_sev_encryption_mask(void);
 
 #endif
+
+/* acpitb.c */
+/* Store the amount of immovable memory regions */
+int num_immovable_mem;
+#ifdef CONFIG_MEMORY_HOTREMOVE
+#define ACPI_MAX_TABLES                128
+void get_immovable_mem(void);
+#endif
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v7 1/3] x86/boot: Add acpitb.c to parse acpi tables
@ 2018-09-13 10:46   ` Chao Fan
  0 siblings, 0 replies; 15+ messages in thread
From: Chao Fan @ 2018-09-13 10:46 UTC (permalink / raw)
  To: linux-efi, linux-acpi, tglx, mingo, hpa, x86, linux-kernel,
	keescook, bhe
  Cc: rjw, lenb, ard.biesheuvel, indou.takao, caoj.fnst, Chao Fan

There is a bug that kaslr may randomly chooses some positions
which are located in movable memory regions. This will break memory
hotplug feature and make the movable memory chosen by KASLR can't be
removed. So dig SRAT table from ACPI tables to get memory information.

Imitate the ACPI code of parsing ACPI tables to dig and read ACPI
tables. Since some operations are not needed here, functions are
simplified. Functions will be used to dig only SRAT tables to get
information of memory, so that KASLR can the memory in immovable node.

And also, these functions won't influence the initialization of
ACPI after start_kernel().

Since use physical address directely, so acpi_os_map_memory()
and acpi_os_unmap_memory() are not needed.

Signed-off-by: Chao Fan <fanc.fnst@cn.fujitsu.com>
---
 arch/x86/boot/compressed/Makefile |   4 +
 arch/x86/boot/compressed/acpitb.c | 401 ++++++++++++++++++++++++++++++
 arch/x86/boot/compressed/misc.h   |   8 +
 3 files changed, 413 insertions(+)
 create mode 100644 arch/x86/boot/compressed/acpitb.c

diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
index 28764dacf018..394d7d93da7a 100644
--- a/arch/x86/boot/compressed/Makefile
+++ b/arch/x86/boot/compressed/Makefile
@@ -83,6 +83,10 @@ ifdef CONFIG_X86_64
 	vmlinux-objs-y += $(obj)/pgtable_64.o
 endif
 
+ifdef CONFIG_MEMORY_HOTREMOVE
+vmlinux-objs-$(CONFIG_RANDOMIZE_BASE) += $(obj)/acpitb.o
+endif
+
 $(obj)/eboot.o: KBUILD_CFLAGS += -fshort-wchar -mno-red-zone
 
 vmlinux-objs-$(CONFIG_EFI_STUB) += $(obj)/eboot.o $(obj)/efi_stub_$(BITS).o \
diff --git a/arch/x86/boot/compressed/acpitb.c b/arch/x86/boot/compressed/acpitb.c
new file mode 100644
index 000000000000..109c59b82cde
--- /dev/null
+++ b/arch/x86/boot/compressed/acpitb.c
@@ -0,0 +1,401 @@
+// SPDX-License-Identifier: GPL-2.0
+#define BOOT_CTYPE_H
+#include "misc.h"
+#include "error.h"
+
+#include <linux/efi.h>
+#include <asm/efi.h>
+#include <linux/numa.h>
+#include <linux/acpi.h>
+
+extern unsigned long get_cmd_line_ptr(void);
+
+#define STATIC
+#include <linux/decompress/mm.h>
+
+#ifdef CONFIG_MEMORY_HOTREMOVE
+struct mem_vector {
+	unsigned long long start;
+	unsigned long long size;
+};
+/* Store the immovable memory regions */
+struct mem_vector immovable_mem[MAX_NUMNODES*2];
+#endif
+
+#ifdef CONFIG_EFI
+/* Search EFI table for rsdp table. */
+static bool efi_get_rsdp_addr(acpi_physical_address *rsdp_addr)
+{
+	efi_system_table_t *systab;
+	bool find_rsdp = false;
+	bool efi_64 = false;
+	void *config_tables;
+	struct efi_info *e;
+	char *sig;
+	int size;
+	int i;
+
+	e = &boot_params->efi_info;
+	sig = (char *)&e->efi_loader_signature;
+
+	if (!strncmp(sig, EFI64_LOADER_SIGNATURE, 4))
+		efi_64 = true;
+	else if (!strncmp(sig, EFI32_LOADER_SIGNATURE, 4))
+		efi_64 = false;
+	else {
+		debug_putstr("Wrong EFI loader signature.\n");
+		return false;
+	}
+
+	/* Get systab from boot params. Based on efi_init(). */
+#ifdef CONFIG_X86_32
+	if (e->efi_systab_hi || e->efi_memmap_hi) {
+		debug_putstr("Table located above 4GB, disabling EFI.\n");
+		return false;
+	}
+	systab = (efi_system_table_t *)e->efi_systab;
+#else
+	systab = (efi_system_table_t *)(
+			e->efi_systab | ((__u64)e->efi_systab_hi<<32));
+#endif
+
+	if (systab == NULL)
+		return false;
+
+	/*
+	 * Get EFI tables from systab. Based on efi_config_init() and
+	 * efi_config_parse_tables(). Only dig the config_table.
+	 */
+	size = efi_64 ? sizeof(efi_config_table_64_t) :
+			sizeof(efi_config_table_32_t);
+
+	for (i = 0; i < systab->nr_tables; i++) {
+		efi_guid_t guid;
+		unsigned long table;
+
+		config_tables = (void *)(systab->tables + size * i);
+		if (efi_64) {
+			efi_config_table_64_t *tmp_table;
+
+			tmp_table = (efi_config_table_64_t *)config_tables;
+			guid = tmp_table->guid;
+			table = tmp_table->table;
+#ifndef CONFIG_64BIT
+			if (table >> 32) {
+				debug_putstr("Table located above 4G, disabling EFI.\n");
+				return false;
+			}
+#endif
+		} else {
+			efi_config_table_32_t *tmp_table;
+
+			tmp_table = (efi_config_table_32_t *)config_tables;
+			guid = tmp_table->guid;
+			table = tmp_table->table;
+		}
+
+		/*
+		 * Get rsdp from EFI tables.
+		 * If ACPI20 table found, use it and return true.
+		 * If ACPI20 table not found, but ACPI table found,
+		 * use the ACPI table and return true.
+		 * If neither ACPI table nor ACPI20 table found,
+		 * return false.
+		 */
+		if (!(efi_guidcmp(guid, ACPI_TABLE_GUID))) {
+			*rsdp_addr = (acpi_physical_address)table;
+			find_rsdp = true;
+		} else if (!(efi_guidcmp(guid, ACPI_20_TABLE_GUID))) {
+			*rsdp_addr = (acpi_physical_address)table;
+			return true;
+		}
+	}
+	return find_rsdp;
+}
+#else
+static bool efi_get_rsdp_addr(acpi_physical_address *rsdp_addr)
+{
+	return false;
+}
+#endif
+
+static u8 checksum(u8 *buffer, u32 length)
+{
+	u8 sum = 0;
+	u8 *end = buffer + length;
+
+	while (buffer < end)
+		sum = (u8)(sum + *(buffer++));
+
+	return sum;
+}
+
+/*
+ * Used to search a block of memory for the RSDP signature.
+ * Return Pointer to the RSDP if found, otherwise NULL.
+ * Based on acpi_tb_scan_memory_for_rsdp().
+ */
+static u8 *scan_mem_for_rsdp(u8 *start_address, u32 length)
+{
+	struct acpi_table_rsdp *rsdp;
+	u8 *end_address;
+	u8 *mem_rover;
+
+	end_address = start_address + length;
+
+	/* Search from given start address for the requested length */
+	for (mem_rover = start_address; mem_rover < end_address;
+	     mem_rover += ACPI_RSDP_SCAN_STEP) {
+		/*
+		 * The RSDP signature and checksum must both be correct
+		 * Note: Sometimes there exists more than one RSDP in memory;
+		 * the valid RSDP has a valid checksum, all others have an
+		 * invalid checksum.
+		 */
+		rsdp = (struct acpi_table_rsdp *)mem_rover;
+
+		/* Nope, BAD Signature */
+		if (!ACPI_VALIDATE_RSDP_SIG(rsdp->signature))
+			continue;
+
+		/* Check the standard checksum */
+		if (checksum((u8 *) rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0)
+			continue;
+
+		/* Check extended checksum if table version >= 2 */
+		if ((rsdp->revision >= 2) &&
+		    (checksum((u8 *) rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0))
+			continue;
+
+		/* Sig and checksum valid, we have found a real RSDP */
+		return mem_rover;
+	}
+	return NULL;
+}
+
+/*
+ * Used to search RSDP physical address.
+ * Based on acpi_find_root_pointer(). Since only use physical address
+ * in this period, so there is no need to do the memory map jobs.
+ */
+static void bios_get_rsdp_addr(acpi_physical_address *rsdp_addr)
+{
+	struct acpi_table_rsdp *rsdp;
+	u8 *table_ptr;
+	u8 *mem_rover;
+	u32 address;
+
+	/*
+	 * Get the location of the Extended BIOS Data Area (EBDA)
+	 * Since we use physical address directely, so
+	 * acpi_os_map_memory() and acpi_os_unmap_memory() are
+	 * not needed here.
+	 */
+	table_ptr = (u8 *)ACPI_EBDA_PTR_LOCATION;
+	*(u32 *)(void *)&address = *(u16 *)(void *)table_ptr;
+	address <<= 4;
+	table_ptr = (u8 *)address;
+
+	/*
+	 * Search EBDA paragraphs (EBDA is required to be a minimum of
+	 * 1K length)
+	 */
+	if (address > 0x400) {
+		mem_rover = scan_mem_for_rsdp(table_ptr, ACPI_EBDA_WINDOW_SIZE);
+
+		if (mem_rover) {
+			address += (u32)ACPI_PTR_DIFF(mem_rover, table_ptr);
+			*rsdp_addr = (acpi_physical_address)address;
+			return;
+		}
+	}
+
+	table_ptr = (u8 *)ACPI_HI_RSDP_WINDOW_BASE;
+	mem_rover = scan_mem_for_rsdp(table_ptr, ACPI_HI_RSDP_WINDOW_SIZE);
+
+	/*
+	 * Search upper memory: 16-byte boundaries in E0000h-FFFFFh
+	 * Since we use physical address directely, so
+	 * acpi_os_map_memory() and acpi_os_unmap_memory() are
+	 * not needed here.
+	 */
+	if (mem_rover) {
+		address = (u32)(ACPI_HI_RSDP_WINDOW_BASE +
+				ACPI_PTR_DIFF(mem_rover, table_ptr));
+		*rsdp_addr = (acpi_physical_address)address;
+		return;
+	}
+}
+
+#ifdef CONFIG_KEXEC
+static bool get_acpi_rsdp(acpi_physical_address *rsdp_addr)
+{
+	char *args = (char *)get_cmd_line_ptr();
+	size_t len = strlen((char *)args);
+	char *tmp_cmdline, *param, *val;
+	unsigned long long addr = 0;
+	char *endptr;
+
+	if (!strstr(args, "acpi_rsdp="))
+		return false;
+
+	tmp_cmdline = malloc(len+1);
+	if (!tmp_cmdline)
+		error("Failed to allocate space for tmp_cmdline");
+
+	memcpy(tmp_cmdline, args, len);
+	tmp_cmdline[len] = 0;
+	args = tmp_cmdline;
+
+	args = skip_spaces(args);
+
+	while (*args) {
+		args = next_arg(args, &param, &val);
+
+		if (!val && strcmp(param, "--") == 0) {
+			warn("Only '--' specified in cmdline");
+			free(tmp_cmdline);
+			return false;
+		}
+
+		if (!strcmp(param, "acpi_rsdp")) {
+			addr = simple_strtoull(val, &endptr, 0);
+
+			if (addr == 0)
+				return false;
+
+			*rsdp_addr = (acpi_physical_address)addr;
+			return true;
+		}
+	}
+	return false;
+}
+#else
+static bool get_acpi_rsdp(acpi_physical_address *rsdp_addr)
+{
+	return false;
+}
+#endif
+
+/*
+ * Used to dig rsdp table from EFI table or BIOS.
+ * If rsdp table found in EFI table, use it. Or search BIOS.
+ * Based on acpi_os_get_root_pointer().
+ */
+static acpi_physical_address get_rsdp_addr(void)
+{
+	acpi_physical_address pa = 0;
+	bool status = false;
+
+	status = get_acpi_rsdp(&pa);
+
+	if (!status || pa == 0)
+		status = efi_get_rsdp_addr(&pa);
+
+	if (!status || pa == 0)
+		bios_get_rsdp_addr(&pa);
+
+	return pa;
+}
+
+static struct acpi_table_header *get_acpi_srat_table(void)
+{
+	char *args = (char *)get_cmd_line_ptr();
+	acpi_physical_address acpi_table;
+	acpi_physical_address root_table;
+	struct acpi_table_header *header;
+	struct acpi_table_rsdp *rsdp;
+	char *signature;
+	u8 *entry;
+	u32 count;
+	u32 size;
+	int i, j;
+	u32 len;
+
+	rsdp = (struct acpi_table_rsdp *)get_rsdp_addr();
+	if (!rsdp)
+		return NULL;
+
+	/* Get rsdt or xsdt from rsdp. */
+	if (!strstr(args, "acpi=rsdt") &&
+	    rsdp->xsdt_physical_address && rsdp->revision > 1) {
+		root_table = rsdp->xsdt_physical_address;
+		size = ACPI_XSDT_ENTRY_SIZE;
+	} else {
+		root_table = rsdp->rsdt_physical_address;
+		size = ACPI_RSDT_ENTRY_SIZE;
+	}
+
+	/* Get ACPI root table from rsdt or xsdt.*/
+	header = (struct acpi_table_header *)root_table;
+	len = header->length;
+	count = (u32)((len - sizeof(struct acpi_table_header)) / size);
+	entry = ACPI_ADD_PTR(u8, header, sizeof(struct acpi_table_header));
+
+	for (i = 0; i < count; i++) {
+		u64 address64;
+
+		if (size == ACPI_RSDT_ENTRY_SIZE)
+			acpi_table = ((acpi_physical_address)
+				      (*ACPI_CAST_PTR(u32, entry)));
+		else {
+			*(u64 *)(void *)&address64 = *(u64 *)(void *)entry;
+			acpi_table = (acpi_physical_address) address64;
+		}
+
+		if (acpi_table) {
+			header = (struct acpi_table_header *)acpi_table;
+			signature = header->signature;
+
+			if (!strncmp(signature, "SRAT", 4))
+				return header;
+		}
+		entry += size;
+	}
+	return NULL;
+}
+
+#ifdef CONFIG_MEMORY_HOTREMOVE
+/*
+ * According to ACPI table, filter the immvoable memory regions
+ * and store them in immovable_mem[].
+ */
+void get_immovable_mem(void)
+{
+	char *args = (char *)get_cmd_line_ptr();
+	struct acpi_table_header *table_header;
+	struct acpi_subtable_header *table;
+	struct acpi_srat_mem_affinity *ma;
+	unsigned long table_end;
+	int i = 0;
+
+	if (!strstr(args, "movable_node") || strstr(args, "acpi=off"))
+		return;
+
+	table_header = get_acpi_srat_table();
+	if (!table_header)
+		return;
+
+	table_end = (unsigned long)table_header + table_header->length;
+
+	table = (struct acpi_subtable_header *)
+		((unsigned long)table_header + sizeof(struct acpi_table_srat));
+
+	while (((unsigned long)table) + table->length < table_end) {
+		if (table->type == 1) {
+			ma = (struct acpi_srat_mem_affinity *)table;
+			if (!(ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE)) {
+				immovable_mem[i].start = ma->base_address;
+				immovable_mem[i].size = ma->length;
+				i++;
+			}
+
+			if (i >= MAX_NUMNODES*2)
+				break;
+		}
+		table = (struct acpi_subtable_header *)
+			((unsigned long)table + table->length);
+	}
+	num_immovable_mem = i;
+}
+#endif
diff --git a/arch/x86/boot/compressed/misc.h b/arch/x86/boot/compressed/misc.h
index a1d5918765f3..bb395e5f88e3 100644
--- a/arch/x86/boot/compressed/misc.h
+++ b/arch/x86/boot/compressed/misc.h
@@ -116,3 +116,11 @@ static inline void console_init(void)
 void set_sev_encryption_mask(void);
 
 #endif
+
+/* acpitb.c */
+/* Store the amount of immovable memory regions */
+int num_immovable_mem;
+#ifdef CONFIG_MEMORY_HOTREMOVE
+#define ACPI_MAX_TABLES                128
+void get_immovable_mem(void);
+#endif
-- 
2.17.1




^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v7 2/3] x86/boot/KASLR: Walk srat tables to filter immovable memory
  2018-09-13 10:46 ` Chao Fan
@ 2018-09-13 10:46   ` Chao Fan
  -1 siblings, 0 replies; 15+ messages in thread
From: Chao Fan @ 2018-09-13 10:46 UTC (permalink / raw)
  To: linux-efi, linux-acpi, tglx, mingo, hpa, x86, linux-kernel,
	keescook, bhe
  Cc: rjw, lenb, ard.biesheuvel, indou.takao, caoj.fnst, Chao Fan

If CONFIG_MEMORY_HOTREMOVE enabled, walk through the acpi srat memory
tables and store those immovable memory regions so that kaslr can get
where to choose for randomization.

Signed-off-by: Chao Fan <fanc.fnst@cn.fujitsu.com>
---
 arch/x86/boot/compressed/kaslr.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c
index 9ed9709d9947..0c3567bc231c 100644
--- a/arch/x86/boot/compressed/kaslr.c
+++ b/arch/x86/boot/compressed/kaslr.c
@@ -417,6 +417,11 @@ static void mem_avoid_init(unsigned long input, unsigned long input_size,
 	/* Mark the memmap regions we need to avoid */
 	handle_mem_options();
 
+#ifdef CONFIG_MEMORY_HOTREMOVE
+	/* Mark the immovable regions we need to choose */
+	get_immovable_mem();
+#endif
+
 #ifdef CONFIG_X86_VERBOSE_BOOTUP
 	/* Make sure video RAM can be used. */
 	add_identity_map(0, PMD_SIZE);
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v7 2/3] x86/boot/KASLR: Walk srat tables to filter immovable memory
@ 2018-09-13 10:46   ` Chao Fan
  0 siblings, 0 replies; 15+ messages in thread
From: Chao Fan @ 2018-09-13 10:46 UTC (permalink / raw)
  To: linux-efi, linux-acpi, tglx, mingo, hpa, x86, linux-kernel,
	keescook, bhe
  Cc: rjw, lenb, ard.biesheuvel, indou.takao, caoj.fnst, Chao Fan

If CONFIG_MEMORY_HOTREMOVE enabled, walk through the acpi srat memory
tables and store those immovable memory regions so that kaslr can get
where to choose for randomization.

Signed-off-by: Chao Fan <fanc.fnst@cn.fujitsu.com>
---
 arch/x86/boot/compressed/kaslr.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c
index 9ed9709d9947..0c3567bc231c 100644
--- a/arch/x86/boot/compressed/kaslr.c
+++ b/arch/x86/boot/compressed/kaslr.c
@@ -417,6 +417,11 @@ static void mem_avoid_init(unsigned long input, unsigned long input_size,
 	/* Mark the memmap regions we need to avoid */
 	handle_mem_options();
 
+#ifdef CONFIG_MEMORY_HOTREMOVE
+	/* Mark the immovable regions we need to choose */
+	get_immovable_mem();
+#endif
+
 #ifdef CONFIG_X86_VERBOSE_BOOTUP
 	/* Make sure video RAM can be used. */
 	add_identity_map(0, PMD_SIZE);
-- 
2.17.1




^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v7 3/3] x86/boot/KASLR: Limit kaslr to choosing the immovable memory
  2018-09-13 10:46 ` Chao Fan
@ 2018-09-13 10:46   ` Chao Fan
  -1 siblings, 0 replies; 15+ messages in thread
From: Chao Fan @ 2018-09-13 10:46 UTC (permalink / raw)
  To: linux-efi, linux-acpi, tglx, mingo, hpa, x86, linux-kernel,
	keescook, bhe
  Cc: rjw, lenb, ard.biesheuvel, indou.takao, caoj.fnst, Chao Fan

If CONFIG_MEMORY_HOTREMOVE enabled and the amount of immovable
memory regions is not zero. Calculate the intersection between memory
regions from e820/efi memory table and immovable memory regions.

Signed-off-by: Chao Fan <fanc.fnst@cn.fujitsu.com>
---
 arch/x86/boot/compressed/kaslr.c | 71 +++++++++++++++++++++++++++-----
 1 file changed, 60 insertions(+), 11 deletions(-)

diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c
index 0c3567bc231c..0a7ef2daf169 100644
--- a/arch/x86/boot/compressed/kaslr.c
+++ b/arch/x86/boot/compressed/kaslr.c
@@ -101,6 +101,11 @@ static bool memmap_too_large;
 /* Store memory limit specified by "mem=nn[KMG]" or "memmap=nn[KMG]" */
 static unsigned long long mem_limit = ULLONG_MAX;
 
+#ifdef CONFIG_MEMORY_HOTREMOVE
+/* Store the immovable memory regions */
+extern struct mem_vector immovable_mem[MAX_NUMNODES*2];
+#endif
+
 
 enum mem_avoid_index {
 	MEM_AVOID_ZO_RANGE = 0,
@@ -577,9 +582,9 @@ static unsigned long slots_fetch_random(void)
 	return 0;
 }
 
-static void process_mem_region(struct mem_vector *entry,
-			       unsigned long minimum,
-			       unsigned long image_size)
+static void slots_count(struct mem_vector *entry,
+			unsigned long minimum,
+			unsigned long image_size)
 {
 	struct mem_vector region, overlap;
 	unsigned long start_orig, end;
@@ -655,6 +660,56 @@ static void process_mem_region(struct mem_vector *entry,
 	}
 }
 
+static bool process_mem_region(struct mem_vector *region,
+			       unsigned long long minimum,
+			       unsigned long long image_size)
+{
+	int i;
+	/*
+	 * If no immovable memory found, or MEMORY_HOTREMOVE disabled,
+	 * walk all the regions, so use region directely.
+	 */
+	if (num_immovable_mem == 0) {
+		slots_count(region, minimum, image_size);
+
+		if (slot_area_index == MAX_SLOT_AREA) {
+			debug_putstr("Aborted e820/efi memmap scan (slot_areas full)!\n");
+			return 1;
+		}
+		return 0;
+	}
+
+#ifdef CONFIG_MEMORY_HOTREMOVE
+	/*
+	 * If immovable memory found, filter the intersection between
+	 * immovable memory and region to slots_count.
+	 * Otherwise, go on old code.
+	 */
+	for (i = 0; i < num_immovable_mem; i++) {
+		struct mem_vector entry;
+		unsigned long long start, end, entry_end, region_end;
+
+		start = immovable_mem[i].start;
+		end = start + immovable_mem[i].size;
+		region_end = region->start + region->size;
+
+		entry.start = clamp(region->start, start, end);
+		entry_end = clamp(region_end, start, end);
+
+		if (entry.start + image_size < entry_end) {
+			entry.size = entry_end - entry.start;
+			slots_count(&entry, minimum, image_size);
+
+			if (slot_area_index == MAX_SLOT_AREA) {
+				debug_putstr("Aborted e820/efi memmap scan (slot_areas full)!\n");
+				return 1;
+			}
+		}
+	}
+	return 0;
+#endif
+}
+
 #ifdef CONFIG_EFI
 /*
  * Returns true if mirror region found (and must have been processed
@@ -720,11 +775,8 @@ process_efi_entries(unsigned long minimum, unsigned long image_size)
 
 		region.start = md->phys_addr;
 		region.size = md->num_pages << EFI_PAGE_SHIFT;
-		process_mem_region(&region, minimum, image_size);
-		if (slot_area_index == MAX_SLOT_AREA) {
-			debug_putstr("Aborted EFI scan (slot_areas full)!\n");
+		if (process_mem_region(&region, minimum, image_size))
 			break;
-		}
 	}
 	return true;
 }
@@ -751,11 +803,8 @@ static void process_e820_entries(unsigned long minimum,
 			continue;
 		region.start = entry->addr;
 		region.size = entry->size;
-		process_mem_region(&region, minimum, image_size);
-		if (slot_area_index == MAX_SLOT_AREA) {
-			debug_putstr("Aborted e820 scan (slot_areas full)!\n");
+		if (process_mem_region(&region, minimum, image_size))
 			break;
-		}
 	}
 }
 
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v7 3/3] x86/boot/KASLR: Limit kaslr to choosing the immovable memory
@ 2018-09-13 10:46   ` Chao Fan
  0 siblings, 0 replies; 15+ messages in thread
From: Chao Fan @ 2018-09-13 10:46 UTC (permalink / raw)
  To: linux-efi, linux-acpi, tglx, mingo, hpa, x86, linux-kernel,
	keescook, bhe
  Cc: rjw, lenb, ard.biesheuvel, indou.takao, caoj.fnst, Chao Fan

If CONFIG_MEMORY_HOTREMOVE enabled and the amount of immovable
memory regions is not zero. Calculate the intersection between memory
regions from e820/efi memory table and immovable memory regions.

Signed-off-by: Chao Fan <fanc.fnst@cn.fujitsu.com>
---
 arch/x86/boot/compressed/kaslr.c | 71 +++++++++++++++++++++++++++-----
 1 file changed, 60 insertions(+), 11 deletions(-)

diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c
index 0c3567bc231c..0a7ef2daf169 100644
--- a/arch/x86/boot/compressed/kaslr.c
+++ b/arch/x86/boot/compressed/kaslr.c
@@ -101,6 +101,11 @@ static bool memmap_too_large;
 /* Store memory limit specified by "mem=nn[KMG]" or "memmap=nn[KMG]" */
 static unsigned long long mem_limit = ULLONG_MAX;
 
+#ifdef CONFIG_MEMORY_HOTREMOVE
+/* Store the immovable memory regions */
+extern struct mem_vector immovable_mem[MAX_NUMNODES*2];
+#endif
+
 
 enum mem_avoid_index {
 	MEM_AVOID_ZO_RANGE = 0,
@@ -577,9 +582,9 @@ static unsigned long slots_fetch_random(void)
 	return 0;
 }
 
-static void process_mem_region(struct mem_vector *entry,
-			       unsigned long minimum,
-			       unsigned long image_size)
+static void slots_count(struct mem_vector *entry,
+			unsigned long minimum,
+			unsigned long image_size)
 {
 	struct mem_vector region, overlap;
 	unsigned long start_orig, end;
@@ -655,6 +660,56 @@ static void process_mem_region(struct mem_vector *entry,
 	}
 }
 
+static bool process_mem_region(struct mem_vector *region,
+			       unsigned long long minimum,
+			       unsigned long long image_size)
+{
+	int i;
+	/*
+	 * If no immovable memory found, or MEMORY_HOTREMOVE disabled,
+	 * walk all the regions, so use region directely.
+	 */
+	if (num_immovable_mem == 0) {
+		slots_count(region, minimum, image_size);
+
+		if (slot_area_index == MAX_SLOT_AREA) {
+			debug_putstr("Aborted e820/efi memmap scan (slot_areas full)!\n");
+			return 1;
+		}
+		return 0;
+	}
+
+#ifdef CONFIG_MEMORY_HOTREMOVE
+	/*
+	 * If immovable memory found, filter the intersection between
+	 * immovable memory and region to slots_count.
+	 * Otherwise, go on old code.
+	 */
+	for (i = 0; i < num_immovable_mem; i++) {
+		struct mem_vector entry;
+		unsigned long long start, end, entry_end, region_end;
+
+		start = immovable_mem[i].start;
+		end = start + immovable_mem[i].size;
+		region_end = region->start + region->size;
+
+		entry.start = clamp(region->start, start, end);
+		entry_end = clamp(region_end, start, end);
+
+		if (entry.start + image_size < entry_end) {
+			entry.size = entry_end - entry.start;
+			slots_count(&entry, minimum, image_size);
+
+			if (slot_area_index == MAX_SLOT_AREA) {
+				debug_putstr("Aborted e820/efi memmap scan (slot_areas full)!\n");
+				return 1;
+			}
+		}
+	}
+	return 0;
+#endif
+}
+
 #ifdef CONFIG_EFI
 /*
  * Returns true if mirror region found (and must have been processed
@@ -720,11 +775,8 @@ process_efi_entries(unsigned long minimum, unsigned long image_size)
 
 		region.start = md->phys_addr;
 		region.size = md->num_pages << EFI_PAGE_SHIFT;
-		process_mem_region(&region, minimum, image_size);
-		if (slot_area_index == MAX_SLOT_AREA) {
-			debug_putstr("Aborted EFI scan (slot_areas full)!\n");
+		if (process_mem_region(&region, minimum, image_size))
 			break;
-		}
 	}
 	return true;
 }
@@ -751,11 +803,8 @@ static void process_e820_entries(unsigned long minimum,
 			continue;
 		region.start = entry->addr;
 		region.size = entry->size;
-		process_mem_region(&region, minimum, image_size);
-		if (slot_area_index == MAX_SLOT_AREA) {
-			debug_putstr("Aborted e820 scan (slot_areas full)!\n");
+		if (process_mem_region(&region, minimum, image_size))
 			break;
-		}
 	}
 }
 
-- 
2.17.1




^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH v7 1/3] x86/boot: Add acpitb.c to parse acpi tables
  2018-09-13 10:46   ` Chao Fan
  (?)
@ 2018-09-22 15:45   ` Kees Cook
  2018-09-25  1:12       ` Chao Fan
  -1 siblings, 1 reply; 15+ messages in thread
From: Kees Cook @ 2018-09-22 15:45 UTC (permalink / raw)
  To: Chao Fan
  Cc: linux-efi, ACPI Devel Maling List, Thomas Gleixner, Ingo Molnar,
	H. Peter Anvin, X86 ML, LKML, Baoquan He, Rafael J. Wysocki,
	Len Brown, Ard Biesheuvel, indou.takao, caoj.fnst

On Thu, Sep 13, 2018 at 3:46 AM, Chao Fan <fanc.fnst@cn.fujitsu.com> wrote:
> There is a bug that kaslr may randomly chooses some positions
> which are located in movable memory regions. This will break memory
> hotplug feature and make the movable memory chosen by KASLR can't be
> removed. So dig SRAT table from ACPI tables to get memory information.
>
> Imitate the ACPI code of parsing ACPI tables to dig and read ACPI
> tables. Since some operations are not needed here, functions are
> simplified. Functions will be used to dig only SRAT tables to get
> information of memory, so that KASLR can the memory in immovable node.
>
> And also, these functions won't influence the initialization of
> ACPI after start_kernel().
>
> Since use physical address directely, so acpi_os_map_memory()
> and acpi_os_unmap_memory() are not needed.
>
> Signed-off-by: Chao Fan <fanc.fnst@cn.fujitsu.com>
> ---
>  arch/x86/boot/compressed/Makefile |   4 +
>  arch/x86/boot/compressed/acpitb.c | 401 ++++++++++++++++++++++++++++++

Does this logic live anywhere else in the kernel already? (i.e. could
other code be reused?)

-Kees

-- 
Kees Cook
Pixel Security

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v7 2/3] x86/boot/KASLR: Walk srat tables to filter immovable memory
  2018-09-13 10:46   ` Chao Fan
  (?)
@ 2018-09-22 15:46   ` Kees Cook
  -1 siblings, 0 replies; 15+ messages in thread
From: Kees Cook @ 2018-09-22 15:46 UTC (permalink / raw)
  To: Chao Fan
  Cc: linux-efi, ACPI Devel Maling List, Thomas Gleixner, Ingo Molnar,
	H. Peter Anvin, X86 ML, LKML, Baoquan He, Rafael J. Wysocki,
	Len Brown, Ard Biesheuvel, indou.takao, caoj.fnst

On Thu, Sep 13, 2018 at 3:46 AM, Chao Fan <fanc.fnst@cn.fujitsu.com> wrote:
> If CONFIG_MEMORY_HOTREMOVE enabled, walk through the acpi srat memory
> tables and store those immovable memory regions so that kaslr can get
> where to choose for randomization.
>
> Signed-off-by: Chao Fan <fanc.fnst@cn.fujitsu.com>
> ---
>  arch/x86/boot/compressed/kaslr.c | 5 +++++
>  1 file changed, 5 insertions(+)
>
> diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c
> index 9ed9709d9947..0c3567bc231c 100644
> --- a/arch/x86/boot/compressed/kaslr.c
> +++ b/arch/x86/boot/compressed/kaslr.c
> @@ -417,6 +417,11 @@ static void mem_avoid_init(unsigned long input, unsigned long input_size,
>         /* Mark the memmap regions we need to avoid */
>         handle_mem_options();
>
> +#ifdef CONFIG_MEMORY_HOTREMOVE
> +       /* Mark the immovable regions we need to choose */
> +       get_immovable_mem();
> +#endif

Style nit-pick: I'd prefer the definition of get_immovable_mem() do
the ifdef so it doesn't appear here.

-Kees

> +
>  #ifdef CONFIG_X86_VERBOSE_BOOTUP
>         /* Make sure video RAM can be used. */
>         add_identity_map(0, PMD_SIZE);
> --
> 2.17.1
>
>
>



-- 
Kees Cook
Pixel Security

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v7 3/3] x86/boot/KASLR: Limit kaslr to choosing the immovable memory
  2018-09-13 10:46   ` Chao Fan
  (?)
@ 2018-09-22 15:48   ` Kees Cook
  2018-09-25  1:04       ` Chao Fan
  -1 siblings, 1 reply; 15+ messages in thread
From: Kees Cook @ 2018-09-22 15:48 UTC (permalink / raw)
  To: Chao Fan
  Cc: linux-efi, ACPI Devel Maling List, Thomas Gleixner, Ingo Molnar,
	H. Peter Anvin, X86 ML, LKML, Baoquan He, Rafael J. Wysocki,
	Len Brown, Ard Biesheuvel, indou.takao, caoj.fnst

On Thu, Sep 13, 2018 at 3:46 AM, Chao Fan <fanc.fnst@cn.fujitsu.com> wrote:
> If CONFIG_MEMORY_HOTREMOVE enabled and the amount of immovable
> memory regions is not zero. Calculate the intersection between memory
> regions from e820/efi memory table and immovable memory regions.
>
> Signed-off-by: Chao Fan <fanc.fnst@cn.fujitsu.com>
> ---
>  arch/x86/boot/compressed/kaslr.c | 71 +++++++++++++++++++++++++++-----
>  1 file changed, 60 insertions(+), 11 deletions(-)
>
> diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c
> index 0c3567bc231c..0a7ef2daf169 100644
> --- a/arch/x86/boot/compressed/kaslr.c
> +++ b/arch/x86/boot/compressed/kaslr.c
> @@ -101,6 +101,11 @@ static bool memmap_too_large;
>  /* Store memory limit specified by "mem=nn[KMG]" or "memmap=nn[KMG]" */
>  static unsigned long long mem_limit = ULLONG_MAX;
>
> +#ifdef CONFIG_MEMORY_HOTREMOVE
> +/* Store the immovable memory regions */
> +extern struct mem_vector immovable_mem[MAX_NUMNODES*2];
> +#endif
> +
>
>  enum mem_avoid_index {
>         MEM_AVOID_ZO_RANGE = 0,
> @@ -577,9 +582,9 @@ static unsigned long slots_fetch_random(void)
>         return 0;
>  }
>
> -static void process_mem_region(struct mem_vector *entry,
> -                              unsigned long minimum,
> -                              unsigned long image_size)
> +static void slots_count(struct mem_vector *entry,
> +                       unsigned long minimum,
> +                       unsigned long image_size)
>  {
>         struct mem_vector region, overlap;
>         unsigned long start_orig, end;
> @@ -655,6 +660,56 @@ static void process_mem_region(struct mem_vector *entry,
>         }
>  }
>
> +static bool process_mem_region(struct mem_vector *region,
> +                              unsigned long long minimum,
> +                              unsigned long long image_size)
> +{
> +       int i;
> +       /*
> +        * If no immovable memory found, or MEMORY_HOTREMOVE disabled,
> +        * walk all the regions, so use region directely.
> +        */
> +       if (num_immovable_mem == 0) {
> +               slots_count(region, minimum, image_size);
> +
> +               if (slot_area_index == MAX_SLOT_AREA) {
> +                       debug_putstr("Aborted e820/efi memmap scan (slot_areas full)!\n");
> +                       return 1;
> +               }
> +               return 0;
> +       }
> +
> +#ifdef CONFIG_MEMORY_HOTREMOVE
> +       /*
> +        * If immovable memory found, filter the intersection between
> +        * immovable memory and region to slots_count.
> +        * Otherwise, go on old code.
> +        */
> +       for (i = 0; i < num_immovable_mem; i++) {
> +               struct mem_vector entry;
> +               unsigned long long start, end, entry_end, region_end;
> +
> +               start = immovable_mem[i].start;
> +               end = start + immovable_mem[i].size;
> +               region_end = region->start + region->size;
> +
> +               entry.start = clamp(region->start, start, end);
> +               entry_end = clamp(region_end, start, end);
> +
> +               if (entry.start + image_size < entry_end) {

Can this logic be rewritten to use the existing mem_overlaps() check
instead? I think that would make it much more readable.

Otherwise, yes, this all looks fine.

-Kees

> +                       entry.size = entry_end - entry.start;
> +                       slots_count(&entry, minimum, image_size);
> +
> +                       if (slot_area_index == MAX_SLOT_AREA) {
> +                               debug_putstr("Aborted e820/efi memmap scan (slot_areas full)!\n");
> +                               return 1;
> +                       }
> +               }
> +       }
> +       return 0;
> +#endif
> +}
> +
>  #ifdef CONFIG_EFI
>  /*
>   * Returns true if mirror region found (and must have been processed
> @@ -720,11 +775,8 @@ process_efi_entries(unsigned long minimum, unsigned long image_size)
>
>                 region.start = md->phys_addr;
>                 region.size = md->num_pages << EFI_PAGE_SHIFT;
> -               process_mem_region(&region, minimum, image_size);
> -               if (slot_area_index == MAX_SLOT_AREA) {
> -                       debug_putstr("Aborted EFI scan (slot_areas full)!\n");
> +               if (process_mem_region(&region, minimum, image_size))
>                         break;
> -               }
>         }
>         return true;
>  }
> @@ -751,11 +803,8 @@ static void process_e820_entries(unsigned long minimum,
>                         continue;
>                 region.start = entry->addr;
>                 region.size = entry->size;
> -               process_mem_region(&region, minimum, image_size);
> -               if (slot_area_index == MAX_SLOT_AREA) {
> -                       debug_putstr("Aborted e820 scan (slot_areas full)!\n");
> +               if (process_mem_region(&region, minimum, image_size))
>                         break;
> -               }
>         }
>  }
>
> --
> 2.17.1
>
>
>



-- 
Kees Cook
Pixel Security

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v7 3/3] x86/boot/KASLR: Limit kaslr to choosing the immovable memory
  2018-09-22 15:48   ` Kees Cook
@ 2018-09-25  1:04       ` Chao Fan
  0 siblings, 0 replies; 15+ messages in thread
From: Chao Fan @ 2018-09-25  1:04 UTC (permalink / raw)
  To: Kees Cook
  Cc: linux-efi, ACPI Devel Maling List, Thomas Gleixner, Ingo Molnar,
	H. Peter Anvin, X86 ML, LKML, Baoquan He, Rafael J. Wysocki,
	Len Brown, Ard Biesheuvel, indou.takao, caoj.fnst

On Sat, Sep 22, 2018 at 08:48:53AM -0700, Kees Cook wrote:
>On Thu, Sep 13, 2018 at 3:46 AM, Chao Fan <fanc.fnst@cn.fujitsu.com> wrote:
>> +#ifdef CONFIG_MEMORY_HOTREMOVE
>> +       /*
>> +        * If immovable memory found, filter the intersection between
>> +        * immovable memory and region to slots_count.
>> +        * Otherwise, go on old code.
>> +        */
>> +       for (i = 0; i < num_immovable_mem; i++) {
>> +               struct mem_vector entry;
>> +               unsigned long long start, end, entry_end, region_end;
>> +
>> +               start = immovable_mem[i].start;
>> +               end = start + immovable_mem[i].size;
>> +               region_end = region->start + region->size;
>> +
>> +               entry.start = clamp(region->start, start, end);
>> +               entry_end = clamp(region_end, start, end);
>> +
>> +               if (entry.start + image_size < entry_end) {
>
>Can this logic be rewritten to use the existing mem_overlaps() check
>instead? I think that would make it much more readable.
>

Sure, I will reuse mem_overlaps() instead of this logical.

>Otherwise, yes, this all looks fine.

Thank you for the review.

Thanks,
Chao Fan

>
>-Kees
>
>> +                       entry.size = entry_end - entry.start;
>> +                       slots_count(&entry, minimum, image_size);
>> +
>> +                       if (slot_area_index == MAX_SLOT_AREA) {
>> +                               debug_putstr("Aborted e820/efi memmap scan (slot_areas full)!\n");
>> +                               return 1;
>> +                       }
>> +               }
>> +       }
>> +       return 0;
>> +#endif
>> +}
>> +
>>  #ifdef CONFIG_EFI
>>  /*
>>   * Returns true if mirror region found (and must have been processed
>> @@ -720,11 +775,8 @@ process_efi_entries(unsigned long minimum, unsigned long image_size)
>>
>>                 region.start = md->phys_addr;
>>                 region.size = md->num_pages << EFI_PAGE_SHIFT;
>> -               process_mem_region(&region, minimum, image_size);
>> -               if (slot_area_index == MAX_SLOT_AREA) {
>> -                       debug_putstr("Aborted EFI scan (slot_areas full)!\n");
>> +               if (process_mem_region(&region, minimum, image_size))
>>                         break;
>> -               }
>>         }
>>         return true;
>>  }
>> @@ -751,11 +803,8 @@ static void process_e820_entries(unsigned long minimum,
>>                         continue;
>>                 region.start = entry->addr;
>>                 region.size = entry->size;
>> -               process_mem_region(&region, minimum, image_size);
>> -               if (slot_area_index == MAX_SLOT_AREA) {
>> -                       debug_putstr("Aborted e820 scan (slot_areas full)!\n");
>> +               if (process_mem_region(&region, minimum, image_size))
>>                         break;
>> -               }
>>         }
>>  }
>>
>> --
>> 2.17.1
>>
>>
>>
>
>
>
>-- 
>Kees Cook
>Pixel Security
>
>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v7 3/3] x86/boot/KASLR: Limit kaslr to choosing the immovable memory
@ 2018-09-25  1:04       ` Chao Fan
  0 siblings, 0 replies; 15+ messages in thread
From: Chao Fan @ 2018-09-25  1:04 UTC (permalink / raw)
  To: Kees Cook
  Cc: linux-efi, ACPI Devel Maling List, Thomas Gleixner, Ingo Molnar,
	H. Peter Anvin, X86 ML, LKML, Baoquan He, Rafael J. Wysocki,
	Len Brown, Ard Biesheuvel, indou.takao, caoj.fnst

On Sat, Sep 22, 2018 at 08:48:53AM -0700, Kees Cook wrote:
>On Thu, Sep 13, 2018 at 3:46 AM, Chao Fan <fanc.fnst@cn.fujitsu.com> wrote:
>> +#ifdef CONFIG_MEMORY_HOTREMOVE
>> +       /*
>> +        * If immovable memory found, filter the intersection between
>> +        * immovable memory and region to slots_count.
>> +        * Otherwise, go on old code.
>> +        */
>> +       for (i = 0; i < num_immovable_mem; i++) {
>> +               struct mem_vector entry;
>> +               unsigned long long start, end, entry_end, region_end;
>> +
>> +               start = immovable_mem[i].start;
>> +               end = start + immovable_mem[i].size;
>> +               region_end = region->start + region->size;
>> +
>> +               entry.start = clamp(region->start, start, end);
>> +               entry_end = clamp(region_end, start, end);
>> +
>> +               if (entry.start + image_size < entry_end) {
>
>Can this logic be rewritten to use the existing mem_overlaps() check
>instead? I think that would make it much more readable.
>

Sure, I will reuse mem_overlaps() instead of this logical.

>Otherwise, yes, this all looks fine.

Thank you for the review.

Thanks,
Chao Fan

>
>-Kees
>
>> +                       entry.size = entry_end - entry.start;
>> +                       slots_count(&entry, minimum, image_size);
>> +
>> +                       if (slot_area_index == MAX_SLOT_AREA) {
>> +                               debug_putstr("Aborted e820/efi memmap scan (slot_areas full)!\n");
>> +                               return 1;
>> +                       }
>> +               }
>> +       }
>> +       return 0;
>> +#endif
>> +}
>> +
>>  #ifdef CONFIG_EFI
>>  /*
>>   * Returns true if mirror region found (and must have been processed
>> @@ -720,11 +775,8 @@ process_efi_entries(unsigned long minimum, unsigned long image_size)
>>
>>                 region.start = md->phys_addr;
>>                 region.size = md->num_pages << EFI_PAGE_SHIFT;
>> -               process_mem_region(&region, minimum, image_size);
>> -               if (slot_area_index == MAX_SLOT_AREA) {
>> -                       debug_putstr("Aborted EFI scan (slot_areas full)!\n");
>> +               if (process_mem_region(&region, minimum, image_size))
>>                         break;
>> -               }
>>         }
>>         return true;
>>  }
>> @@ -751,11 +803,8 @@ static void process_e820_entries(unsigned long minimum,
>>                         continue;
>>                 region.start = entry->addr;
>>                 region.size = entry->size;
>> -               process_mem_region(&region, minimum, image_size);
>> -               if (slot_area_index == MAX_SLOT_AREA) {
>> -                       debug_putstr("Aborted e820 scan (slot_areas full)!\n");
>> +               if (process_mem_region(&region, minimum, image_size))
>>                         break;
>> -               }
>>         }
>>  }
>>
>> --
>> 2.17.1
>>
>>
>>
>
>
>
>-- 
>Kees Cook
>Pixel Security
>
>



^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v7 1/3] x86/boot: Add acpitb.c to parse acpi tables
  2018-09-22 15:45   ` Kees Cook
@ 2018-09-25  1:12       ` Chao Fan
  0 siblings, 0 replies; 15+ messages in thread
From: Chao Fan @ 2018-09-25  1:12 UTC (permalink / raw)
  To: Kees Cook
  Cc: linux-efi, ACPI Devel Maling List, Thomas Gleixner, Ingo Molnar,
	H. Peter Anvin, X86 ML, LKML, Baoquan He, Rafael J. Wysocki,
	Len Brown, Ard Biesheuvel, indou.takao, caoj.fnst

On Sat, Sep 22, 2018 at 08:45:12AM -0700, Kees Cook wrote:
>On Thu, Sep 13, 2018 at 3:46 AM, Chao Fan <fanc.fnst@cn.fujitsu.com> wrote:
>> There is a bug that kaslr may randomly chooses some positions
>> which are located in movable memory regions. This will break memory
>> hotplug feature and make the movable memory chosen by KASLR can't be
>> removed. So dig SRAT table from ACPI tables to get memory information.
>>
>> Imitate the ACPI code of parsing ACPI tables to dig and read ACPI
>> tables. Since some operations are not needed here, functions are
>> simplified. Functions will be used to dig only SRAT tables to get
>> information of memory, so that KASLR can the memory in immovable node.
>>
>> And also, these functions won't influence the initialization of
>> ACPI after start_kernel().
>>
>> Since use physical address directely, so acpi_os_map_memory()
>> and acpi_os_unmap_memory() are not needed.
>>
>> Signed-off-by: Chao Fan <fanc.fnst@cn.fujitsu.com>
>> ---
>>  arch/x86/boot/compressed/Makefile |   4 +
>>  arch/x86/boot/compressed/acpitb.c | 401 ++++++++++++++++++++++++++++++
>
>Does this logic live anywhere else in the kernel already? (i.e. could
>other code be reused?)

Live in uncompressec period, but not completely same.
The map between physical address and virtual address is not needed here.
So I thins it's hard to reuse, that's why I made this new file.

Thanks,
Chao Fan

>
>-Kees
>
>-- 
>Kees Cook
>Pixel Security
>
>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v7 1/3] x86/boot: Add acpitb.c to parse acpi tables
@ 2018-09-25  1:12       ` Chao Fan
  0 siblings, 0 replies; 15+ messages in thread
From: Chao Fan @ 2018-09-25  1:12 UTC (permalink / raw)
  To: Kees Cook
  Cc: linux-efi, ACPI Devel Maling List, Thomas Gleixner, Ingo Molnar,
	H. Peter Anvin, X86 ML, LKML, Baoquan He, Rafael J. Wysocki,
	Len Brown, Ard Biesheuvel, indou.takao, caoj.fnst

On Sat, Sep 22, 2018 at 08:45:12AM -0700, Kees Cook wrote:
>On Thu, Sep 13, 2018 at 3:46 AM, Chao Fan <fanc.fnst@cn.fujitsu.com> wrote:
>> There is a bug that kaslr may randomly chooses some positions
>> which are located in movable memory regions. This will break memory
>> hotplug feature and make the movable memory chosen by KASLR can't be
>> removed. So dig SRAT table from ACPI tables to get memory information.
>>
>> Imitate the ACPI code of parsing ACPI tables to dig and read ACPI
>> tables. Since some operations are not needed here, functions are
>> simplified. Functions will be used to dig only SRAT tables to get
>> information of memory, so that KASLR can the memory in immovable node.
>>
>> And also, these functions won't influence the initialization of
>> ACPI after start_kernel().
>>
>> Since use physical address directely, so acpi_os_map_memory()
>> and acpi_os_unmap_memory() are not needed.
>>
>> Signed-off-by: Chao Fan <fanc.fnst@cn.fujitsu.com>
>> ---
>>  arch/x86/boot/compressed/Makefile |   4 +
>>  arch/x86/boot/compressed/acpitb.c | 401 ++++++++++++++++++++++++++++++
>
>Does this logic live anywhere else in the kernel already? (i.e. could
>other code be reused?)

Live in uncompressec period, but not completely same.
The map between physical address and virtual address is not needed here.
So I thins it's hard to reuse, that's why I made this new file.

Thanks,
Chao Fan

>
>-Kees
>
>-- 
>Kees Cook
>Pixel Security
>
>



^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2018-09-25  1:13 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-09-13 10:46 [PATCH v7 0/3] x86/boot/KASLR: Parse ACPI table and limit kaslr in immovable memory Chao Fan
2018-09-13 10:46 ` Chao Fan
2018-09-13 10:46 ` [PATCH v7 1/3] x86/boot: Add acpitb.c to parse acpi tables Chao Fan
2018-09-13 10:46   ` Chao Fan
2018-09-22 15:45   ` Kees Cook
2018-09-25  1:12     ` Chao Fan
2018-09-25  1:12       ` Chao Fan
2018-09-13 10:46 ` [PATCH v7 2/3] x86/boot/KASLR: Walk srat tables to filter immovable memory Chao Fan
2018-09-13 10:46   ` Chao Fan
2018-09-22 15:46   ` Kees Cook
2018-09-13 10:46 ` [PATCH v7 3/3] x86/boot/KASLR: Limit kaslr to choosing the " Chao Fan
2018-09-13 10:46   ` Chao Fan
2018-09-22 15:48   ` Kees Cook
2018-09-25  1:04     ` Chao Fan
2018-09-25  1:04       ` Chao Fan

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.