diff options
| author | Tom Rini <[email protected]> | 2021-09-16 10:29:40 -0400 |
|---|---|---|
| committer | Tom Rini <[email protected]> | 2021-09-16 10:29:40 -0400 |
| commit | 6674edaabfd271471608146806f5b6540bc76a1b (patch) | |
| tree | 574f8b5265002ad046aa1b81725a9483feb48a8d /lib/efi_loader | |
| parent | 4f8bf67f9c7fec8c5c1ae57c6ba24d337a19c578 (diff) | |
| parent | bb92678ced0b1594b93ab2f10b2c17750c789c96 (diff) | |
Merge tag 'v2021.10-rc4' into next
Prepare v2021.10-rc4
Signed-off-by: Tom Rini <[email protected]>
# gpg: Signature made Tue 14 Sep 2021 06:58:32 PM EDT
# gpg: using RSA key 1A3C7F70E08FAB1707809BBF147C39FF9634B72C
# gpg: Good signature from "Thomas Rini <[email protected]>" [ultimate]
# Conflicts:
# board/Arcturus/ucp1020/spl.c
# cmd/mvebu/Kconfig
# common/Kconfig.boot
# common/image-fit.c
# configs/UCP1020_defconfig
# configs/sifive_unmatched_defconfig
# drivers/pci/Kconfig
# include/configs/UCP1020.h
# include/configs/sifive-unmatched.h
# lib/Makefile
# scripts/config_whitelist.txt
Diffstat (limited to 'lib/efi_loader')
| -rw-r--r-- | lib/efi_loader/Kconfig | 2 | ||||
| -rw-r--r-- | lib/efi_loader/efi_image_loader.c | 35 | ||||
| -rw-r--r-- | lib/efi_loader/efi_tcg2.c | 40 | ||||
| -rw-r--r-- | lib/efi_loader/efi_var_common.c | 41 | ||||
| -rw-r--r-- | lib/efi_loader/efi_var_file.c | 39 | ||||
| -rw-r--r-- | lib/efi_loader/efi_variable.c | 6 | ||||
| -rw-r--r-- | lib/efi_loader/efi_watchdog.c | 3 |
7 files changed, 118 insertions, 48 deletions
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index 0e5231b9252..14bf5f7e92e 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -10,6 +10,7 @@ config EFI_LOADER depends on !EFI_STUB || !X86_64 || EFI_STUB_64BIT # We need EFI_STUB_32BIT to be set on x86_32 with EFI_STUB depends on !EFI_STUB || !X86 || X86_64 || EFI_STUB_32BIT + depends on BLK default y if !ARM || SYS_CPU = armv7 || SYS_CPU = armv8 select LIB_UUID select PARTITION_UUIDS @@ -314,7 +315,6 @@ config EFI_TCG2_PROTOCOL depends on TPM_V2 select SHA1 select SHA256 - select SHA512_ALGO select SHA384 select SHA512 select HASH diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c index a0eb63fcebe..e9572d4d5db 100644 --- a/lib/efi_loader/efi_image_loader.c +++ b/lib/efi_loader/efi_image_loader.c @@ -801,6 +801,23 @@ efi_status_t efi_check_pe(void *buffer, size_t size, void **nt_header) } /** + * section_size() - determine size of section + * + * The size of a section in memory if normally given by VirtualSize. + * If VirtualSize is not provided, use SizeOfRawData. + * + * @sec: section header + * Return: size of section in memory + */ +static u32 section_size(IMAGE_SECTION_HEADER *sec) +{ + if (sec->Misc.VirtualSize) + return sec->Misc.VirtualSize; + else + return sec->SizeOfRawData; +} + +/** * efi_load_pe() - relocate EFI binary * * This function loads all sections from a PE binary into a newly reserved @@ -869,8 +886,9 @@ efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, /* Calculate upper virtual address boundary */ for (i = num_sections - 1; i >= 0; i--) { IMAGE_SECTION_HEADER *sec = §ions[i]; + virt_size = max_t(unsigned long, virt_size, - sec->VirtualAddress + sec->Misc.VirtualSize); + sec->VirtualAddress + section_size(sec)); } /* Read 32/64bit specific header bits */ @@ -880,6 +898,7 @@ efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, image_base = opt->ImageBase; efi_set_code_and_data_type(loaded_image_info, opt->Subsystem); handle->image_type = opt->Subsystem; + virt_size = ALIGN(virt_size, opt->SectionAlignment); efi_reloc = efi_alloc(virt_size, loaded_image_info->image_code_type); if (!efi_reloc) { @@ -890,12 +909,12 @@ efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, handle->entry = efi_reloc + opt->AddressOfEntryPoint; rel_size = opt->DataDirectory[rel_idx].Size; rel = efi_reloc + opt->DataDirectory[rel_idx].VirtualAddress; - virt_size = ALIGN(virt_size, opt->SectionAlignment); } else if (nt->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) { IMAGE_OPTIONAL_HEADER32 *opt = &nt->OptionalHeader; image_base = opt->ImageBase; efi_set_code_and_data_type(loaded_image_info, opt->Subsystem); handle->image_type = opt->Subsystem; + virt_size = ALIGN(virt_size, opt->SectionAlignment); efi_reloc = efi_alloc(virt_size, loaded_image_info->image_code_type); if (!efi_reloc) { @@ -906,7 +925,6 @@ efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, handle->entry = efi_reloc + opt->AddressOfEntryPoint; rel_size = opt->DataDirectory[rel_idx].Size; rel = efi_reloc + opt->DataDirectory[rel_idx].VirtualAddress; - virt_size = ALIGN(virt_size, opt->SectionAlignment); } else { log_err("Invalid optional header magic %x\n", nt->OptionalHeader.Magic); @@ -931,11 +949,16 @@ efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, /* Load sections into RAM */ for (i = num_sections - 1; i >= 0; i--) { IMAGE_SECTION_HEADER *sec = §ions[i]; - memset(efi_reloc + sec->VirtualAddress, 0, - sec->Misc.VirtualSize); + u32 copy_size = section_size(sec); + + if (copy_size > sec->SizeOfRawData) { + copy_size = sec->SizeOfRawData; + memset(efi_reloc + sec->VirtualAddress, 0, + sec->Misc.VirtualSize); + } memcpy(efi_reloc + sec->VirtualAddress, efi + sec->PointerToRawData, - min(sec->Misc.VirtualSize, sec->SizeOfRawData)); + copy_size); } /* Run through relocations */ diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c index 35e69b91129..cb48919223d 100644 --- a/lib/efi_loader/efi_tcg2.c +++ b/lib/efi_loader/efi_tcg2.c @@ -607,8 +607,8 @@ efi_tcg2_get_capability(struct efi_tcg2_protocol *this, goto out; } - if (capability->size < boot_service_capability_min) { - capability->size = boot_service_capability_min; + if (capability->size < BOOT_SERVICE_CAPABILITY_MIN) { + capability->size = BOOT_SERVICE_CAPABILITY_MIN; efi_ret = EFI_BUFFER_TOO_SMALL; goto out; } @@ -708,6 +708,18 @@ efi_tcg2_get_eventlog(struct efi_tcg2_protocol *this, EFI_ENTRY("%p, %u, %p, %p, %p", this, log_format, event_log_location, event_log_last_entry, event_log_truncated); + if (!this || !event_log_location || !event_log_last_entry || + !event_log_truncated) { + ret = EFI_INVALID_PARAMETER; + goto out; + } + + /* Only support TPMV2 */ + if (log_format != TCG2_EVENT_LOG_FORMAT_TCG_2) { + ret = EFI_INVALID_PARAMETER; + goto out; + } + ret = platform_get_tpm2_device(&dev); if (ret != EFI_SUCCESS) { event_log_location = NULL; @@ -853,20 +865,19 @@ efi_status_t tcg2_measure_pe_image(void *efi, u64 efi_size, if (ret != EFI_SUCCESS) return ret; - ret = EFI_CALL(efi_search_protocol(&handle->header, - &efi_guid_loaded_image_device_path, - &handler)); + ret = efi_search_protocol(&handle->header, + &efi_guid_loaded_image_device_path, &handler); if (ret != EFI_SUCCESS) return ret; - device_path = EFI_CALL(handler->protocol_interface); + device_path = handler->protocol_interface; device_path_length = efi_dp_size(device_path); if (device_path_length > 0) { /* add end node size */ device_path_length += sizeof(struct efi_device_path); } event_size = sizeof(struct uefi_image_load_event) + device_path_length; - image_load_event = (struct uefi_image_load_event *)malloc(event_size); + image_load_event = calloc(1, event_size); if (!image_load_event) return EFI_OUT_OF_RESOURCES; @@ -889,10 +900,8 @@ efi_status_t tcg2_measure_pe_image(void *efi, u64 efi_size, goto out; } - if (device_path_length > 0) { - memcpy(image_load_event->device_path, device_path, - device_path_length); - } + /* device_path_length might be zero */ + memcpy(image_load_event->device_path, device_path, device_path_length); ret = tcg2_agile_log_append(pcr_index, event_type, &digest_list, event_size, (u8 *)image_load_event); @@ -946,7 +955,7 @@ efi_tcg2_hash_log_extend_event(struct efi_tcg2_protocol *this, u64 flags, goto out; } - if (efi_tcg_event->header.pcr_index > TPM2_MAX_PCRS) { + if (efi_tcg_event->header.pcr_index > EFI_TCG2_MAX_PCR_INDEX) { ret = EFI_INVALID_PARAMETER; goto out; } @@ -965,6 +974,7 @@ efi_tcg2_hash_log_extend_event(struct efi_tcg2_protocol *this, u64 flags, data_to_hash_len, (void **)&nt); if (ret != EFI_SUCCESS) { log_err("Not a valid PE-COFF file\n"); + ret = EFI_UNSUPPORTED; goto out; } ret = tcg2_hash_pe_image((void *)(uintptr_t)data_to_hash, @@ -1038,9 +1048,15 @@ efi_tcg2_get_active_pcr_banks(struct efi_tcg2_protocol *this, { efi_status_t ret; + if (!this || !active_pcr_banks) { + ret = EFI_INVALID_PARAMETER; + goto out; + } + EFI_ENTRY("%p, %p", this, active_pcr_banks); ret = __get_active_pcr_banks(active_pcr_banks); +out: return EFI_EXIT(ret); } diff --git a/lib/efi_loader/efi_var_common.c b/lib/efi_loader/efi_var_common.c index 3d92afe2ebd..a00bbf16206 100644 --- a/lib/efi_loader/efi_var_common.c +++ b/lib/efi_loader/efi_var_common.c @@ -32,10 +32,10 @@ static const struct efi_auth_var_name_type name_type[] = { {u"KEK", &efi_global_variable_guid, EFI_AUTH_VAR_KEK}, {u"db", &efi_guid_image_security_database, EFI_AUTH_VAR_DB}, {u"dbx", &efi_guid_image_security_database, EFI_AUTH_VAR_DBX}, - /* not used yet {u"dbt", &efi_guid_image_security_database, EFI_AUTH_VAR_DBT}, {u"dbr", &efi_guid_image_security_database, EFI_AUTH_VAR_DBR}, - */ + {u"AuditMode", &efi_global_variable_guid, EFI_AUTH_MODE}, + {u"DeployedMode", &efi_global_variable_guid, EFI_AUTH_MODE}, }; static bool efi_secure_boot; @@ -314,17 +314,40 @@ err: efi_status_t efi_init_secure_state(void) { - enum efi_secure_mode mode = EFI_MODE_SETUP; + enum efi_secure_mode mode; u8 efi_vendor_keys = 0; - efi_uintn_t size = 0; + efi_uintn_t size; efi_status_t ret; + u8 deployed_mode = 0; + u8 audit_mode = 0; + u8 setup_mode = 1; - ret = efi_get_variable_int(L"PK", &efi_global_variable_guid, - NULL, &size, NULL, NULL); - if (ret == EFI_BUFFER_TOO_SMALL) { - if (IS_ENABLED(CONFIG_EFI_SECURE_BOOT)) - mode = EFI_MODE_USER; + if (IS_ENABLED(CONFIG_EFI_SECURE_BOOT)) { + size = sizeof(deployed_mode); + ret = efi_get_variable_int(u"DeployedMode", &efi_global_variable_guid, + NULL, &size, &deployed_mode, NULL); + size = sizeof(audit_mode); + ret = efi_get_variable_int(u"AuditMode", &efi_global_variable_guid, + NULL, &size, &audit_mode, NULL); + size = 0; + ret = efi_get_variable_int(u"PK", &efi_global_variable_guid, + NULL, &size, NULL, NULL); + if (ret == EFI_BUFFER_TOO_SMALL) { + setup_mode = 0; + audit_mode = 0; + } else { + setup_mode = 1; + deployed_mode = 0; + } } + if (deployed_mode) + mode = EFI_MODE_DEPLOYED; + else if (audit_mode) + mode = EFI_MODE_AUDIT; + else if (setup_mode) + mode = EFI_MODE_SETUP; + else + mode = EFI_MODE_USER; ret = efi_transfer_secure_state(mode); if (ret != EFI_SUCCESS) diff --git a/lib/efi_loader/efi_var_file.c b/lib/efi_loader/efi_var_file.c index de076b8cbc4..c7c6805ed05 100644 --- a/lib/efi_loader/efi_var_file.c +++ b/lib/efi_loader/efi_var_file.c @@ -148,9 +148,10 @@ error: #endif } -efi_status_t efi_var_restore(struct efi_var_file *buf) +efi_status_t efi_var_restore(struct efi_var_file *buf, bool safe) { struct efi_var_entry *var, *last_var; + u16 *data; efi_status_t ret; if (buf->reserved || buf->magic != EFI_VAR_FILE_MAGIC || @@ -160,21 +161,29 @@ efi_status_t efi_var_restore(struct efi_var_file *buf) return EFI_INVALID_PARAMETER; } - var = buf->var; last_var = (struct efi_var_entry *)((u8 *)buf + buf->length); - while (var < last_var) { - u16 *data = var->name + u16_strlen(var->name) + 1; + for (var = buf->var; var < last_var; + var = (struct efi_var_entry *) + ALIGN((uintptr_t)data + var->length, 8)) { - if (var->attr & EFI_VARIABLE_NON_VOLATILE && var->length) { - ret = efi_var_mem_ins(var->name, &var->guid, var->attr, - var->length, data, 0, NULL, - var->time); - if (ret != EFI_SUCCESS) - log_err("Failed to set EFI variable %ls\n", - var->name); - } - var = (struct efi_var_entry *) - ALIGN((uintptr_t)data + var->length, 8); + data = var->name + u16_strlen(var->name) + 1; + + /* + * Secure boot related and non-volatile variables shall only be + * restored from U-Boot's preseed. + */ + if (!safe && + (efi_auth_var_get_type(var->name, &var->guid) != + EFI_AUTH_VAR_NONE || + !(var->attr & EFI_VARIABLE_NON_VOLATILE))) + continue; + if (!var->length) + continue; + ret = efi_var_mem_ins(var->name, &var->guid, var->attr, + var->length, data, 0, NULL, + var->time); + if (ret != EFI_SUCCESS) + log_err("Failed to set EFI variable %ls\n", var->name); } return EFI_SUCCESS; } @@ -213,7 +222,7 @@ efi_status_t efi_var_from_file(void) log_err("Failed to load EFI variables\n"); goto error; } - if (buf->length != len || efi_var_restore(buf) != EFI_SUCCESS) + if (buf->length != len || efi_var_restore(buf, false) != EFI_SUCCESS) log_err("Invalid EFI variables file\n"); error: free(buf); diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c index ba0874e9e78..fa2b6bc7a86 100644 --- a/lib/efi_loader/efi_variable.c +++ b/lib/efi_loader/efi_variable.c @@ -247,7 +247,7 @@ efi_status_t efi_set_variable_int(u16 *variable_name, const efi_guid_t *vendor, return EFI_WRITE_PROTECTED; if (IS_ENABLED(CONFIG_EFI_VARIABLES_PRESEED)) { - if (var_type != EFI_AUTH_VAR_NONE) + if (var_type >= EFI_AUTH_VAR_PK) return EFI_WRITE_PROTECTED; } @@ -268,7 +268,7 @@ efi_status_t efi_set_variable_int(u16 *variable_name, const efi_guid_t *vendor, return EFI_NOT_FOUND; } - if (var_type != EFI_AUTH_VAR_NONE) { + if (var_type >= EFI_AUTH_VAR_PK) { /* authentication is mandatory */ if (!(attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)) { @@ -426,7 +426,7 @@ efi_status_t efi_init_variables(void) if (IS_ENABLED(CONFIG_EFI_VARIABLES_PRESEED)) { ret = efi_var_restore((struct efi_var_file *) - __efi_var_file_begin); + __efi_var_file_begin, true); if (ret != EFI_SUCCESS) log_err("Invalid EFI variable seed\n"); } diff --git a/lib/efi_loader/efi_watchdog.c b/lib/efi_loader/efi_watchdog.c index 61ea0f79260..87ca6c5b0b7 100644 --- a/lib/efi_loader/efi_watchdog.c +++ b/lib/efi_loader/efi_watchdog.c @@ -27,8 +27,7 @@ static void EFIAPI efi_watchdog_timer_notify(struct efi_event *event, EFI_ENTRY("%p, %p", event, context); printf("\nEFI: Watchdog timeout\n"); - EFI_CALL_VOID(efi_runtime_services.reset_system(EFI_RESET_COLD, - EFI_SUCCESS, 0, NULL)); + do_reset(NULL, 0, 0, NULL); EFI_EXIT(EFI_UNSUPPORTED); } |
