2019-09-26 08:52:22

by Steve Wahl

[permalink] [raw]
Subject: [PATCH v3 0/2] x86/boot/64: Avoid mapping reserved ranges in early page tables.

This patch set narrows the valid space addressed by the page table
level2_kernel_pgt to only contain ranges checked against the "usable
RAM" list provided by the BIOS.

Prior to this, some larger than needed mappings were occasionally
crossing over into spaces marked reserved, allowing the processor to
access these reserved spaces, which were caught by the hardware and
caused BIOS to halt on our platform (UV).

Changes since v1:

* Cover letter added because there's now two patches.

* Patch 1: Added comment and re-worked changelog text.

* Patch 2: New change requested by Dave Hansen to handle the case that
the mapping of the last PMD page for the kernel image could cross a
reserved region boundary.

Changes since v2:

* Patch 1: Added further inline comments.
* Patch 2: None.

Steve Wahl (2):
x86/boot/64: Make level2_kernel_pgt pages invalid outside kernel area.
x86/boot/64: round memory hole size up to next PMD page.

arch/x86/boot/compressed/misc.c | 25 +++++++++++++++++++------
arch/x86/kernel/head64.c | 22 ++++++++++++++++++++--
2 files changed, 39 insertions(+), 8 deletions(-)

--
2.21.0


--
Steve Wahl, Hewlett Packard Enterprise


2019-09-26 08:52:27

by Steve Wahl

[permalink] [raw]
Subject: [PATCH v3 2/2] x86/boot/64: round memory hole size up to next PMD page.

The kernel image map is created using PMD pages, which can include
some extra space beyond what's actually needed. Round the size of the
memory hole we search for up to the next PMD boundary, to be certain
all of the space to be mapped is usable RAM and includes no reserved
areas.

Signed-off-by: Steve Wahl <[email protected]>
Cc: [email protected]
---
Changes since v1:
* This patch is completely new to this verison.
Changes since v2:
None.

arch/x86/boot/compressed/misc.c | 25 +++++++++++++++++++------
1 file changed, 19 insertions(+), 6 deletions(-)

diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c
index 53ac0cb2396d..9652d5c2afda 100644
--- a/arch/x86/boot/compressed/misc.c
+++ b/arch/x86/boot/compressed/misc.c
@@ -345,6 +345,7 @@ asmlinkage __visible void *extract_kernel(void *rmode, memptr heap,
{
const unsigned long kernel_total_size = VO__end - VO__text;
unsigned long virt_addr = LOAD_PHYSICAL_ADDR;
+ unsigned long needed_size;

/* Retain x86 boot parameters pointer passed from startup_32/64. */
boot_params = rmode;
@@ -379,26 +380,38 @@ asmlinkage __visible void *extract_kernel(void *rmode, memptr heap,
free_mem_ptr = heap; /* Heap */
free_mem_end_ptr = heap + BOOT_HEAP_SIZE;

+ /*
+ * The memory hole needed for the kernel is the larger of either
+ * the entire decompressed kernel plus relocation table, or the
+ * entire decompressed kernel plus .bss and .brk sections.
+ *
+ * On X86_64, the memory is mapped with PMD pages. Round the
+ * size up so that the full extent of PMD pages mapped is
+ * included in the check against the valid memory table
+ * entries. This ensures the full mapped area is usable RAM
+ * and doesn't include any reserved areas.
+ */
+ needed_size = max(output_len, kernel_total_size);
+#ifdef CONFIG_X86_64
+ needed_size = ALIGN(needed_size, MIN_KERNEL_ALIGN);
+#endif
+
/* Report initial kernel position details. */
debug_putaddr(input_data);
debug_putaddr(input_len);
debug_putaddr(output);
debug_putaddr(output_len);
debug_putaddr(kernel_total_size);
+ debug_putaddr(needed_size);

#ifdef CONFIG_X86_64
/* Report address of 32-bit trampoline */
debug_putaddr(trampoline_32bit);
#endif

- /*
- * The memory hole needed for the kernel is the larger of either
- * the entire decompressed kernel plus relocation table, or the
- * entire decompressed kernel plus .bss and .brk sections.
- */
choose_random_location((unsigned long)input_data, input_len,
(unsigned long *)&output,
- max(output_len, kernel_total_size),
+ needed_size,
&virt_addr);

/* Validate memory location choices. */
--
2.21.0


--
Steve Wahl, Hewlett Packard Enterprise

2019-09-26 11:00:16

by Kirill A. Shutemov

[permalink] [raw]
Subject: Re: [PATCH v3 2/2] x86/boot/64: round memory hole size up to next PMD page.

On Tue, Sep 24, 2019 at 04:04:31PM -0500, Steve Wahl wrote:
> The kernel image map is created using PMD pages, which can include
> some extra space beyond what's actually needed. Round the size of the
> memory hole we search for up to the next PMD boundary, to be certain
> all of the space to be mapped is usable RAM and includes no reserved
> areas.
>
> Signed-off-by: Steve Wahl <[email protected]>
> Cc: [email protected]

Acked-by: Kirill A. Shutemov <[email protected]>

--
Kirill A. Shutemov

2019-10-10 19:32:55

by Steve Wahl

[permalink] [raw]
Subject: Re: [PATCH v3 0/2] x86/boot/64: Avoid mapping reserved ranges in early page tables.

It's been a while on this patch set; two weeks ago Kirill added acks,
no movement since. Is there anything I need to be doing on my part to
move this forward?

Thanks!

--> Steve Wahl

On Tue, Sep 24, 2019 at 04:03:22PM -0500, Steve Wahl wrote:
> This patch set narrows the valid space addressed by the page table
> level2_kernel_pgt to only contain ranges checked against the "usable
> RAM" list provided by the BIOS.
>
> Prior to this, some larger than needed mappings were occasionally
> crossing over into spaces marked reserved, allowing the processor to
> access these reserved spaces, which were caught by the hardware and
> caused BIOS to halt on our platform (UV).
>
> Changes since v1:
>
> * Cover letter added because there's now two patches.
>
> * Patch 1: Added comment and re-worked changelog text.
>
> * Patch 2: New change requested by Dave Hansen to handle the case that
> the mapping of the last PMD page for the kernel image could cross a
> reserved region boundary.
>
> Changes since v2:
>
> * Patch 1: Added further inline comments.
> * Patch 2: None.
>
> Steve Wahl (2):
> x86/boot/64: Make level2_kernel_pgt pages invalid outside kernel area.
> x86/boot/64: round memory hole size up to next PMD page.
>
> arch/x86/boot/compressed/misc.c | 25 +++++++++++++++++++------
> arch/x86/kernel/head64.c | 22 ++++++++++++++++++++--
> 2 files changed, 39 insertions(+), 8 deletions(-)
>
> --
> 2.21.0
>
>
> --
> Steve Wahl, Hewlett Packard Enterprise

--
Steve Wahl, Hewlett Packard Enterprise

Subject: [tip: x86/urgent] x86/boot/64: Round memory hole size up to next PMD page

The following commit has been merged into the x86/urgent branch of tip:

Commit-ID: 1869dbe87cb94dc9a218ae1d9301dea3678bd4ff
Gitweb: https://git.kernel.org/tip/1869dbe87cb94dc9a218ae1d9301dea3678bd4ff
Author: Steve Wahl <[email protected]>
AuthorDate: Tue, 24 Sep 2019 16:04:31 -05:00
Committer: Borislav Petkov <[email protected]>
CommitterDate: Fri, 11 Oct 2019 18:47:23 +02:00

x86/boot/64: Round memory hole size up to next PMD page

The kernel image map is created using PMD pages, which can include
some extra space beyond what's actually needed. Round the size of the
memory hole we search for up to the next PMD boundary, to be certain
all of the space to be mapped is usable RAM and includes no reserved
areas.

Signed-off-by: Steve Wahl <[email protected]>
Signed-off-by: Borislav Petkov <[email protected]>
Acked-by: Dave Hansen <[email protected]>
Acked-by: Kirill A. Shutemov <[email protected]>
Cc: Baoquan He <[email protected]>
Cc: Brijesh Singh <[email protected]>
Cc: [email protected]
Cc: Feng Tang <[email protected]>
Cc: "H. Peter Anvin" <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jordan Borgner <[email protected]>
Cc: Juergen Gross <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: Thomas Gleixner <[email protected]>
Cc: x86-ml <[email protected]>
Cc: Zhenzhong Duan <[email protected]>
Link: https://lkml.kernel.org/r/df4f49f05c0c27f108234eb93db5c613d09ea62e.1569358539.git.steve.wahl@hpe.com
---
arch/x86/boot/compressed/misc.c | 25 +++++++++++++++++++------
1 file changed, 19 insertions(+), 6 deletions(-)

diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c
index 53ac0cb..9652d5c 100644
--- a/arch/x86/boot/compressed/misc.c
+++ b/arch/x86/boot/compressed/misc.c
@@ -345,6 +345,7 @@ asmlinkage __visible void *extract_kernel(void *rmode, memptr heap,
{
const unsigned long kernel_total_size = VO__end - VO__text;
unsigned long virt_addr = LOAD_PHYSICAL_ADDR;
+ unsigned long needed_size;

/* Retain x86 boot parameters pointer passed from startup_32/64. */
boot_params = rmode;
@@ -379,26 +380,38 @@ asmlinkage __visible void *extract_kernel(void *rmode, memptr heap,
free_mem_ptr = heap; /* Heap */
free_mem_end_ptr = heap + BOOT_HEAP_SIZE;

+ /*
+ * The memory hole needed for the kernel is the larger of either
+ * the entire decompressed kernel plus relocation table, or the
+ * entire decompressed kernel plus .bss and .brk sections.
+ *
+ * On X86_64, the memory is mapped with PMD pages. Round the
+ * size up so that the full extent of PMD pages mapped is
+ * included in the check against the valid memory table
+ * entries. This ensures the full mapped area is usable RAM
+ * and doesn't include any reserved areas.
+ */
+ needed_size = max(output_len, kernel_total_size);
+#ifdef CONFIG_X86_64
+ needed_size = ALIGN(needed_size, MIN_KERNEL_ALIGN);
+#endif
+
/* Report initial kernel position details. */
debug_putaddr(input_data);
debug_putaddr(input_len);
debug_putaddr(output);
debug_putaddr(output_len);
debug_putaddr(kernel_total_size);
+ debug_putaddr(needed_size);

#ifdef CONFIG_X86_64
/* Report address of 32-bit trampoline */
debug_putaddr(trampoline_32bit);
#endif

- /*
- * The memory hole needed for the kernel is the larger of either
- * the entire decompressed kernel plus relocation table, or the
- * entire decompressed kernel plus .bss and .brk sections.
- */
choose_random_location((unsigned long)input_data, input_len,
(unsigned long *)&output,
- max(output_len, kernel_total_size),
+ needed_size,
&virt_addr);

/* Validate memory location choices. */

Subject: [tip: x86/urgent] x86/boot/64: Round memory hole size up to next PMD page

The following commit has been merged into the x86/urgent branch of tip:

Commit-ID: 1869dbe87cb94dc9a218ae1d9301dea3678bd4ff
Gitweb: https://git.kernel.org/tip/1869dbe87cb94dc9a218ae1d9301dea3678bd4ff
Author: Steve Wahl <[email protected]>
AuthorDate: Tue, 24 Sep 2019 16:04:31 -05:00
Committer: Borislav Petkov <[email protected]>
CommitterDate: Fri, 11 Oct 2019 18:47:23 +02:00

x86/boot/64: Round memory hole size up to next PMD page

The kernel image map is created using PMD pages, which can include
some extra space beyond what's actually needed. Round the size of the
memory hole we search for up to the next PMD boundary, to be certain
all of the space to be mapped is usable RAM and includes no reserved
areas.

Signed-off-by: Steve Wahl <[email protected]>
Signed-off-by: Borislav Petkov <[email protected]>
Acked-by: Dave Hansen <[email protected]>
Acked-by: Kirill A. Shutemov <[email protected]>
Cc: Baoquan He <[email protected]>
Cc: Brijesh Singh <[email protected]>
Cc: [email protected]
Cc: Feng Tang <[email protected]>
Cc: "H. Peter Anvin" <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jordan Borgner <[email protected]>
Cc: Juergen Gross <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: Thomas Gleixner <[email protected]>
Cc: x86-ml <[email protected]>
Cc: Zhenzhong Duan <[email protected]>
Link: https://lkml.kernel.org/r/df4f49f05c0c27f108234eb93db5c613d09ea62e.1569358539.git.steve.wahl@hpe.com
---
arch/x86/boot/compressed/misc.c | 25 +++++++++++++++++++------
1 file changed, 19 insertions(+), 6 deletions(-)

diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c
index 53ac0cb..9652d5c 100644
--- a/arch/x86/boot/compressed/misc.c
+++ b/arch/x86/boot/compressed/misc.c
@@ -345,6 +345,7 @@ asmlinkage __visible void *extract_kernel(void *rmode, memptr heap,
{
const unsigned long kernel_total_size = VO__end - VO__text;
unsigned long virt_addr = LOAD_PHYSICAL_ADDR;
+ unsigned long needed_size;

/* Retain x86 boot parameters pointer passed from startup_32/64. */
boot_params = rmode;
@@ -379,26 +380,38 @@ asmlinkage __visible void *extract_kernel(void *rmode, memptr heap,
free_mem_ptr = heap; /* Heap */
free_mem_end_ptr = heap + BOOT_HEAP_SIZE;

+ /*
+ * The memory hole needed for the kernel is the larger of either
+ * the entire decompressed kernel plus relocation table, or the
+ * entire decompressed kernel plus .bss and .brk sections.
+ *
+ * On X86_64, the memory is mapped with PMD pages. Round the
+ * size up so that the full extent of PMD pages mapped is
+ * included in the check against the valid memory table
+ * entries. This ensures the full mapped area is usable RAM
+ * and doesn't include any reserved areas.
+ */
+ needed_size = max(output_len, kernel_total_size);
+#ifdef CONFIG_X86_64
+ needed_size = ALIGN(needed_size, MIN_KERNEL_ALIGN);
+#endif
+
/* Report initial kernel position details. */
debug_putaddr(input_data);
debug_putaddr(input_len);
debug_putaddr(output);
debug_putaddr(output_len);
debug_putaddr(kernel_total_size);
+ debug_putaddr(needed_size);

#ifdef CONFIG_X86_64
/* Report address of 32-bit trampoline */
debug_putaddr(trampoline_32bit);
#endif

- /*
- * The memory hole needed for the kernel is the larger of either
- * the entire decompressed kernel plus relocation table, or the
- * entire decompressed kernel plus .bss and .brk sections.
- */
choose_random_location((unsigned long)input_data, input_len,
(unsigned long *)&output,
- max(output_len, kernel_total_size),
+ needed_size,
&virt_addr);

/* Validate memory location choices. */