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>] [thread-next>] [day] [month] [year] [list]
Date:   Sat, 30 Nov 2019 11:50:40 -0800
From:   Rob Clark <robdclark@...il.com>
To:     Leif Lindholm <leif.lindholm@...aro.org>
Cc:     Rob Clark <robdclark@...omium.org>,
        Ard Biesheuvel <ard.biesheuvel@...aro.org>,
        Jarkko Sakkinen <jarkko.sakkinen@...ux.intel.com>,
        Ingo Molnar <mingo@...nel.org>,
        Kairui Song <kasong@...hat.com>,
        Hans de Goede <hdegoede@...hat.com>,
        Matthew Garrett <matthewgarrett@...gle.com>,
        linux-efi@...r.kernel.org (open list:EXTENSIBLE FIRMWARE INTERFACE
        (EFI)), linux-kernel@...r.kernel.org (open list)
Subject: [PATCH] efi/fdt: install new fdt config table

From: Rob Clark <robdclark@...omium.org>

If there is an fdt config table, replace it with the newly allocated one
before calling ExitBootServices().

Signed-off-by: Rob Clark <robdclark@...omium.org>
---
The DtbLoader.efi[1] driver, which Leif created for EBBR boot on the
"windows" aarch64 laptops, tries to detect in an EBS hook, whether the
HLOS is using DT.  It does this by realizing that the kernel cmdline is
patched in to the fdt, and comparing the CRC.  If the CRC has changed,
that means the HLOS is using DT boot, so it removes the ACPI config
tables, so that the HLOS does not see two conflicting sets of config
tables.

However, I realized this mechanism does not work when directly loading
the linux kernel as an efi executable (ie. without an intermediary like
grub doing it's own DT modifications), because efi/libstub is modifying
a copy of the DT config table.

If we update the config table with the new DT, then it will realize
properly that the HLOS is using DT.

[1] https://git.linaro.org/people/leif.lindholm/edk2.git/log/?h=dtbloader

 .../firmware/efi/libstub/efi-stub-helper.c    | 32 +++++++++++++++++++
 drivers/firmware/efi/libstub/efistub.h        |  2 ++
 drivers/firmware/efi/libstub/fdt.c            |  2 ++
 3 files changed, 36 insertions(+)

diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
index 35dbc2791c97..210070f3b231 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -953,3 +953,35 @@ void *get_efi_config_table(efi_system_table_t *sys_table, efi_guid_t guid)
 	else
 		return get_efi_config_table32(sys_table, guid);
 }
+
+#define REPLACE_EFI_CONFIG_TABLE(bits)					\
+static void *replace_efi_config_table##bits(efi_system_table_t *_sys_table, \
+					efi_guid_t guid, void *table)	\
+{									\
+	efi_system_table_##bits##_t *sys_table;				\
+	efi_config_table_##bits##_t *tables;				\
+	int i;								\
+									\
+	sys_table = (typeof(sys_table))_sys_table;			\
+	tables = (typeof(tables))(unsigned long)sys_table->tables;	\
+									\
+	for (i = 0; i < sys_table->nr_tables; i++) {			\
+		if (efi_guidcmp(tables[i].guid, guid) != 0)		\
+			continue;					\
+									\
+		tables[i].table = (uintptr_t)table;			\
+		return;							\
+	}								\
+}
+REPLACE_EFI_CONFIG_TABLE(32)
+REPLACE_EFI_CONFIG_TABLE(64)
+
+/* replaces an existing config table: */
+void replace_efi_config_table(efi_system_table_t *sys_table, efi_guid_t guid,
+			  void *table)
+{
+	if (efi_is_64bit())
+		replace_efi_config_table64(sys_table, guid, table);
+	else
+		replace_efi_config_table32(sys_table, guid, table);
+}
diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
index 7f1556fd867d..66f2927ce26f 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -66,6 +66,8 @@ efi_status_t check_platform_features(efi_system_table_t *sys_table_arg);
 efi_status_t efi_random_get_seed(efi_system_table_t *sys_table_arg);
 
 void *get_efi_config_table(efi_system_table_t *sys_table, efi_guid_t guid);
+void replace_efi_config_table(efi_system_table_t *sys_table, efi_guid_t guid,
+			  void *table);
 
 /* Helper macros for the usual case of using simple C variables: */
 #ifndef fdt_setprop_inplace_var
diff --git a/drivers/firmware/efi/libstub/fdt.c b/drivers/firmware/efi/libstub/fdt.c
index 0bf0190917e0..15887ec2dc3b 100644
--- a/drivers/firmware/efi/libstub/fdt.c
+++ b/drivers/firmware/efi/libstub/fdt.c
@@ -313,6 +313,8 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
 	priv.runtime_entry_count	= &runtime_entry_count;
 	priv.new_fdt_addr		= (void *)*new_fdt_addr;
 
+	replace_efi_config_table(sys_table, DEVICE_TREE_GUID, priv.new_fdt_addr);
+
 	status = efi_exit_boot_services(sys_table, handle, &map, &priv, exit_boot_func);
 
 	if (status == EFI_SUCCESS) {
-- 
2.23.0

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ