Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 33b6d034 authored by Thiebaud Weksteen's avatar Thiebaud Weksteen Committed by Jarkko Sakkinen
Browse files

efi: call get_event_log before ExitBootServices



With TPM 2.0 specification, the event logs may only be accessible by
calling an EFI Boot Service. Modify the EFI stub to copy the log area to
a new Linux-specific EFI configuration table so it remains accessible
once booted.

When calling this service, it is possible to specify the expected format
of the logs: TPM 1.2 (SHA1) or TPM 2.0 ("Crypto Agile"). For now, only the
first format is retrieved.

Signed-off-by: default avatarThiebaud Weksteen <tweek@google.com>
Reviewed-by: default avatarJavier Martinez Canillas <javierm@redhat.com>
Tested-by: default avatarJavier Martinez Canillas <javierm@redhat.com>
Tested-by: default avatarJarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Reviewed-by: default avatarJarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Signed-off-by: default avatarJarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
parent 4d01d29d
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -999,6 +999,7 @@ struct boot_params *efi_main(struct efi_config *c,

	/* Ask the firmware to clear memory on unclean shutdown */
	efi_enable_reset_attack_mitigation(sys_table);
	efi_retrieve_tpm2_eventlog(sys_table);

	setup_graphics(boot_params);

+1 −1
Original line number Diff line number Diff line
@@ -11,7 +11,7 @@
KASAN_SANITIZE_runtime-wrappers.o	:= n

obj-$(CONFIG_ACPI_BGRT) 		+= efi-bgrt.o
obj-$(CONFIG_EFI)			+= efi.o vars.o reboot.o memattr.o
obj-$(CONFIG_EFI)			+= efi.o vars.o reboot.o memattr.o tpm.o
obj-$(CONFIG_EFI)			+= capsule.o memmap.o
obj-$(CONFIG_EFI_VARS)			+= efivars.o
obj-$(CONFIG_EFI_ESRT)			+= esrt.o
+4 −0
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ struct efi __read_mostly efi = {
	.properties_table	= EFI_INVALID_TABLE_ADDR,
	.mem_attr_table		= EFI_INVALID_TABLE_ADDR,
	.rng_seed		= EFI_INVALID_TABLE_ADDR,
	.tpm_log		= EFI_INVALID_TABLE_ADDR
};
EXPORT_SYMBOL(efi);

@@ -464,6 +465,7 @@ static __initdata efi_config_table_type_t common_tables[] = {
	{EFI_PROPERTIES_TABLE_GUID, "PROP", &efi.properties_table},
	{EFI_MEMORY_ATTRIBUTES_TABLE_GUID, "MEMATTR", &efi.mem_attr_table},
	{LINUX_EFI_RANDOM_SEED_TABLE_GUID, "RNG", &efi.rng_seed},
	{LINUX_EFI_TPM_EVENT_LOG_GUID, "TPMEventLog", &efi.tpm_log},
	{NULL_GUID, NULL, NULL},
};

@@ -552,6 +554,8 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz,
	if (efi_enabled(EFI_MEMMAP))
		efi_memattr_init();

	efi_tpm_eventlog_init();

	/* Parse the EFI Properties table if it exists */
	if (efi.properties_table != EFI_INVALID_TABLE_ADDR) {
		efi_properties_table_t *tbl;
+1 −2
Original line number Diff line number Diff line
@@ -30,8 +30,7 @@ OBJECT_FILES_NON_STANDARD := y
# Prevents link failures: __sanitizer_cov_trace_pc() is not linked in.
KCOV_INSTRUMENT			:= n

lib-y				:= efi-stub-helper.o gop.o secureboot.o
lib-$(CONFIG_RESET_ATTACK_MITIGATION) += tpm.o
lib-y				:= efi-stub-helper.o gop.o secureboot.o tpm.o

# include the stub's generic dependencies from lib/ when building for ARM/arm64
arm-deps-y := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c fdt_empty_tree.c fdt_sw.c
+81 −0
Original line number Diff line number Diff line
@@ -4,15 +4,18 @@
 * Copyright (C) 2016 CoreOS, Inc
 * Copyright (C) 2017 Google, Inc.
 *     Matthew Garrett <mjg59@google.com>
 *     Thiebaud Weksteen <tweek@google.com>
 *
 * This file is part of the Linux kernel, and is made available under the
 * terms of the GNU General Public License version 2.
 */
#include <linux/efi.h>
#include <linux/tpm_eventlog.h>
#include <asm/efi.h>

#include "efistub.h"

#ifdef CONFIG_RESET_ATTACK_MITIGATION
static const efi_char16_t efi_MemoryOverWriteRequest_name[] = {
	'M', 'e', 'm', 'o', 'r', 'y', 'O', 'v', 'e', 'r', 'w', 'r', 'i', 't',
	'e', 'R', 'e', 'q', 'u', 'e', 's', 't', 'C', 'o', 'n', 't', 'r', 'o',
@@ -56,3 +59,81 @@ void efi_enable_reset_attack_mitigation(efi_system_table_t *sys_table_arg)
		    EFI_VARIABLE_BOOTSERVICE_ACCESS |
		    EFI_VARIABLE_RUNTIME_ACCESS, sizeof(val), &val);
}

#endif

void efi_retrieve_tpm2_eventlog_1_2(efi_system_table_t *sys_table_arg)
{
	efi_guid_t tcg2_guid = EFI_TCG2_PROTOCOL_GUID;
	efi_guid_t linux_eventlog_guid = LINUX_EFI_TPM_EVENT_LOG_GUID;
	efi_status_t status;
	efi_physical_addr_t log_location, log_last_entry;
	struct linux_efi_tpm_eventlog *log_tbl;
	unsigned long first_entry_addr, last_entry_addr;
	size_t log_size, last_entry_size;
	efi_bool_t truncated;
	void *tcg2_protocol;

	status = efi_call_early(locate_protocol, &tcg2_guid, NULL,
				&tcg2_protocol);
	if (status != EFI_SUCCESS)
		return;

	status = efi_call_proto(efi_tcg2_protocol, get_event_log, tcg2_protocol,
				EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2,
				&log_location, &log_last_entry, &truncated);
	if (status != EFI_SUCCESS)
		return;

	if (!log_location)
		return;
	first_entry_addr = (unsigned long) log_location;

	/*
	 * We populate the EFI table even if the logs are empty.
	 */
	if (!log_last_entry) {
		log_size = 0;
	} else {
		last_entry_addr = (unsigned long) log_last_entry;
		/*
		 * get_event_log only returns the address of the last entry.
		 * We need to calculate its size to deduce the full size of
		 * the logs.
		 */
		last_entry_size = sizeof(struct tcpa_event) +
			((struct tcpa_event *) last_entry_addr)->event_size;
		log_size = log_last_entry - log_location + last_entry_size;
	}

	/* Allocate space for the logs and copy them. */
	status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
				sizeof(*log_tbl) + log_size,
				(void **) &log_tbl);

	if (status != EFI_SUCCESS) {
		efi_printk(sys_table_arg,
			   "Unable to allocate memory for event log\n");
		return;
	}

	memset(log_tbl, 0, sizeof(*log_tbl) + log_size);
	log_tbl->size = log_size;
	log_tbl->version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2;
	memcpy(log_tbl->log, (void *) first_entry_addr, log_size);

	status = efi_call_early(install_configuration_table,
				&linux_eventlog_guid, log_tbl);
	if (status != EFI_SUCCESS)
		goto err_free;
	return;

err_free:
	efi_call_early(free_pool, log_tbl);
}

void efi_retrieve_tpm2_eventlog(efi_system_table_t *sys_table_arg)
{
	/* Only try to retrieve the logs in 1.2 format. */
	efi_retrieve_tpm2_eventlog_1_2(sys_table_arg);
}
Loading