* [PATCH v6 0/4] Adjust the padding size for KASLR
@ 2019-12-06 16:57 Masayoshi Mizuma
2019-12-06 16:57 ` [PATCH v6 1/4] x86/boot: Wrap up the SRAT traversing code into subtable_parse() Masayoshi Mizuma
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Masayoshi Mizuma @ 2019-12-06 16:57 UTC (permalink / raw)
To: Borislav Petkov, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
x86, Baoquan He
Cc: Masayoshi Mizuma, Masayoshi Mizuma, linux-kernel
From: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>
The system sometimes crashes while memory hot-adding on KASLR
enabled system. The crash happens because the regions pointed by
kaslr_regions[].base are overwritten by the hot-added memory.
It happens because of the padding size for kaslr_regions[].base isn't
enough for the system whose physical memory layout has huge space for
memory hotplug. kaslr_regions[].base points "actual installed
memory size + padding" or higher address. So, if the "actual + padding"
is lower address than the maximum memory address, which means the memory
address reachable by memory hot-add, kaslr_regions[].base is destroyed by
the overwritten.
address
^
|------- maximum memory address (Hotplug)
| ^
|------- kaslr_regions[0].base | Hotadd-able region
| ^ |
| | padding |
| V V
|------- actual memory address (Installed on boot)
|
Fix it by getting the maximum memory address from SRAT and store
the value in boot_param, then set the padding size while KASLR
initializing if the default padding size isn't enough.
Changelog:
v6: - Add documents to top of calc_direct_mapping_size() to
explain why the size of direct mapping area is configured
as boot_params.max_addr (0004 patch).
- Add Acked-by from Baoquan (0004 patch).
Masayoshi Mizuma (4):
x86/boot: Wrap up the SRAT traversing code into subtable_parse()
x86/boot: Add max_addr field in struct boot_params
x86/boot: Get the max address from SRAT
x86/mm/KASLR: Adjust the padding size for the direct mapping.
Documentation/x86/zero-page.rst | 4 ++
arch/x86/boot/compressed/acpi.c | 42 +++++++++++++++---
arch/x86/include/uapi/asm/bootparam.h | 2 +-
arch/x86/mm/kaslr.c | 63 ++++++++++++++++++++-------
4 files changed, 88 insertions(+), 23 deletions(-)
--
2.20.1
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v6 1/4] x86/boot: Wrap up the SRAT traversing code into subtable_parse()
2019-12-06 16:57 [PATCH v6 0/4] Adjust the padding size for KASLR Masayoshi Mizuma
@ 2019-12-06 16:57 ` Masayoshi Mizuma
2019-12-06 16:57 ` [PATCH v6 2/4] x86/boot: Add max_addr field in struct boot_params Masayoshi Mizuma
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Masayoshi Mizuma @ 2019-12-06 16:57 UTC (permalink / raw)
To: Borislav Petkov, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
x86, Baoquan He
Cc: Masayoshi Mizuma, Masayoshi Mizuma, linux-kernel
From: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>
Wrap up the SRAT traversing code into subtable_parse().
Reviewed-by: Baoquan He <bhe@redhat.com>
Signed-off-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>
---
arch/x86/boot/compressed/acpi.c | 21 ++++++++++++++-------
1 file changed, 14 insertions(+), 7 deletions(-)
diff --git a/arch/x86/boot/compressed/acpi.c b/arch/x86/boot/compressed/acpi.c
index 25019d42ae93..a0f81438a0fd 100644
--- a/arch/x86/boot/compressed/acpi.c
+++ b/arch/x86/boot/compressed/acpi.c
@@ -362,6 +362,19 @@ static unsigned long get_acpi_srat_table(void)
return 0;
}
+static void subtable_parse(struct acpi_subtable_header *sub_table, int *num)
+{
+ struct acpi_srat_mem_affinity *ma;
+
+ ma = (struct acpi_srat_mem_affinity *)sub_table;
+
+ if (!(ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) && ma->length) {
+ immovable_mem[*num].start = ma->base_address;
+ immovable_mem[*num].size = ma->length;
+ (*num)++;
+ }
+}
+
/**
* count_immovable_mem_regions - Parse SRAT and cache the immovable
* memory regions into the immovable_mem array.
@@ -395,14 +408,8 @@ int count_immovable_mem_regions(void)
while (table + sizeof(struct acpi_subtable_header) < table_end) {
sub_table = (struct acpi_subtable_header *)table;
if (sub_table->type == ACPI_SRAT_TYPE_MEMORY_AFFINITY) {
- struct acpi_srat_mem_affinity *ma;
- ma = (struct acpi_srat_mem_affinity *)sub_table;
- if (!(ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) && ma->length) {
- immovable_mem[num].start = ma->base_address;
- immovable_mem[num].size = ma->length;
- num++;
- }
+ subtable_parse(sub_table, &num);
if (num >= MAX_NUMNODES*2) {
debug_putstr("Too many immovable memory regions, aborting.\n");
--
2.20.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v6 2/4] x86/boot: Add max_addr field in struct boot_params
2019-12-06 16:57 [PATCH v6 0/4] Adjust the padding size for KASLR Masayoshi Mizuma
2019-12-06 16:57 ` [PATCH v6 1/4] x86/boot: Wrap up the SRAT traversing code into subtable_parse() Masayoshi Mizuma
@ 2019-12-06 16:57 ` Masayoshi Mizuma
2019-12-06 16:57 ` [PATCH v6 3/4] x86/boot: Get the max address from SRAT Masayoshi Mizuma
2019-12-06 16:57 ` [PATCH v6 4/4] x86/mm/KASLR: Adjust the padding size for the direct mapping Masayoshi Mizuma
3 siblings, 0 replies; 5+ messages in thread
From: Masayoshi Mizuma @ 2019-12-06 16:57 UTC (permalink / raw)
To: Borislav Petkov, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
x86, Baoquan He
Cc: Masayoshi Mizuma, Masayoshi Mizuma, linux-kernel
From: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>
Add max_addr field in struct boot_params. max_addr shows the
maximum memory address to be reachable by memory hot-add.
max_addr is set by parsing ACPI SRAT.
Reviewed-by: Baoquan He <bhe@redhat.com>
Signed-off-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>
---
Documentation/x86/zero-page.rst | 4 ++++
arch/x86/include/uapi/asm/bootparam.h | 2 +-
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/Documentation/x86/zero-page.rst b/Documentation/x86/zero-page.rst
index f088f5881666..cc3938d68481 100644
--- a/Documentation/x86/zero-page.rst
+++ b/Documentation/x86/zero-page.rst
@@ -19,6 +19,7 @@ Offset/Size Proto Name Meaning
058/008 ALL tboot_addr Physical address of tboot shared page
060/010 ALL ist_info Intel SpeedStep (IST) BIOS support information
(struct ist_info)
+078/010 ALL max_addr The possible maximum physical memory address [1]_
080/010 ALL hd0_info hd0 disk parameter, OBSOLETE!!
090/010 ALL hd1_info hd1 disk parameter, OBSOLETE!!
0A0/010 ALL sys_desc_table System description table (struct sys_desc_table),
@@ -43,3 +44,6 @@ Offset/Size Proto Name Meaning
(array of struct e820_entry)
D00/1EC ALL eddbuf EDD data (array of struct edd_info)
=========== ===== ======================= =================================================
+
+.. [1] max_addr shows the maximum memory address to be reachable by memory
+ hot-add. max_addr is set by parsing ACPI SRAT.
diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h
index c895df5482c5..6efad338bba9 100644
--- a/arch/x86/include/uapi/asm/bootparam.h
+++ b/arch/x86/include/uapi/asm/bootparam.h
@@ -158,7 +158,7 @@ struct boot_params {
__u64 tboot_addr; /* 0x058 */
struct ist_info ist_info; /* 0x060 */
__u64 acpi_rsdp_addr; /* 0x070 */
- __u8 _pad3[8]; /* 0x078 */
+ __u64 max_addr; /* 0x078 */
__u8 hd0_info[16]; /* obsolete! */ /* 0x080 */
__u8 hd1_info[16]; /* obsolete! */ /* 0x090 */
struct sys_desc_table sys_desc_table; /* obsolete! */ /* 0x0a0 */
--
2.20.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v6 3/4] x86/boot: Get the max address from SRAT
2019-12-06 16:57 [PATCH v6 0/4] Adjust the padding size for KASLR Masayoshi Mizuma
2019-12-06 16:57 ` [PATCH v6 1/4] x86/boot: Wrap up the SRAT traversing code into subtable_parse() Masayoshi Mizuma
2019-12-06 16:57 ` [PATCH v6 2/4] x86/boot: Add max_addr field in struct boot_params Masayoshi Mizuma
@ 2019-12-06 16:57 ` Masayoshi Mizuma
2019-12-06 16:57 ` [PATCH v6 4/4] x86/mm/KASLR: Adjust the padding size for the direct mapping Masayoshi Mizuma
3 siblings, 0 replies; 5+ messages in thread
From: Masayoshi Mizuma @ 2019-12-06 16:57 UTC (permalink / raw)
To: Borislav Petkov, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
x86, Baoquan He
Cc: Masayoshi Mizuma, Masayoshi Mizuma, linux-kernel
From: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>
Get the max address from SRAT and write it into boot_params->max_addr.
Acked-by: Baoquan He <bhe@redhat.com>
Signed-off-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>
---
arch/x86/boot/compressed/acpi.c | 33 +++++++++++++++++++++++++++------
1 file changed, 27 insertions(+), 6 deletions(-)
diff --git a/arch/x86/boot/compressed/acpi.c b/arch/x86/boot/compressed/acpi.c
index a0f81438a0fd..47db706656e0 100644
--- a/arch/x86/boot/compressed/acpi.c
+++ b/arch/x86/boot/compressed/acpi.c
@@ -362,17 +362,32 @@ static unsigned long get_acpi_srat_table(void)
return 0;
}
-static void subtable_parse(struct acpi_subtable_header *sub_table, int *num)
+/**
+ * subtable_parse - Cache the immovable memory regions into the
+ * immovable_mem array and update the index of the array.
+ *
+ * Return the end physical address of hotpluggable region.
+ * The system memory can be extended to the address by hotplug.
+ */
+static unsigned long subtable_parse(struct acpi_subtable_header *sub_table,
+ int *num)
{
struct acpi_srat_mem_affinity *ma;
+ unsigned long addr = 0;
ma = (struct acpi_srat_mem_affinity *)sub_table;
- if (!(ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) && ma->length) {
- immovable_mem[*num].start = ma->base_address;
- immovable_mem[*num].size = ma->length;
- (*num)++;
+ if (ma->length) {
+ if (ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE)
+ addr = ma->base_address + ma->length;
+ else {
+ immovable_mem[*num].start = ma->base_address;
+ immovable_mem[*num].size = ma->length;
+ (*num)++;
+ }
}
+
+ return addr;
}
/**
@@ -391,6 +406,7 @@ int count_immovable_mem_regions(void)
struct acpi_subtable_header *sub_table;
struct acpi_table_header *table_header;
char arg[MAX_ACPI_ARG_LENGTH];
+ unsigned long max_addr = 0, addr;
int num = 0;
if (cmdline_find_option("acpi", arg, sizeof(arg)) == 3 &&
@@ -409,7 +425,9 @@ int count_immovable_mem_regions(void)
sub_table = (struct acpi_subtable_header *)table;
if (sub_table->type == ACPI_SRAT_TYPE_MEMORY_AFFINITY) {
- subtable_parse(sub_table, &num);
+ addr = subtable_parse(sub_table, &num);
+ if (addr > max_addr)
+ max_addr = addr;
if (num >= MAX_NUMNODES*2) {
debug_putstr("Too many immovable memory regions, aborting.\n");
@@ -418,6 +436,9 @@ int count_immovable_mem_regions(void)
}
table += sub_table->length;
}
+
+ boot_params->max_addr = max_addr;
+
return num;
}
#endif /* CONFIG_RANDOMIZE_BASE && CONFIG_MEMORY_HOTREMOVE */
--
2.20.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v6 4/4] x86/mm/KASLR: Adjust the padding size for the direct mapping.
2019-12-06 16:57 [PATCH v6 0/4] Adjust the padding size for KASLR Masayoshi Mizuma
` (2 preceding siblings ...)
2019-12-06 16:57 ` [PATCH v6 3/4] x86/boot: Get the max address from SRAT Masayoshi Mizuma
@ 2019-12-06 16:57 ` Masayoshi Mizuma
3 siblings, 0 replies; 5+ messages in thread
From: Masayoshi Mizuma @ 2019-12-06 16:57 UTC (permalink / raw)
To: Borislav Petkov, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
x86, Baoquan He
Cc: Masayoshi Mizuma, Masayoshi Mizuma, linux-kernel
From: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>
The system sometimes crashes while memory hot-adding on KASLR
enabled system. The crash happens because the regions pointed by
kaslr_regions[].base are overwritten by the hot-added memory.
It happens because of the padding size for kaslr_regions[].base isn't
enough for the system whose physical memory layout has huge space for
memory hotplug. kaslr_regions[].base points "actual installed
memory size + padding" or higher address. So, if the "actual + padding"
is lower address than the maximum memory address, which means the memory
address reachable by memory hot-add, kaslr_regions[].base is destroyed by
the overwritten.
address
^
|------- maximum memory address (Hotplug)
| ^
|------- kaslr_regions[0].base | Hotadd-able region
| ^ |
| | padding |
| V V
|------- actual memory address (Installed on boot)
|
Fix it by getting the maximum memory address from SRAT and store
the value in boot_param, then set the padding size while KASLR
initializing if the default padding size isn't enough.
Acked-by: Baoquan He <bhe@redhat.com>
Signed-off-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>
---
arch/x86/mm/kaslr.c | 63 ++++++++++++++++++++++++++++++++++-----------
1 file changed, 48 insertions(+), 15 deletions(-)
diff --git a/arch/x86/mm/kaslr.c b/arch/x86/mm/kaslr.c
index dc6182eecefa..b3f2f468d20f 100644
--- a/arch/x86/mm/kaslr.c
+++ b/arch/x86/mm/kaslr.c
@@ -70,15 +70,58 @@ static inline bool kaslr_memory_enabled(void)
return kaslr_enabled() && !IS_ENABLED(CONFIG_KASAN);
}
+/*
+ * Even though a huge virtual address space is reserved for the direct
+ * mapping of physical memory, e.g in 4-level paging mode, it's 64TB,
+ * rare system can own enough physical memory to use it up, most are
+ * even less than 1TB. So with KASLR enabled, we adapt the size of
+ * direct mapping area to the size of actual physical memory plus the
+ * configured padding CONFIG_RANDOMIZE_MEMORY_PHYSICAL_PADDING.
+ * The left part will be taken out to join memory randomization.
+ *
+ * And in case CONFIG_MEMORY_HOTPLUG is enabled and boot_params.max_addr
+ * has a physical memory address, that means the system memory can be
+ * expanded by memory hot-add to boot_params.max_addr. Set the size
+ * of direct mapping area to boot_params.max_addr so that we can avoid
+ * overwriting the hot-added memory.
+ */
+static inline unsigned long calc_direct_mapping_size(void)
+{
+ unsigned long size_tb, memory_tb;
+
+ memory_tb = DIV_ROUND_UP(max_pfn << PAGE_SHIFT, 1UL << TB_SHIFT) +
+ CONFIG_RANDOMIZE_MEMORY_PHYSICAL_PADDING;
+
+#ifdef CONFIG_MEMORY_HOTPLUG
+ if (boot_params.max_addr) {
+ unsigned long maximum_tb;
+
+ maximum_tb = DIV_ROUND_UP(boot_params.max_addr,
+ 1UL << TB_SHIFT);
+
+ if (maximum_tb > memory_tb)
+ memory_tb = maximum_tb;
+ }
+#endif
+ size_tb = 1 << (MAX_PHYSMEM_BITS - TB_SHIFT);
+
+ /*
+ * Adapt physical memory region size based on available memory
+ */
+ if (memory_tb < size_tb)
+ size_tb = memory_tb;
+
+ return size_tb;
+}
+
/* Initialize base and padding for each memory region randomized with KASLR */
void __init kernel_randomize_memory(void)
{
- size_t i;
- unsigned long vaddr_start, vaddr;
- unsigned long rand, memory_tb;
- struct rnd_state rand_state;
+ unsigned long vaddr_start, vaddr, rand;
unsigned long remain_entropy;
unsigned long vmemmap_size;
+ struct rnd_state rand_state;
+ size_t i;
vaddr_start = pgtable_l5_enabled() ? __PAGE_OFFSET_BASE_L5 : __PAGE_OFFSET_BASE_L4;
vaddr = vaddr_start;
@@ -95,20 +138,10 @@ void __init kernel_randomize_memory(void)
if (!kaslr_memory_enabled())
return;
- kaslr_regions[0].size_tb = 1 << (MAX_PHYSMEM_BITS - TB_SHIFT);
+ kaslr_regions[0].size_tb = calc_direct_mapping_size();
kaslr_regions[1].size_tb = VMALLOC_SIZE_TB;
- /*
- * Update Physical memory mapping to available and
- * add padding if needed (especially for memory hotplug support).
- */
BUG_ON(kaslr_regions[0].base != &page_offset_base);
- memory_tb = DIV_ROUND_UP(max_pfn << PAGE_SHIFT, 1UL << TB_SHIFT) +
- CONFIG_RANDOMIZE_MEMORY_PHYSICAL_PADDING;
-
- /* Adapt phyiscal memory region size based on available memory */
- if (memory_tb < kaslr_regions[0].size_tb)
- kaslr_regions[0].size_tb = memory_tb;
/*
* Calculate the vmemmap region size in TBs, aligned to a TB
--
2.20.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2019-12-06 16:57 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-12-06 16:57 [PATCH v6 0/4] Adjust the padding size for KASLR Masayoshi Mizuma
2019-12-06 16:57 ` [PATCH v6 1/4] x86/boot: Wrap up the SRAT traversing code into subtable_parse() Masayoshi Mizuma
2019-12-06 16:57 ` [PATCH v6 2/4] x86/boot: Add max_addr field in struct boot_params Masayoshi Mizuma
2019-12-06 16:57 ` [PATCH v6 3/4] x86/boot: Get the max address from SRAT Masayoshi Mizuma
2019-12-06 16:57 ` [PATCH v6 4/4] x86/mm/KASLR: Adjust the padding size for the direct mapping Masayoshi Mizuma
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.