Pull EFI fixes from Ingo Molnar: "Misc EFI fixes all across the map: CPER error report fixes, fixes to TPM event log parsing, fix for a kexec hang, a Sparse fix and other fixes" * 'efi-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: efi/tpm: Fix sanity check of unsigned tbl_size being less than zero efi/x86: Do not clean dummy variable in kexec path efi: Make unexported efi_rci2_sysfs_init() static efi/tpm: Only set 'efi_tpm_final_log_size' after successful event log parsing efi/tpm: Don't traverse an event log with no events efi/tpm: Don't access event->count when it isn't mapped efivar/ssdt: Don't iterate over EFI vars if no SSDT override was specified efi/cper: Fix endianness of PCIe class code
Unified · Split
| @@ -917,9 +917,6 @@ static void __init kexec_enter_virtual_mode(void) · 916 unmodified lines | |||
| 917 | 917 | ||
| 918 | if (efi_enabled(EFI_OLD_MEMMAP) && (__supported_pte_mask & _PAGE_NX)) | 918 | if (efi_enabled(EFI_OLD_MEMMAP) && (__supported_pte_mask & _PAGE_NX)) |
| 919 | runtime_code_page_mkexec(); | 919 | runtime_code_page_mkexec(); |
| 920 | |||
| 921 | /* clean DUMMY object */ | ||
| 922 | efi_delete_dummy_variable(); | ||
| 923 | #endif | 920 | #endif |
| 924 | } | 921 | } |
| 925 | 922 | ||
| @@ -381,7 +381,7 @@ static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie, · 380 unmodified lines | |||
| 381 | printk("%s""vendor_id: 0x%04x, device_id: 0x%04x\n", pfx, | 381 | printk("%s""vendor_id: 0x%04x, device_id: 0x%04x\n", pfx, |
| 382 | pcie->device_id.vendor_id, pcie->device_id.device_id); | 382 | pcie->device_id.vendor_id, pcie->device_id.device_id); |
| 383 | p = pcie->device_id.class_code; | 383 | p = pcie->device_id.class_code; |
| 384 | printk("%s""class_code: %02x%02x%02x\n", pfx, p[0], p[1], p[2]); | 384 | printk("%s""class_code: %02x%02x%02x\n", pfx, p[2], p[1], p[0]); |
| 385 | } | 385 | } |
| 386 | if (pcie->validation_bits & CPER_PCIE_VALID_SERIAL_NUMBER) | 386 | if (pcie->validation_bits & CPER_PCIE_VALID_SERIAL_NUMBER) |
| 387 | printk("%s""serial number: 0x%04x, 0x%04x\n", pfx, | 387 | printk("%s""serial number: 0x%04x, 0x%04x\n", pfx, |
| @@ -267,6 +267,9 @@ static __init int efivar_ssdt_load(void) · 266 unmodified lines | |||
| 267 | void *data; | 267 | void *data; |
| 268 | int ret; | 268 | int ret; |
| 269 | 269 | ||
| 270 | if (!efivar_ssdt[0]) | ||
| 271 | return 0; | ||
| 272 | |||
| 270 | ret = efivar_init(efivar_ssdt_iter, &entries, true, &entries); | 273 | ret = efivar_init(efivar_ssdt_iter, &entries, true, &entries); |
| 271 | 274 | ||
| 272 | list_for_each_entry_safe(entry, aux, &entries, list) { | 275 | list_for_each_entry_safe(entry, aux, &entries, list) { |
| @@ -76,7 +76,7 @@ static u16 checksum(void) · 75 unmodified lines | |||
| 76 | return chksum; | 76 | return chksum; |
| 77 | } | 77 | } |
| 78 | 78 | ||
| 79 | int __init efi_rci2_sysfs_init(void) | 79 | static int __init efi_rci2_sysfs_init(void) |
| 80 | { | 80 | { |
| 81 | struct kobject *tables_kobj; | 81 | struct kobject *tables_kobj; |
| 82 | int ret = -ENOMEM; | 82 | int ret = -ENOMEM; |
| @@ -40,7 +40,7 @@ int __init efi_tpm_eventlog_init(void) · 39 unmodified lines | |||
| 40 | { | 40 | { |
| 41 | struct linux_efi_tpm_eventlog *log_tbl; | 41 | struct linux_efi_tpm_eventlog *log_tbl; |
| 42 | struct efi_tcg2_final_events_table *final_tbl; | 42 | struct efi_tcg2_final_events_table *final_tbl; |
| 43 | unsigned int tbl_size; | 43 | int tbl_size; |
| 44 | int ret = 0; | 44 | int ret = 0; |
| 45 | 45 | ||
| 46 | if (efi.tpm_log == EFI_INVALID_TABLE_ADDR) { | 46 | if (efi.tpm_log == EFI_INVALID_TABLE_ADDR) { |
| @@ -75,16 +75,28 @@ int __init efi_tpm_eventlog_init(void) · 28 unmodified lines | |||
| 75 | goto out; | 75 | goto out; |
| 76 | } | 76 | } |
| 77 | 77 | ||
| 78 | tbl_size = tpm2_calc_event_log_size((void *)efi.tpm_final_log | 78 | tbl_size = 0; |
| 79 | + sizeof(final_tbl->version) | 79 | if (final_tbl->nr_events != 0) { |
| 80 | + sizeof(final_tbl->nr_events), | 80 | void *events = (void *)efi.tpm_final_log |
| 81 | final_tbl->nr_events, | 81 | + sizeof(final_tbl->version) |
| 82 | log_tbl->log); | 82 | + sizeof(final_tbl->nr_events); |
| 83 | |||
| 84 | tbl_size = tpm2_calc_event_log_size(events, | ||
| 85 | final_tbl->nr_events, | ||
| 86 | log_tbl->log); | ||
| 87 | } | ||
| 88 | |||
| 89 | if (tbl_size < 0) { | ||
| 90 | pr_err(FW_BUG "Failed to parse event in TPM Final Events Log\n"); | ||
| 91 | goto out_calc; | ||
| 92 | } | ||
| 93 | |||
| 83 | memblock_reserve((unsigned long)final_tbl, | 94 | memblock_reserve((unsigned long)final_tbl, |
| 84 | tbl_size + sizeof(*final_tbl)); | 95 | tbl_size + sizeof(*final_tbl)); |
| 85 | early_memunmap(final_tbl, sizeof(*final_tbl)); | ||
| 86 | efi_tpm_final_log_size = tbl_size; | 96 | efi_tpm_final_log_size = tbl_size; |
| 87 | 97 | ||
| 98 | out_calc: | ||
| 99 | early_memunmap(final_tbl, sizeof(*final_tbl)); | ||
| 88 | out: | 100 | out: |
| 89 | early_memunmap(log_tbl, sizeof(*log_tbl)); | 101 | early_memunmap(log_tbl, sizeof(*log_tbl)); |
| 90 | return ret; | 102 | return ret; |
| @@ -152,7 +152,7 @@ struct tcg_algorithm_info { · 151 unmodified lines | |||
| 152 | * total. Once we've done this we know the offset of the data length field, | 152 | * total. Once we've done this we know the offset of the data length field, |
| 153 | * and can calculate the total size of the event. | 153 | * and can calculate the total size of the event. |
| 154 | * | 154 | * |
| 155 | * Return: size of the event on success, <0 on failure | 155 | * Return: size of the event on success, 0 on failure |
| 156 | */ | 156 | */ |
| 157 | 157 | ||
| 158 | static inline int __calc_tpm2_event_size(struct tcg_pcr_event2_head *event, | 158 | static inline int __calc_tpm2_event_size(struct tcg_pcr_event2_head *event, |
| @@ -170,6 +170,7 @@ static inline int __calc_tpm2_event_size(struct tcg_pcr_event2_head *event, · 11 unmodified lines | |||
| 170 | u16 halg; | 170 | u16 halg; |
| 171 | int i; | 171 | int i; |
| 172 | int j; | 172 | int j; |
| 173 | u32 count, event_type; | ||
| 173 | 174 | ||
| 174 | marker = event; | 175 | marker = event; |
| 175 | marker_start = marker; | 176 | marker_start = marker; |
| @@ -190,16 +191,22 @@ static inline int __calc_tpm2_event_size(struct tcg_pcr_event2_head *event, · 14 unmodified lines | |||
| 190 | } | 191 | } |
| 191 | 192 | ||
| 192 | event = (struct tcg_pcr_event2_head *)mapping; | 193 | event = (struct tcg_pcr_event2_head *)mapping; |
| 194 | /* | ||
| 195 | * The loop below will unmap these fields if the log is larger than | ||
| 196 | * one page, so save them here for reference: | ||
| 197 | */ | ||
| 198 | count = READ_ONCE(event->count); | ||
| 199 | event_type = READ_ONCE(event->event_type); | ||
| 193 | 200 | ||
| 194 | efispecid = (struct tcg_efi_specid_event_head *)event_header->event; | 201 | efispecid = (struct tcg_efi_specid_event_head *)event_header->event; |
| 195 | 202 | ||
| 196 | /* Check if event is malformed. */ | 203 | /* Check if event is malformed. */ |
| 197 | if (event->count > efispecid->num_algs) { | 204 | if (count > efispecid->num_algs) { |
| 198 | size = 0; | 205 | size = 0; |
| 199 | goto out; | 206 | goto out; |
| 200 | } | 207 | } |
| 201 | 208 | ||
| 202 | for (i = 0; i < event->count; i++) { | 209 | for (i = 0; i < count; i++) { |
| 203 | halg_size = sizeof(event->digests[i].alg_id); | 210 | halg_size = sizeof(event->digests[i].alg_id); |
| 204 | 211 | ||
| 205 | /* Map the digest's algorithm identifier */ | 212 | /* Map the digest's algorithm identifier */ |
| @@ -256,8 +263,9 @@ static inline int __calc_tpm2_event_size(struct tcg_pcr_event2_head *event, · 50 unmodified lines | |||
| 256 | + event_field->event_size; | 263 | + event_field->event_size; |
| 257 | size = marker - marker_start; | 264 | size = marker - marker_start; |
| 258 | 265 | ||
| 259 | if ((event->event_type == 0) && (event_field->event_size == 0)) | 266 | if (event_type == 0 && event_field->event_size == 0) |
| 260 | size = 0; | 267 | size = 0; |
| 268 | |||
| 261 | out: | 269 | out: |
| 262 | if (do_mapping) | 270 | if (do_mapping) |
| 263 | TPM_MEMUNMAP(mapping, mapping_size); | 271 | TPM_MEMUNMAP(mapping, mapping_size); |