Skip to content

Commit

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

Pull EFI updates from Ard Biesheuvel:
 "Just some cleanups and bug fixes this time around:

   - Align handling of the compiled-in command line with the core kernel

   - Measure the initrd into the TPM also when it was loaded via the EFI
     file I/O protocols

   - Clean up TPM event log handling

   - Sanity check the EFI memory attributes table, and apply it after
     kexec too

   - Assorted other fixes"

* tag 'efi-next-for-v6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi:
  efi: Fix memory leak in efivar_ssdt_load
  efi/libstub: Take command line overrides into account for loaded files
  efi/libstub: Fix command line fallback handling when loading files
  efi/libstub: Parse builtin command line after bootloader provided one
  x86/efi: Apply EFI Memory Attributes after kexec
  x86/efi: Drop support for the EFI_PROPERTIES_TABLE
  efi/memattr: Ignore table if the size is clearly bogus
  efi/zboot: Fix outdated comment about using LoadImage/StartImage
  efi/libstub: Free correct pointer on failure
  libstub,tpm: do not ignore failure case when reading final event log
  tpm: fix unsigned/signed mismatch errors related to __calc_tpm2_event_size
  tpm: do not ignore memblock_reserve return value
  tpm: fix signed/unsigned bug when checking event logs
  efi/libstub: measure initrd to PCR9 independent of source
  efi/libstub: remove unnecessary cmd_line_len from efi_convert_cmdline()
  efi/libstub: fix efi_parse_options() ignoring the default command line
  • Loading branch information
torvalds committed Nov 20, 2024
2 parents fcb3ad4 + c5d91b1 commit 18a411c
Show file tree
Hide file tree
Showing 14 changed files with 117 additions and 133 deletions.
20 changes: 1 addition & 19 deletions arch/x86/platform/efi/efi.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,12 @@
#include <asm/uv/uv.h>

static unsigned long efi_systab_phys __initdata;
static unsigned long prop_phys = EFI_INVALID_TABLE_ADDR;
static unsigned long uga_phys = EFI_INVALID_TABLE_ADDR;
static unsigned long efi_runtime, efi_nr_tables;

unsigned long efi_fw_vendor, efi_config_table;

static const efi_config_table_type_t arch_tables[] __initconst = {
{EFI_PROPERTIES_TABLE_GUID, &prop_phys, "PROP" },
{UGA_IO_PROTOCOL_GUID, &uga_phys, "UGA" },
#ifdef CONFIG_X86_UV
{UV_SYSTEM_TABLE_GUID, &uv_systab_phys, "UVsystab" },
Expand All @@ -82,7 +80,6 @@ static const unsigned long * const efi_tables[] = {
&efi_runtime,
&efi_config_table,
&efi.esrt,
&prop_phys,
&efi_mem_attr_table,
#ifdef CONFIG_EFI_RCI2_TABLE
&rci2_table_phys,
Expand Down Expand Up @@ -502,22 +499,6 @@ void __init efi_init(void)
return;
}

/* Parse the EFI Properties table if it exists */
if (prop_phys != EFI_INVALID_TABLE_ADDR) {
efi_properties_table_t *tbl;

tbl = early_memremap_ro(prop_phys, sizeof(*tbl));
if (tbl == NULL) {
pr_err("Could not map Properties table!\n");
} else {
if (tbl->memory_protection_attribute &
EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA)
set_bit(EFI_NX_PE_DATA, &efi.flags);

early_memunmap(tbl, sizeof(*tbl));
}
}

set_bit(EFI_RUNTIME_SERVICES, &efi.flags);
efi_clean_memmap();

Expand Down Expand Up @@ -784,6 +765,7 @@ static void __init kexec_enter_virtual_mode(void)

efi_sync_low_kernel_mappings();
efi_native_runtime_setup();
efi_runtime_update_mappings();
#endif
}

Expand Down
42 changes: 0 additions & 42 deletions arch/x86/platform/efi/efi_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -412,51 +412,9 @@ static int __init efi_update_mem_attr(struct mm_struct *mm, efi_memory_desc_t *m

void __init efi_runtime_update_mappings(void)
{
efi_memory_desc_t *md;

/*
* Use the EFI Memory Attribute Table for mapping permissions if it
* exists, since it is intended to supersede EFI_PROPERTIES_TABLE.
*/
if (efi_enabled(EFI_MEM_ATTR)) {
efi_disable_ibt_for_runtime = false;
efi_memattr_apply_permissions(NULL, efi_update_mem_attr);
return;
}

/*
* EFI_MEMORY_ATTRIBUTES_TABLE is intended to replace
* EFI_PROPERTIES_TABLE. So, use EFI_PROPERTIES_TABLE to update
* permissions only if EFI_MEMORY_ATTRIBUTES_TABLE is not
* published by the firmware. Even if we find a buggy implementation of
* EFI_MEMORY_ATTRIBUTES_TABLE, don't fall back to
* EFI_PROPERTIES_TABLE, because of the same reason.
*/

if (!efi_enabled(EFI_NX_PE_DATA))
return;

for_each_efi_memory_desc(md) {
unsigned long pf = 0;

if (!(md->attribute & EFI_MEMORY_RUNTIME))
continue;

if (!(md->attribute & EFI_MEMORY_WB))
pf |= _PAGE_PCD;

if ((md->attribute & EFI_MEMORY_XP) ||
(md->type == EFI_RUNTIME_SERVICES_DATA))
pf |= _PAGE_NX;

if (!(md->attribute & EFI_MEMORY_RO) &&
(md->type != EFI_RUNTIME_SERVICES_CODE))
pf |= _PAGE_RW;

if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT))
pf |= _PAGE_ENC;

efi_update_mappings(md, pf);
}
}

Expand Down
10 changes: 4 additions & 6 deletions drivers/firmware/efi/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,10 @@ config EFI_ZBOOT
help
Create the bootable image as an EFI application that carries the
actual kernel image in compressed form, and decompresses it into
memory before executing it via LoadImage/StartImage EFI boot service
calls. For compatibility with non-EFI loaders, the payload can be
decompressed and executed by the loader as well, provided that the
loader implements the decompression algorithm and that non-EFI boot
is supported by the encapsulated image. (The compression algorithm
used is described in the zboot image header)
memory before executing it. For compatibility with non-EFI loaders,
the payload can be decompressed and executed by the loader as well,
provided that the loader implements the decompression algorithm.
(The compression algorithm used is described in the zboot header)

config EFI_ARMSTUB_DTB_LOADER
bool "Enable the DTB loader"
Expand Down
41 changes: 28 additions & 13 deletions drivers/firmware/efi/efi.c
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@ static __init int efivar_ssdt_load(void)
efi_char16_t *name = NULL;
efi_status_t status;
efi_guid_t guid;
int ret = 0;

if (!efivar_ssdt[0])
return 0;
Expand All @@ -294,8 +295,8 @@ static __init int efivar_ssdt_load(void)
efi_char16_t *name_tmp =
krealloc(name, name_size, GFP_KERNEL);
if (!name_tmp) {
kfree(name);
return -ENOMEM;
ret = -ENOMEM;
goto out;
}
name = name_tmp;
continue;
Expand All @@ -309,26 +310,38 @@ static __init int efivar_ssdt_load(void)
pr_info("loading SSDT from variable %s-%pUl\n", efivar_ssdt, &guid);

status = efi.get_variable(name, &guid, NULL, &data_size, NULL);
if (status != EFI_BUFFER_TOO_SMALL || !data_size)
return -EIO;
if (status != EFI_BUFFER_TOO_SMALL || !data_size) {
ret = -EIO;
goto out;
}

data = kmalloc(data_size, GFP_KERNEL);
if (!data)
return -ENOMEM;
if (!data) {
ret = -ENOMEM;
goto out;
}

status = efi.get_variable(name, &guid, NULL, &data_size, data);
if (status == EFI_SUCCESS) {
acpi_status ret = acpi_load_table(data, NULL);
if (ret)
pr_err("failed to load table: %u\n", ret);
else
acpi_status acpi_ret = acpi_load_table(data, NULL);
if (ACPI_FAILURE(acpi_ret)) {
pr_err("efivar_ssdt: failed to load table: %u\n",
acpi_ret);
} else {
/*
* The @data will be in use by ACPI engine,
* do not free it!
*/
continue;
}
} else {
pr_err("failed to get var data: 0x%lx\n", status);
pr_err("efivar_ssdt: failed to get var data: 0x%lx\n", status);
}
kfree(data);
}
return 0;
out:
kfree(name);
return ret;
}
#else
static inline int efivar_ssdt_load(void) { return 0; }
Expand Down Expand Up @@ -433,7 +446,9 @@ static int __init efisubsys_init(void)
error = generic_ops_register();
if (error)
goto err_put;
efivar_ssdt_load();
error = efivar_ssdt_load();
if (error)
pr_err("efi: failed to load SSDT, error %d.\n", error);
platform_device_register_simple("efivars", 0, NULL, 0);
}

Expand Down
12 changes: 6 additions & 6 deletions drivers/firmware/efi/libstub/efi-stub-helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ static efi_status_t efi_measure_tagged_event(unsigned long load_addr,
* Size of memory allocated return in *cmd_line_len.
* Returns NULL on error.
*/
char *efi_convert_cmdline(efi_loaded_image_t *image, int *cmd_line_len)
char *efi_convert_cmdline(efi_loaded_image_t *image)
{
const efi_char16_t *options = efi_table_attr(image, load_options);
u32 options_size = efi_table_attr(image, load_options_size);
Expand Down Expand Up @@ -405,7 +405,6 @@ char *efi_convert_cmdline(efi_loaded_image_t *image, int *cmd_line_len)
snprintf((char *)cmdline_addr, options_bytes, "%.*ls",
options_bytes - 1, options);

*cmd_line_len = options_bytes;
return (char *)cmdline_addr;
}

Expand Down Expand Up @@ -621,10 +620,6 @@ efi_status_t efi_load_initrd(efi_loaded_image_t *image,
status = efi_load_initrd_dev_path(&initrd, hard_limit);
if (status == EFI_SUCCESS) {
efi_info("Loaded initrd from LINUX_EFI_INITRD_MEDIA_GUID device path\n");
if (initrd.size > 0 &&
efi_measure_tagged_event(initrd.base, initrd.size,
EFISTUB_EVT_INITRD) == EFI_SUCCESS)
efi_info("Measured initrd data into PCR 9\n");
} else if (status == EFI_NOT_FOUND) {
status = efi_load_initrd_cmdline(image, &initrd, soft_limit,
hard_limit);
Expand All @@ -637,6 +632,11 @@ efi_status_t efi_load_initrd(efi_loaded_image_t *image,
if (status != EFI_SUCCESS)
goto failed;

if (initrd.size > 0 &&
efi_measure_tagged_event(initrd.base, initrd.size,
EFISTUB_EVT_INITRD) == EFI_SUCCESS)
efi_info("Measured initrd data into PCR 9\n");

status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, sizeof(initrd),
(void **)&tbl);
if (status != EFI_SUCCESS)
Expand Down
26 changes: 11 additions & 15 deletions drivers/firmware/efi/libstub/efi-stub.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,6 @@ static u32 get_supported_rt_services(void)

efi_status_t efi_handle_cmdline(efi_loaded_image_t *image, char **cmdline_ptr)
{
int cmdline_size = 0;
efi_status_t status;
char *cmdline;

Expand All @@ -121,35 +120,32 @@ efi_status_t efi_handle_cmdline(efi_loaded_image_t *image, char **cmdline_ptr)
* protocol. We are going to copy the command line into the
* device tree, so this can be allocated anywhere.
*/
cmdline = efi_convert_cmdline(image, &cmdline_size);
cmdline = efi_convert_cmdline(image);
if (!cmdline) {
efi_err("getting command line via LOADED_IMAGE_PROTOCOL\n");
return EFI_OUT_OF_RESOURCES;
}

if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) ||
IS_ENABLED(CONFIG_CMDLINE_FORCE) ||
cmdline_size == 0) {
status = efi_parse_options(CONFIG_CMDLINE);
if (status != EFI_SUCCESS) {
efi_err("Failed to parse options\n");
if (!IS_ENABLED(CONFIG_CMDLINE_FORCE)) {
status = efi_parse_options(cmdline);
if (status != EFI_SUCCESS)
goto fail_free_cmdline;
}
}

if (!IS_ENABLED(CONFIG_CMDLINE_FORCE) && cmdline_size > 0) {
status = efi_parse_options(cmdline);
if (status != EFI_SUCCESS) {
efi_err("Failed to parse options\n");
if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) ||
IS_ENABLED(CONFIG_CMDLINE_FORCE) ||
cmdline[0] == 0) {
status = efi_parse_options(CONFIG_CMDLINE);
if (status != EFI_SUCCESS)
goto fail_free_cmdline;
}
}

*cmdline_ptr = cmdline;
return EFI_SUCCESS;

fail_free_cmdline:
efi_bs_call(free_pool, cmdline_ptr);
efi_err("Failed to parse options\n");
efi_bs_call(free_pool, cmdline);
return status;
}

Expand Down
2 changes: 1 addition & 1 deletion drivers/firmware/efi/libstub/efistub.h
Original file line number Diff line number Diff line change
Expand Up @@ -1056,7 +1056,7 @@ void efi_free(unsigned long size, unsigned long addr);

void efi_apply_loadoptions_quirk(const void **load_options, u32 *load_options_size);

char *efi_convert_cmdline(efi_loaded_image_t *image, int *cmd_line_len);
char *efi_convert_cmdline(efi_loaded_image_t *image);

efi_status_t efi_get_memory_map(struct efi_boot_memmap **map,
bool install_cfg_tbl);
Expand Down
22 changes: 22 additions & 0 deletions drivers/firmware/efi/libstub/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,12 @@ static efi_status_t efi_open_device_path(efi_file_protocol_t **volume,
return status;
}

#ifndef CONFIG_CMDLINE
#define CONFIG_CMDLINE
#endif

static const efi_char16_t builtin_cmdline[] = L"" CONFIG_CMDLINE;

/*
* Check the cmdline for a LILO-style file= arguments.
*
Expand All @@ -189,6 +195,8 @@ efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
unsigned long *load_addr,
unsigned long *load_size)
{
const bool ignore_load_options = IS_ENABLED(CONFIG_CMDLINE_OVERRIDE) ||
IS_ENABLED(CONFIG_CMDLINE_FORCE);
const efi_char16_t *cmdline = efi_table_attr(image, load_options);
u32 cmdline_len = efi_table_attr(image, load_options_size);
unsigned long efi_chunk_size = ULONG_MAX;
Expand All @@ -197,6 +205,7 @@ efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
unsigned long alloc_addr;
unsigned long alloc_size;
efi_status_t status;
bool twopass;
int offset;

if (!load_addr || !load_size)
Expand All @@ -209,6 +218,16 @@ efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
efi_chunk_size = EFI_READ_CHUNK_SIZE;

alloc_addr = alloc_size = 0;

if (!ignore_load_options && cmdline_len > 0) {
twopass = IS_ENABLED(CONFIG_CMDLINE_BOOL) ||
IS_ENABLED(CONFIG_CMDLINE_EXTEND);
} else {
do_builtin: cmdline = builtin_cmdline;
cmdline_len = ARRAY_SIZE(builtin_cmdline) - 1;
twopass = false;
}

do {
struct finfo fi;
unsigned long size;
Expand Down Expand Up @@ -290,6 +309,9 @@ efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
efi_call_proto(volume, close);
} while (offset > 0);

if (twopass)
goto do_builtin;

*load_addr = alloc_addr;
*load_size = alloc_size;

Expand Down
9 changes: 6 additions & 3 deletions drivers/firmware/efi/libstub/tpm.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ static void efi_retrieve_tcg2_eventlog(int version, efi_physical_addr_t log_loca
struct linux_efi_tpm_eventlog *log_tbl = NULL;
unsigned long first_entry_addr, last_entry_addr;
size_t log_size, last_entry_size;
int final_events_size = 0;
u32 final_events_size = 0;

first_entry_addr = (unsigned long) log_location;

Expand Down Expand Up @@ -110,9 +110,9 @@ static void efi_retrieve_tcg2_eventlog(int version, efi_physical_addr_t log_loca
*/
if (final_events_table && final_events_table->nr_events) {
struct tcg_pcr_event2_head *header;
int offset;
u32 offset;
void *data;
int event_size;
u32 event_size;
int i = final_events_table->nr_events;

data = (void *)final_events_table;
Expand All @@ -124,6 +124,9 @@ static void efi_retrieve_tcg2_eventlog(int version, efi_physical_addr_t log_loca
event_size = __calc_tpm2_event_size(header,
(void *)(long)log_location,
false);
/* If calc fails this is a malformed log */
if (!event_size)
break;
final_events_size += event_size;
i--;
}
Expand Down
Loading

0 comments on commit 18a411c

Please sign in to comment.