Commit 70ef6544 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'efi-next-for-v6.9' of git://git.kernel.org/pub/scm/linux/kernel/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
parents 27b984af 021bc4b9
......@@ -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) > $@
......
......@@ -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);
......
......@@ -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,
......
......@@ -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" },
......
......@@ -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;
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;
......
......@@ -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();
......
......@@ -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 {
......@@ -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;
......@@ -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);
......
......@@ -47,39 +47,18 @@ void efi_enable_reset_attack_mitigation(void)
#endif
void efi_retrieve_tpm2_eventlog(void)
static void efi_retrieve_tcg2_eventlog(int version, efi_physical_addr_t log_location,
efi_physical_addr_t log_last_entry,
efi_bool_t truncated,
struct efi_tcg2_final_events_table *final_events_table)
{
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 = 0, log_last_entry = 0;
struct linux_efi_tpm_eventlog *log_tbl = NULL;
struct efi_tcg2_final_events_table *final_events_table = NULL;
unsigned long first_entry_addr, last_entry_addr;
size_t log_size, last_entry_size;
efi_bool_t truncated;
int version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_2;
efi_tcg2_protocol_t *tcg2_protocol = NULL;
int final_events_size = 0;
status = efi_bs_call(locate_protocol, &tcg2_guid, NULL,
(void **)&tcg2_protocol);
if (status != EFI_SUCCESS)
return;
status = efi_call_proto(tcg2_protocol, get_event_log, version,
&log_location, &log_last_entry, &truncated);
if (status != EFI_SUCCESS || !log_location) {
version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2;
status = efi_call_proto(tcg2_protocol, get_event_log, version,
&log_location, &log_last_entry,
&truncated);
if (status != EFI_SUCCESS || !log_location)
return;
}
first_entry_addr = (unsigned long) log_location;
/*
......@@ -93,8 +72,10 @@ void efi_retrieve_tpm2_eventlog(void)
* 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.
*
* CC Event log also uses TCG2 format, handle it same as TPM2.
*/
if (version == EFI_TCG2_EVENT_LOG_FORMAT_TCG_2) {
if (version > EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2) {
/*
* The TCG2 log format has variable length entries,
* and the information to decode the hash algorithms
......@@ -127,8 +108,6 @@ void efi_retrieve_tpm2_eventlog(void)
* Figure out whether any events have already been logged to the
* final events structure, and if so how much space they take up
*/
if (version == EFI_TCG2_EVENT_LOG_FORMAT_TCG_2)
final_events_table = get_efi_config_table(LINUX_EFI_TPM_FINAL_LOG_GUID);
if (final_events_table && final_events_table->nr_events) {
struct tcg_pcr_event2_head *header;
int offset;
......@@ -165,3 +144,50 @@ void efi_retrieve_tpm2_eventlog(void)
err_free:
efi_bs_call(free_pool, log_tbl);
}
void efi_retrieve_eventlog(void)
{
struct efi_tcg2_final_events_table *final_events_table = NULL;
efi_physical_addr_t log_location = 0, log_last_entry = 0;
efi_guid_t tpm2_guid = EFI_TCG2_PROTOCOL_GUID;
int version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_2;
efi_tcg2_protocol_t *tpm2 = NULL;
efi_bool_t truncated;
efi_status_t status;
status = efi_bs_call(locate_protocol, &tpm2_guid, NULL, (void **)&tpm2);
if (status == EFI_SUCCESS) {
status = efi_call_proto(tpm2, get_event_log, version, &log_location,
&log_last_entry, &truncated);
if (status != EFI_SUCCESS || !log_location) {
version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2;
status = efi_call_proto(tpm2, get_event_log, version,
&log_location, &log_last_entry,
&truncated);
} else {
final_events_table =
get_efi_config_table(EFI_TCG2_FINAL_EVENTS_TABLE_GUID);
}
} else {
efi_guid_t cc_guid = EFI_CC_MEASUREMENT_PROTOCOL_GUID;
efi_cc_protocol_t *cc = NULL;
status = efi_bs_call(locate_protocol, &cc_guid, NULL, (void **)&cc);
if (status != EFI_SUCCESS)
return;
version = EFI_CC_EVENT_LOG_FORMAT_TCG_2;
status = efi_call_proto(cc, get_event_log, version, &log_location,
&log_last_entry, &truncated);
final_events_table =
get_efi_config_table(EFI_CC_FINAL_EVENTS_TABLE_GUID);
}
if (status != EFI_SUCCESS || !log_location)
return;
efi_retrieve_tcg2_eventlog(version, log_location, log_last_entry,
truncated, final_events_table);
}
......@@ -236,6 +236,15 @@ efi_status_t efi_adjust_memory_range_protection(unsigned long start,
rounded_end = roundup(start + size, EFI_PAGE_SIZE);
if (memattr != NULL) {
status = efi_call_proto(memattr, set_memory_attributes,
rounded_start,
rounded_end - rounded_start,
EFI_MEMORY_RO);
if (status != EFI_SUCCESS) {
efi_warn("Failed to set EFI_MEMORY_RO attribute\n");
return status;
}
status = efi_call_proto(memattr, clear_memory_attributes,
rounded_start,
rounded_end - rounded_start,
......@@ -812,7 +821,7 @@ static efi_status_t efi_decompress_kernel(unsigned long *kernel_entry)
*kernel_entry = addr + entry;
return efi_adjust_memory_range_protection(addr, kernel_total_size);
return efi_adjust_memory_range_protection(addr, kernel_text_size);
}
static void __noreturn enter_kernel(unsigned long kernel_addr,
......@@ -926,7 +935,7 @@ void __noreturn efi_stub_entry(efi_handle_t handle,
efi_random_get_seed();
efi_retrieve_tpm2_eventlog();
efi_retrieve_eventlog();
setup_graphics(boot_params);
......
......@@ -326,16 +326,15 @@ static int efi_secret_probe(struct platform_device *dev)
return ret;
}
static int efi_secret_remove(struct platform_device *dev)
static void efi_secret_remove(struct platform_device *dev)
{
efi_secret_securityfs_teardown(dev);
efi_secret_unmap_area();
return 0;
}
static struct platform_driver efi_secret_driver = {
.probe = efi_secret_probe,
.remove = efi_secret_remove,
.remove_new = efi_secret_remove,
.driver = {
.name = "efi_secret",
},
......
......@@ -386,6 +386,7 @@ void efi_native_runtime_setup(void);
#define EFI_CONSOLE_OUT_DEVICE_GUID EFI_GUID(0xd3b36f2c, 0xd551, 0x11d4, 0x9a, 0x46, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d)
#define APPLE_PROPERTIES_PROTOCOL_GUID EFI_GUID(0x91bd12fe, 0xf6c3, 0x44fb, 0xa5, 0xb7, 0x51, 0x22, 0xab, 0x30, 0x3a, 0xe0)
#define EFI_TCG2_PROTOCOL_GUID EFI_GUID(0x607f766c, 0x7455, 0x42be, 0x93, 0x0b, 0xe4, 0xd7, 0x6d, 0xb2, 0x72, 0x0f)
#define EFI_TCG2_FINAL_EVENTS_TABLE_GUID EFI_GUID(0x1e2ed096, 0x30e2, 0x4254, 0xbd, 0x89, 0x86, 0x3b, 0xbe, 0xf8, 0x23, 0x25)
#define EFI_LOAD_FILE_PROTOCOL_GUID EFI_GUID(0x56ec3091, 0x954c, 0x11d2, 0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
#define EFI_LOAD_FILE2_PROTOCOL_GUID EFI_GUID(0x4006c0c1, 0xfcb3, 0x403e, 0x99, 0x6d, 0x4a, 0x6c, 0x87, 0x24, 0xe0, 0x6d)
#define EFI_RT_PROPERTIES_TABLE_GUID EFI_GUID(0xeb66918a, 0x7eef, 0x402a, 0x84, 0x2e, 0x93, 0x1d, 0x21, 0xc3, 0x8a, 0xe9)
......@@ -400,6 +401,8 @@ void efi_native_runtime_setup(void);
#define EFI_CERT_X509_GUID EFI_GUID(0xa5c059a1, 0x94e4, 0x4aa7, 0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72)
#define EFI_CERT_X509_SHA256_GUID EFI_GUID(0x3bd2a492, 0x96c0, 0x4079, 0xb4, 0x20, 0xfc, 0xf9, 0x8e, 0xf1, 0x03, 0xed)
#define EFI_CC_BLOB_GUID EFI_GUID(0x067b1f5f, 0xcf26, 0x44c5, 0x85, 0x54, 0x93, 0xd7, 0x77, 0x91, 0x2d, 0x42)
#define EFI_CC_MEASUREMENT_PROTOCOL_GUID EFI_GUID(0x96751a3d, 0x72f4, 0x41a6, 0xa7, 0x94, 0xed, 0x5d, 0x0e, 0x67, 0xae, 0x6b)
#define EFI_CC_FINAL_EVENTS_TABLE_GUID EFI_GUID(0xdd4a4648, 0x2de7, 0x4665, 0x96, 0x4d, 0x21, 0xd9, 0xef, 0x5f, 0xb4, 0x46)
/*
* This GUID is used to pass to the kernel proper the struct screen_info
......@@ -411,7 +414,6 @@ void efi_native_runtime_setup(void);
#define LINUX_EFI_LOADER_ENTRY_GUID EFI_GUID(0x4a67b082, 0x0a4c, 0x41cf, 0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f)
#define LINUX_EFI_RANDOM_SEED_TABLE_GUID EFI_GUID(0x1ce1e5bc, 0x7ceb, 0x42f2, 0x81, 0xe5, 0x8a, 0xad, 0xf1, 0x80, 0xf5, 0x7b)
#define LINUX_EFI_TPM_EVENT_LOG_GUID EFI_GUID(0xb7799cb0, 0xeca2, 0x4943, 0x96, 0x67, 0x1f, 0xae, 0x07, 0xb7, 0x47, 0xfa)
#define LINUX_EFI_TPM_FINAL_LOG_GUID EFI_GUID(0x1e2ed096, 0x30e2, 0x4254, 0xbd, 0x89, 0x86, 0x3b, 0xbe, 0xf8, 0x23, 0x25)
#define LINUX_EFI_MEMRESERVE_TABLE_GUID EFI_GUID(0x888eb0c6, 0x8ede, 0x4ff5, 0xa8, 0xf0, 0x9a, 0xee, 0x5c, 0xb9, 0x77, 0xc2)
#define LINUX_EFI_INITRD_MEDIA_GUID EFI_GUID(0x5568e427, 0x68fc, 0x4f3d, 0xac, 0x74, 0xca, 0x55, 0x52, 0x31, 0xcc, 0x68)
#define LINUX_EFI_MOK_VARIABLE_TABLE_GUID EFI_GUID(0xc451ed2b, 0x9694, 0x45d3, 0xba, 0xba, 0xed, 0x9f, 0x89, 0x88, 0xa3, 0x89)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment