Re: [PATCH] tpm: Don't duplicate events from the final event log in the TCG2 log

2019-06-05 Thread Jarkko Sakkinen
On Tue, Jun 04, 2019 at 12:35:11PM -0700, Matthew Garrett wrote:
> 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.

Sounds flakky how UEFI firmaware works. Wonder why the ignition of the
final events log is bound to the invokation of GetEventLog() in the
first place.

> 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 
> Reported-by: Joe Richey 
> Suggested-by: Joe Richey 

Rename final_events_early_size as final_events_preboot_size because it
is a bit more descriptive name. Other than that looks good to me.

/Jarkko


[PATCH] tpm: Don't duplicate events from the final event log in the TCG2 log

2019-06-04 Thread Matthew Garrett
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 
Reported-by: Joe Richey 
Suggested-by: Joe Richey 
---
 drivers/char/tpm/eventlog/efi.c   | 11 ++-
 .../firmware/efi/libstub/efi-stub-helper.c| 15 ++
 drivers/firmware/efi/libstub/efistub.h|  2 ++
 drivers/firmware/efi/libstub/fdt.c| 27 ++---
 drivers/firmware/efi/libstub/tpm.c| 30 +++
 drivers/firmware/efi/tpm.c|  2 +-
 include/linux/efi.h   |  1 +
 7 files changed, 68 insertions(+), 20 deletions(-)

diff --git a/drivers/char/tpm/eventlog/efi.c b/drivers/char/tpm/eventlog/efi.c
index 9179cf6bdee9..06b7fc99aa4a 100644
--- a/drivers/char/tpm/eventlog/efi.c
+++ b/drivers/char/tpm/eventlog/efi.c
@@ -80,6 +80,8 @@ int tpm_read_log_efi(struct tpm_chip *chip)
goto out;
}
 
+   efi_tpm_final_log_size -= log_tbl->final_events_early_size;
+
tmp = krealloc(log->bios_event_log,
   log_size + efi_tpm_final_log_size,
   GFP_KERNEL);
@@ -90,8 +92,15 @@ int tpm_read_log_efi(struct tpm_chip *chip)
}
 
log->bios_event_log = tmp;
+
+   /*
+* Copy any of the final events log that didn't also end up in the
+* main log. Events can be logged in both if events are generated
+* between GetEventLog() and ExitBootServices().
+*/
memcpy((void *)log->bios_event_log + log_size,
-  final_tbl->events, efi_tpm_final_log_size);
+  final_tbl->events + log_tbl->final_events_early_size,
+  efi_tpm_final_log_size);
log->bios_event_log_end = log->bios_event_log +
log_size + efi_tpm_final_log_size;
 
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c 
b/drivers/firmware/efi/libstub/efi-stub-helper.c
index e4610e72b78f..1db780c0f07b 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -926,3 +926,18 @@ efi_status_t efi_exit_boot_services(efi_system_table_t 
*sys_table_arg,
 fail:
return status;
 }
+
+void *get_efi_config_table(efi_system_table_t *sys_table, efi_guid_t guid)
+{
+   efi_config_table_t *tables = (efi_config_table_t *)sys_table->tables;
+   int i;
+
+   for (i = 0; i < sys_table->nr_tables; i++) {
+   if (efi_guidcmp(tables[i].guid, guid) != 0)
+   continue;
+
+   return (void *)tables[i].table;
+   }
+
+   return NULL;
+}
diff --git a/drivers/firmware/efi/libstub/efistub.h 
b/drivers/firmware/efi/libstub/efistub.h
index 1b1dfcaa6fb9..7f1556fd867d 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -65,6 +65,8 @@ efi_status_t check_platform_features(efi_system_table_t 
*sys_table_arg);
 
 efi_status_t efi_random_get_seed(efi_system_table_t *sys_table_arg);
 
+void *get_efi_config_table(efi_system_table_t *sys_table, efi_guid_t guid);
+
 /* Helper macros for the usual case of using simple C variables: */
 #ifndef fdt_setprop_inplace_var
 #define fdt_setprop_inplace_var(fdt, node_offset, name, var) \
diff --git a/drivers/firmware/efi/libstub/fdt.c 
b/drivers/firmware/efi/libstub/fdt.c
index 5440ba17a1c5..0bf0190917e0 100644
--- a/drivers/firmware/efi/libstub/fdt.c
+++ b/drivers/firmware/efi/libstub/fdt.c
@@ -363,26 +363,17 @@ efi_status_t 
allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
 
 void *get_fdt(efi_system_table_t *sys_table, unsigned long *fdt_size)
 {
-   efi_guid_t fdt_guid = DEVICE_TREE_GUID;
-   efi_config_table_t *tables;
-   int i;
+   void *fdt;
 
-   tables = (efi_config_table_t *)sys_table->tables;
+   fdt = get_efi_config_table(sys_table, DEVICE_TREE_GUID);
 
-   for (i = 0; i < sys_table->nr_tables; i++) {
-   void *fdt;
+   if (!fdt)
+   return NULL;
 
-   if (efi_guidcmp(tables[i].guid, fdt_guid) != 0)
-   continue;
-
-   fdt = (void *)tables[i].table;
-   if (fdt_check_header(fdt) != 0) {
-