lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Message-Id: <20191220005708.65594-1-ganshun@google.com>
Date:   Thu, 19 Dec 2019 16:57:08 -0800
From:   Gan Shun Lim <ganshun@...gle.com>
To:     akpm@...ux-foundation.org
Cc:     linux-kernel@...r.kernel.org, Gan Shun Lim <ganshun@...gle.com>
Subject: [PATCH] Reserve EBDA region

When we boot LinuxBoot-style (as a UEFI binary), sometimes UEFI does
not correctly mark the EBDA region as reserved. We reserve it in all
e820 maps to ensure both the Linuxboot kernel and the future kexec-ed
kernel do not corrupt it. This patch also adds a LinuxBoot config that
selects the RESERVE_EBDA automatically.

Signed-off-by: Gan Shun Lim <ganshun@...gle.com>
---
 arch/x86/Kconfig                | 23 ++++++++++++++++++++
 arch/x86/include/asm/e820/api.h |  1 +
 arch/x86/kernel/e820.c          | 38 +++++++++++++++++++++++++++++++++
 arch/x86/kernel/setup.c         |  4 ++++
 4 files changed, 66 insertions(+)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 5e89499536606..bf3bd0381df70 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -2467,6 +2467,29 @@ config MODIFY_LDT_SYSCALL
 
 source "kernel/livepatch/Kconfig"
 
+config LINUXBOOT
+	bool "LinuxBoot"
+	select KEXEC_CORE
+	select KEXEC
+	select KEXEC_FILE
+	select EFI
+	select EFI_STUB
+	select RESERVE_EBDA
+	help
+	  Include code to handle booting directly out of firmware.
+	  On EFI systems, this means booting with the EFI boot stub
+	  as an EFI application, embedded in the firmware image. LinuxBoot
+	  should then kexec the actual runtime operating system, and is not
+	  meant to keep running.
+
+config RESERVE_EBDA
+	bool "Reserve the EBDA on boot"
+	help
+	  The Extended BIOS Data Area can be left unreserved when booting
+	  LinuxBoot as an EFI application. This unconditionally marks the
+	  area as reserved for both current and kexec-ed kernels so that
+	  it's not accidently corrupted on kexec.
+
 endmenu
 
 config ARCH_HAS_ADD_PAGES
diff --git a/arch/x86/include/asm/e820/api.h b/arch/x86/include/asm/e820/api.h
index e8f58ddd06d97..57c6bc2f78fda 100644
--- a/arch/x86/include/asm/e820/api.h
+++ b/arch/x86/include/asm/e820/api.h
@@ -29,6 +29,7 @@ extern u64  e820__memblock_alloc_reserved(u64 size, u64 align);
 extern void e820__memblock_setup(void);
 
 extern void e820__reserve_setup_data(void);
+extern void e820__reserve_ebda(void);
 extern void e820__finish_early_params(void);
 extern void e820__reserve_resources(void);
 extern void e820__reserve_resources_late(void);
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
index c5399e80c59c5..8401d3fd9b945 100644
--- a/arch/x86/kernel/e820.c
+++ b/arch/x86/kernel/e820.c
@@ -18,6 +18,7 @@
 #include <linux/memory_hotplug.h>
 
 #include <asm/e820/api.h>
+#include <asm/bios_ebda.h>
 #include <asm/setup.h>
 
 /*
@@ -523,6 +524,14 @@ static u64 __init e820__range_update_kexec(u64 start, u64 size, enum e820_type o
 	return __e820__range_update(e820_table_kexec, start, size, old_type, new_type);
 }
 
+static u64 __init e820__range_update_firmware(u64 start, u64 size,
+					      enum e820_type old_type,
+					      enum e820_type  new_type)
+{
+	return __e820__range_update(e820_table_firmware, start, size,
+				    old_type, new_type);
+}
+
 /* Remove a range of memory from the E820 table: */
 u64 __init e820__range_remove(u64 start, u64 size, enum e820_type old_type, bool check_type)
 {
@@ -1022,6 +1031,35 @@ void __init e820__reserve_setup_data(void)
 	e820__print_table("reserve setup_data");
 }
 
+void __init e820__reserve_ebda(void)
+{
+	unsigned long address;
+	unsigned long start_page, new_length;
+	size_t length;
+
+	address = get_bios_ebda();
+	if (!address) {
+		pr_info("BIOS EBDA non-existent.\n");
+		return;
+	}
+	length = get_bios_ebda_length();
+	start_page = ALIGN_DOWN(address, PAGE_SIZE);
+	new_length = PAGE_ALIGN(address + length) - start_page;
+	pr_info("BIOS EBDA structure found at phys 0x%lx, length 0x%x\n",
+		address, (unsigned int)length);
+	pr_info("Reserving EBDA Page aligned starting at 0x%lx, length 0x%lx\n",
+		start_page, new_length);
+	// Reserve page aligned because memremap doesn't allow us to access
+	// mixed pages.
+	e820__range_update(start_page, new_length, E820_TYPE_RAM,
+			   E820_TYPE_RESERVED);
+	// reserve only the actual ebda region to pass on.
+	e820__range_update_kexec(address, length, E820_TYPE_RAM,
+				 E820_TYPE_RESERVED);
+	e820__range_update_firmware(address, length, E820_TYPE_RAM,
+				    E820_TYPE_RESERVED);
+}
+
 /*
  * Called after parse_early_param(), after early parameters (such as mem=)
  * have been processed, in which case we already have an E820 table filled in
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index cedfe2077a69b..06226d8222d13 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -1036,6 +1036,10 @@ void __init setup_arch(char **cmdline_p)
 		setup_clear_cpu_cap(X86_FEATURE_APIC);
 	}
 
+#ifdef CONFIG_LINUXBOOT_RESERVE_EBDA
+	/* update the e820_saved too */
+	e820__reserve_ebda();
+#endif
 	e820__reserve_setup_data();
 	e820__finish_early_params();
 
-- 
2.24.1.735.g03f4e72817-goog

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ