Commit 70ef6544 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull EFI updates from Ard Biesheuvel:

 - Measure initrd and command line using the CC protocol if the ordinary
   TCG2 protocol is not implemented, typically on TDX confidential VMs

 - Avoid creating mappings that are both writable and executable while
   running in the EFI boot services. This is a prerequisite for getting
   the x86 shim loader signed by MicroSoft again, which allows the
   distros to install on x86 PCs that ship with EFI secure boot enabled.

 - API update for struct platform_driver::remove()

* tag 'efi-next-for-v6.9' of git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi:
  virt: efi_secret: Convert to platform remove callback returning void
  x86/efistub: Remap kernel text read-only before dropping NX attribute
  efi/libstub: Add get_event_log() support for CC platforms
  efi/libstub: Measure into CC protocol if TCG2 protocol is absent
  efi/libstub: Add Confidential Computing (CC) measurement typedefs
  efi/tpm: Use symbolic GUID name from spec for final events table
  efi/libstub: Use TPM event typedefs from the TCG PC Client spec
parents 27b984af 021bc4b9
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -84,7 +84,7 @@ LDFLAGS_vmlinux += -T
hostprogs	:= mkpiggy
HOST_EXTRACFLAGS += -I$(srctree)/tools/include

sed-voffset := -e 's/^\([0-9a-fA-F]*\) [ABCDGRSTVW] \(_text\|__bss_start\|_end\)$$/\#define VO_\2 _AC(0x\1,UL)/p'
sed-voffset := -e 's/^\([0-9a-fA-F]*\) [ABCDGRSTVW] \(_text\|__start_rodata\|__bss_start\|_end\)$$/\#define VO_\2 _AC(0x\1,UL)/p'

quiet_cmd_voffset = VOFFSET $@
      cmd_voffset = $(NM) $< | sed -n $(sed-voffset) > $@
+1 −0
Original line number Diff line number Diff line
@@ -344,6 +344,7 @@ static size_t parse_elf(void *output)
	return ehdr.e_entry - LOAD_PHYSICAL_ADDR;
}

const unsigned long kernel_text_size = VO___start_rodata - VO__text;
const unsigned long kernel_total_size = VO__end - VO__text;

static u8 boot_heap[BOOT_HEAP_SIZE] __aligned(4);
+1 −0
Original line number Diff line number Diff line
@@ -81,6 +81,7 @@

#ifndef __ASSEMBLY__
extern unsigned int output_len;
extern const unsigned long kernel_text_size;
extern const unsigned long kernel_total_size;

unsigned long decompress_kernel(unsigned char *outbuf, unsigned long virt_addr,
+2 −1
Original line number Diff line number Diff line
@@ -597,7 +597,8 @@ static const efi_config_table_type_t common_tables[] __initconst = {
	{EFI_MEMORY_ATTRIBUTES_TABLE_GUID,	&efi_mem_attr_table,	"MEMATTR"	},
	{LINUX_EFI_RANDOM_SEED_TABLE_GUID,	&efi_rng_seed,		"RNG"		},
	{LINUX_EFI_TPM_EVENT_LOG_GUID,		&efi.tpm_log,		"TPMEventLog"	},
	{LINUX_EFI_TPM_FINAL_LOG_GUID,		&efi.tpm_final_log,	"TPMFinalLog"	},
	{EFI_TCG2_FINAL_EVENTS_TABLE_GUID,	&efi.tpm_final_log,	"TPMFinalLog"	},
	{EFI_CC_FINAL_EVENTS_TABLE_GUID,	&efi.tpm_final_log,	"CCFinalLog"	},
	{LINUX_EFI_MEMRESERVE_TABLE_GUID,	&mem_reserve,		"MEMRESERVE"	},
	{LINUX_EFI_INITRD_MEDIA_GUID,		&initrd,		"INITRD"	},
	{EFI_RT_PROPERTIES_TABLE_GUID,		&rt_prop,		"RTPROP"	},
+70 −28
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@

#include <linux/efi.h>
#include <linux/kernel.h>
#include <linux/overflow.h>
#include <asm/efi.h>
#include <asm/setup.h>

@@ -201,7 +202,7 @@ void efi_apply_loadoptions_quirk(const void **load_options, u32 *load_options_si
	*load_options_size = load_option_unpacked.optional_data_size;
}

enum efistub_event {
enum efistub_event_type {
	EFISTUB_EVT_INITRD,
	EFISTUB_EVT_LOAD_OPTIONS,
	EFISTUB_EVT_COUNT,
@@ -227,54 +228,95 @@ static const struct {
	},
};

static_assert(sizeof(efi_tcg2_event_t) == sizeof(efi_cc_event_t));

union efistub_event {
	efi_tcg2_event_t	tcg2_data;
	efi_cc_event_t		cc_data;
};

struct efistub_measured_event {
	union efistub_event	event_data;
	TCG_PCClientTaggedEvent tagged_event __packed;
};

static efi_status_t efi_measure_tagged_event(unsigned long load_addr,
					     unsigned long load_size,
					     enum efistub_event event)
					     enum efistub_event_type event)
{
	union {
		efi_status_t
		(__efiapi *hash_log_extend_event)(void *, u64, efi_physical_addr_t,
						  u64, const union efistub_event *);
		struct { u32 hash_log_extend_event; } mixed_mode;
	} method;
	struct efistub_measured_event *evt;
	int size = struct_size(evt, tagged_event.tagged_event_data,
			       events[event].event_data_len);
	efi_guid_t tcg2_guid = EFI_TCG2_PROTOCOL_GUID;
	efi_tcg2_protocol_t *tcg2 = NULL;
	union efistub_event ev;
	efi_status_t status;
	void *protocol;

	efi_bs_call(locate_protocol, &tcg2_guid, NULL, (void **)&tcg2);
	if (tcg2) {
		struct efi_measured_event {
			efi_tcg2_event_t	event_data;
			efi_tcg2_tagged_event_t tagged_event;
			u8			tagged_event_data[];
		} *evt;
		int size = sizeof(*evt) + events[event].event_data_len;

		status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, size,
				     (void **)&evt);
		if (status != EFI_SUCCESS)
			goto fail;

		evt->event_data = (struct efi_tcg2_event){
		ev.tcg2_data = (struct efi_tcg2_event){
			.event_size			= size,
			.event_header.header_size	= sizeof(evt->event_data.event_header),
			.event_header.header_size	= sizeof(ev.tcg2_data.event_header),
			.event_header.header_version	= EFI_TCG2_EVENT_HEADER_VERSION,
			.event_header.pcr_index		= events[event].pcr_index,
			.event_header.event_type	= EV_EVENT_TAG,
		};
		protocol = tcg2;
		method.hash_log_extend_event =
			(void *)efi_table_attr(tcg2, hash_log_extend_event);
	} else {
		efi_guid_t cc_guid = EFI_CC_MEASUREMENT_PROTOCOL_GUID;
		efi_cc_protocol_t *cc = NULL;

		efi_bs_call(locate_protocol, &cc_guid, NULL, (void **)&cc);
		if (!cc)
			return EFI_UNSUPPORTED;

		evt->tagged_event = (struct efi_tcg2_tagged_event){
			.tagged_event_id		= events[event].event_id,
			.tagged_event_data_size		= events[event].event_data_len,
		ev.cc_data = (struct efi_cc_event){
			.event_size			= size,
			.event_header.header_size	= sizeof(ev.cc_data.event_header),
			.event_header.header_version	= EFI_CC_EVENT_HEADER_VERSION,
			.event_header.event_type	= EV_EVENT_TAG,
		};

		memcpy(evt->tagged_event_data, events[event].event_data,
		status = efi_call_proto(cc, map_pcr_to_mr_index,
					events[event].pcr_index,
					&ev.cc_data.event_header.mr_index);
		if (status != EFI_SUCCESS)
			goto fail;

		protocol = cc;
		method.hash_log_extend_event =
			(void *)efi_table_attr(cc, hash_log_extend_event);
	}

	status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, size, (void **)&evt);
	if (status != EFI_SUCCESS)
		goto fail;

	*evt = (struct efistub_measured_event) {
		.event_data			     = ev,
		.tagged_event.tagged_event_id	     = events[event].event_id,
		.tagged_event.tagged_event_data_size = events[event].event_data_len,
	};

	memcpy(evt->tagged_event.tagged_event_data, events[event].event_data,
	       events[event].event_data_len);

		status = efi_call_proto(tcg2, hash_log_extend_event, 0,
	status = efi_fn_call(&method, hash_log_extend_event, protocol, 0,
			     load_addr, load_size, &evt->event_data);
	efi_bs_call(free_pool, evt);

		if (status != EFI_SUCCESS)
			goto fail;
	if (status == EFI_SUCCESS)
		return EFI_SUCCESS;
	}

	return EFI_UNSUPPORTED;
fail:
	efi_warn("Failed to measure data for event %d: 0x%lx\n", event, status);
	return status;
Loading