Skip to content

Commit

Permalink
Merge tag 'efi-next-for-v6.9' of git://git.kernel.org/pub/scm/linux/k…
Browse files Browse the repository at this point in the history
…ernel/git/efi/efi

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
  • Loading branch information
Linus Torvalds committed Mar 13, 2024
2 parents 27b984a + 021bc4b commit 70ef654
Show file tree
Hide file tree
Showing 11 changed files with 234 additions and 72 deletions.
2 changes: 1 addition & 1 deletion arch/x86/boot/compressed/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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) > $@
Expand Down
1 change: 1 addition & 0 deletions arch/x86/boot/compressed/misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions arch/x86/include/asm/boot.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
3 changes: 2 additions & 1 deletion drivers/firmware/efi/efi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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" },
Expand Down
98 changes: 70 additions & 28 deletions drivers/firmware/efi/libstub/efi-stub-helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

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

Expand Down Expand Up @@ -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,
Expand All @@ -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;

evt->tagged_event = (struct efi_tcg2_tagged_event){
.tagged_event_id = events[event].event_id,
.tagged_event_data_size = events[event].event_data_len,
};

memcpy(evt->tagged_event_data, events[event].event_data,
events[event].event_data_len);
efi_bs_call(locate_protocol, &cc_guid, NULL, (void **)&cc);
if (!cc)
return EFI_UNSUPPORTED;

status = efi_call_proto(tcg2, hash_log_extend_event, 0,
load_addr, load_size, &evt->event_data);
efi_bs_call(free_pool, evt);
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,
};

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;
return EFI_SUCCESS;

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

return EFI_UNSUPPORTED;
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_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)
return EFI_SUCCESS;

fail:
efi_warn("Failed to measure data for event %d: 0x%lx\n", event, status);
return status;
Expand Down
2 changes: 1 addition & 1 deletion drivers/firmware/efi/libstub/efi-stub.c
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ efi_status_t efi_stub_common(efi_handle_t handle,

si = setup_graphics();

efi_retrieve_tpm2_eventlog();
efi_retrieve_eventlog();

/* Ask the firmware to clear memory on unclean shutdown */
efi_enable_reset_attack_mitigation();
Expand Down
95 changes: 88 additions & 7 deletions drivers/firmware/efi/libstub/efistub.h
Original file line number Diff line number Diff line change
Expand Up @@ -843,14 +843,14 @@ struct efi_tcg2_event {
/* u8[] event follows here */
} __packed;

struct efi_tcg2_tagged_event {
u32 tagged_event_id;
u32 tagged_event_data_size;
/* u8 tagged event data follows here */
} __packed;
/* from TCG PC Client Platform Firmware Profile Specification */
typedef struct tdTCG_PCClientTaggedEvent {
u32 tagged_event_id;
u32 tagged_event_data_size;
u8 tagged_event_data[];
} TCG_PCClientTaggedEvent;

typedef struct efi_tcg2_event efi_tcg2_event_t;
typedef struct efi_tcg2_tagged_event efi_tcg2_tagged_event_t;
typedef union efi_tcg2_protocol efi_tcg2_protocol_t;

union efi_tcg2_protocol {
Expand Down Expand Up @@ -882,6 +882,87 @@ union efi_tcg2_protocol {
} mixed_mode;
};

typedef struct {
u8 major;
u8 minor;
} efi_cc_version_t;

typedef struct {
u8 type;
u8 sub_type;
} efi_cc_type_t;

/* EFI CC type/subtype defines */
#define EFI_CC_TYPE_NONE 0
#define EFI_CC_TYPE_AMD_SEV 1
#define EFI_CC_TYPE_INTEL_TDX 2

typedef u32 efi_cc_mr_index_t;

struct efi_cc_event {
u32 event_size;
struct {
u32 header_size;
u16 header_version;
u32 mr_index;
u32 event_type;
} __packed event_header;
/* u8[] event follows here */
} __packed;

typedef struct efi_cc_event efi_cc_event_t;

typedef u32 efi_cc_event_log_bitmap_t;
typedef u32 efi_cc_event_log_format_t;
typedef u32 efi_cc_event_algorithm_bitmap_t;

typedef struct {
u8 size;
efi_cc_version_t structure_version;
efi_cc_version_t protocol_version;
efi_cc_event_algorithm_bitmap_t hash_algorithm_bitmap;
efi_cc_event_log_bitmap_t supported_event_logs;
efi_cc_type_t cc_type;
} efi_cc_boot_service_cap_t;

#define EFI_CC_EVENT_HEADER_VERSION 1

#define EFI_CC_BOOT_HASH_ALG_SHA384 0x00000004

#define EFI_CC_EVENT_LOG_FORMAT_TCG_2 0x00000002

typedef union efi_cc_protocol efi_cc_protocol_t;

union efi_cc_protocol {
struct {
efi_status_t
(__efiapi *get_capability)(efi_cc_protocol_t *,
efi_cc_boot_service_cap_t *);

efi_status_t
(__efiapi *get_event_log)(efi_cc_protocol_t *,
efi_cc_event_log_format_t,
efi_physical_addr_t *,
efi_physical_addr_t *,
efi_bool_t *);

efi_status_t
(__efiapi *hash_log_extend_event)(efi_cc_protocol_t *, u64,
efi_physical_addr_t, u64,
const efi_cc_event_t *);

efi_status_t
(__efiapi *map_pcr_to_mr_index)(efi_cc_protocol_t *, u32,
efi_cc_mr_index_t *);
};
struct {
u32 get_capability;
u32 get_event_log;
u32 hash_log_extend_event;
u32 map_pcr_to_mr_index;
} mixed_mode;
};

struct riscv_efi_boot_protocol {
u64 revision;

Expand Down Expand Up @@ -1061,7 +1142,7 @@ static inline void
efi_enable_reset_attack_mitigation(void) { }
#endif

void efi_retrieve_tpm2_eventlog(void);
void efi_retrieve_eventlog(void);

struct screen_info *alloc_screen_info(void);
struct screen_info *__alloc_screen_info(void);
Expand Down
Loading

0 comments on commit 70ef654

Please sign in to comment.