summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Garrett <matthewgarrett@google.com>2019-06-07 16:51:47 -0400
committerJarkko Sakkinen <jarkko.sakkinen@linux.intel.com>2019-06-24 16:57:50 -0400
commit166a2809d65b282272c474835ec22c882a39ca1b (patch)
tree3ad4681aa56962a7834f8ad6c8a45d1ec73e3c59
parent82d736ac56d7cd78696c5234853684bad05efadf (diff)
tpm: Don't duplicate events from the final event log in the TCG2 log
After the first call to GetEventLog() on UEFI systems using the TCG2 crypto agile log format, any further log events (other than those triggered by ExitBootServices()) will be logged in both the main log and also in the Final Events Log. While the kernel only calls GetEventLog() immediately before ExitBootServices(), we can't control whether earlier parts of the boot process have done so. This will result in log entries that exist in both logs, and so the current approach of simply appending the Final Event Log to the main log will result in events being duplicated. We can avoid this problem by looking at the size of the Final Event Log just before we call ExitBootServices() and exporting this to the main kernel. The kernel can then skip over all events that occured before ExitBootServices() and only append events that were not also logged to the main log. Signed-off-by: Matthew Garrett <mjg59@google.com> Reported-by: Joe Richey <joerichey@google.com> Suggested-by: Joe Richey <joerichey@google.com> Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> Tested-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
-rw-r--r--drivers/char/tpm/eventlog/efi.c11
-rw-r--r--drivers/firmware/efi/libstub/tpm.c30
-rw-r--r--include/linux/efi.h1
3 files changed, 41 insertions, 1 deletions
diff --git a/drivers/char/tpm/eventlog/efi.c b/drivers/char/tpm/eventlog/efi.c
index 73b981026627..6bb023de17f1 100644
--- a/drivers/char/tpm/eventlog/efi.c
+++ b/drivers/char/tpm/eventlog/efi.c
@@ -75,6 +75,8 @@ int tpm_read_log_efi(struct tpm_chip *chip)
75 goto out; 75 goto out;
76 } 76 }
77 77
78 efi_tpm_final_log_size -= log_tbl->final_events_preboot_size;
79
78 tmp = krealloc(log->bios_event_log, 80 tmp = krealloc(log->bios_event_log,
79 log_size + efi_tpm_final_log_size, 81 log_size + efi_tpm_final_log_size,
80 GFP_KERNEL); 82 GFP_KERNEL);
@@ -85,8 +87,15 @@ int tpm_read_log_efi(struct tpm_chip *chip)
85 } 87 }
86 88
87 log->bios_event_log = tmp; 89 log->bios_event_log = tmp;
90
91 /*
92 * Copy any of the final events log that didn't also end up in the
93 * main log. Events can be logged in both if events are generated
94 * between GetEventLog() and ExitBootServices().
95 */
88 memcpy((void *)log->bios_event_log + log_size, 96 memcpy((void *)log->bios_event_log + log_size,
89 final_tbl->events, efi_tpm_final_log_size); 97 final_tbl->events + log_tbl->final_events_preboot_size,
98 efi_tpm_final_log_size);
90 log->bios_event_log_end = log->bios_event_log + 99 log->bios_event_log_end = log->bios_event_log +
91 log_size + efi_tpm_final_log_size; 100 log_size + efi_tpm_final_log_size;
92 101
diff --git a/drivers/firmware/efi/libstub/tpm.c b/drivers/firmware/efi/libstub/tpm.c
index 6b3b507a54eb..eb9af83e4d59 100644
--- a/drivers/firmware/efi/libstub/tpm.c
+++ b/drivers/firmware/efi/libstub/tpm.c
@@ -64,11 +64,13 @@ void efi_retrieve_tpm2_eventlog(efi_system_table_t *sys_table_arg)
64 efi_status_t status; 64 efi_status_t status;
65 efi_physical_addr_t log_location = 0, log_last_entry = 0; 65 efi_physical_addr_t log_location = 0, log_last_entry = 0;
66 struct linux_efi_tpm_eventlog *log_tbl = NULL; 66 struct linux_efi_tpm_eventlog *log_tbl = NULL;
67 struct efi_tcg2_final_events_table *final_events_table;
67 unsigned long first_entry_addr, last_entry_addr; 68 unsigned long first_entry_addr, last_entry_addr;
68 size_t log_size, last_entry_size; 69 size_t log_size, last_entry_size;
69 efi_bool_t truncated; 70 efi_bool_t truncated;
70 int version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_2; 71 int version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_2;
71 void *tcg2_protocol = NULL; 72 void *tcg2_protocol = NULL;
73 int final_events_size = 0;
72 74
73 status = efi_call_early(locate_protocol, &tcg2_guid, NULL, 75 status = efi_call_early(locate_protocol, &tcg2_guid, NULL,
74 &tcg2_protocol); 76 &tcg2_protocol);
@@ -134,8 +136,36 @@ void efi_retrieve_tpm2_eventlog(efi_system_table_t *sys_table_arg)
134 return; 136 return;
135 } 137 }
136 138
139 /*
140 * Figure out whether any events have already been logged to the
141 * final events structure, and if so how much space they take up
142 */
143 final_events_table = get_efi_config_table(sys_table_arg,
144 LINUX_EFI_TPM_FINAL_LOG_GUID);
145 if (final_events_table && final_events_table->nr_events) {
146 struct tcg_pcr_event2_head *header;
147 int offset;
148 void *data;
149 int event_size;
150 int i = final_events_table->nr_events;
151
152 data = (void *)final_events_table;
153 offset = sizeof(final_events_table->version) +
154 sizeof(final_events_table->nr_events);
155
156 while (i > 0) {
157 header = data + offset + final_events_size;
158 event_size = __calc_tpm2_event_size(header,
159 (void *)(long)log_location,
160 false);
161 final_events_size += event_size;
162 i--;
163 }
164 }
165
137 memset(log_tbl, 0, sizeof(*log_tbl) + log_size); 166 memset(log_tbl, 0, sizeof(*log_tbl) + log_size);
138 log_tbl->size = log_size; 167 log_tbl->size = log_size;
168 log_tbl->final_events_preboot_size = final_events_size;
139 log_tbl->version = version; 169 log_tbl->version = version;
140 memcpy(log_tbl->log, (void *) first_entry_addr, log_size); 170 memcpy(log_tbl->log, (void *) first_entry_addr, log_size);
141 171
diff --git a/include/linux/efi.h b/include/linux/efi.h
index b391263d8ec6..f87fabea4a85 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -1708,6 +1708,7 @@ struct linux_efi_random_seed {
1708 1708
1709struct linux_efi_tpm_eventlog { 1709struct linux_efi_tpm_eventlog {
1710 u32 size; 1710 u32 size;
1711 u32 final_events_preboot_size;
1711 u8 version; 1712 u8 version;
1712 u8 log[]; 1713 u8 log[];
1713}; 1714};