Re: [PATCH V7 2/4] tpm: Reserve the TPM final events table

2019-05-31 Thread Joe Richey
On Mon, May 20, 2019 at 1:55 PM Matthew Garrett
 wrote:
>
> From: Matthew Garrett 
>
> UEFI systems provide a boot services protocol for obtaining the TPM
> event log, but this is unusable after ExitBootServices() is called.
> Unfortunately ExitBootServices() itself triggers additional TPM events
> that then can't be obtained using this protocol. The platform provides a
> mechanism for the OS to obtain these events by recording them to a
> separate UEFI configuration table which the OS can then map.
>
> Unfortunately this table isn't self describing in terms of providing its
> length, so we need to parse the events inside it to figure out how long
> it is. Since the table isn't mapped at this point, we need to extend the
> length calculation function to be able to map the event as it goes
> along.
>
> (Fixes by Bartosz Szczepanek )
>
> Signed-off-by: Matthew Garrett 
> ---
>  drivers/char/tpm/eventlog/tpm2.c |   2 +-
>  drivers/firmware/efi/efi.c   |   2 +
>  drivers/firmware/efi/tpm.c   |  62 ++-
>  include/linux/efi.h  |   9 +++
>  include/linux/tpm_eventlog.h | 102 ---
>  5 files changed, 164 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/char/tpm/eventlog/tpm2.c 
> b/drivers/char/tpm/eventlog/tpm2.c
> index 1a977bdd3bd2..de1d9f7e5a92 100644
> --- a/drivers/char/tpm/eventlog/tpm2.c
> +++ b/drivers/char/tpm/eventlog/tpm2.c
> @@ -40,7 +40,7 @@
>  static size_t calc_tpm2_event_size(struct tcg_pcr_event2_head *event,
>struct tcg_pcr_event *event_header)
>  {
> -   return __calc_tpm2_event_size(event, event_header);
> +   return __calc_tpm2_event_size(event, event_header, false);
>  }
>
>  static void *tpm2_bios_measurements_start(struct seq_file *m, loff_t *pos)
> diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
> index 55b77c576c42..6b11c41e0575 100644
> --- a/drivers/firmware/efi/efi.c
> +++ b/drivers/firmware/efi/efi.c
> @@ -53,6 +53,7 @@ struct efi __read_mostly efi = {
> .mem_attr_table = EFI_INVALID_TABLE_ADDR,
> .rng_seed   = EFI_INVALID_TABLE_ADDR,
> .tpm_log= EFI_INVALID_TABLE_ADDR,
> +   .tpm_final_log  = EFI_INVALID_TABLE_ADDR,
> .mem_reserve= EFI_INVALID_TABLE_ADDR,
>  };
>  EXPORT_SYMBOL(efi);
> @@ -485,6 +486,7 @@ static __initdata efi_config_table_type_t common_tables[] 
> = {
> {EFI_MEMORY_ATTRIBUTES_TABLE_GUID, "MEMATTR", &efi.mem_attr_table},
> {LINUX_EFI_RANDOM_SEED_TABLE_GUID, "RNG", &efi.rng_seed},
> {LINUX_EFI_TPM_EVENT_LOG_GUID, "TPMEventLog", &efi.tpm_log},
> +   {LINUX_EFI_TPM_FINAL_LOG_GUID, "TPMFinalLog", &efi.tpm_final_log},
> {LINUX_EFI_MEMRESERVE_TABLE_GUID, "MEMRESERVE", &efi.mem_reserve},
> {NULL_GUID, NULL, NULL},
>  };
> diff --git a/drivers/firmware/efi/tpm.c b/drivers/firmware/efi/tpm.c
> index 3a689b40ccc0..2c912ea08166 100644
> --- a/drivers/firmware/efi/tpm.c
> +++ b/drivers/firmware/efi/tpm.c
> @@ -4,34 +4,90 @@
>   * Thiebaud Weksteen 
>   */
>
> +#define TPM_MEMREMAP(start, size) early_memremap(start, size)
> +#define TPM_MEMUNMAP(start, size) early_memunmap(start, size)
> +
>  #include 
>  #include 
>  #include 
> +#include 
>
>  #include 
>
> +int efi_tpm_final_log_size;
> +EXPORT_SYMBOL(efi_tpm_final_log_size);
> +
> +static int tpm2_calc_event_log_size(void *data, int count, void *size_info)
> +{
> +   struct tcg_pcr_event2_head *header;
> +   int event_size, size = 0;
> +
> +   while (count > 0) {
> +   header = data + size;
> +   event_size = __calc_tpm2_event_size(header, size_info, true);
> +   if (event_size == 0)
> +   return -1;
> +   size += event_size;
> +   count--;
> +   }
> +
> +   return size;
> +}
> +
>  /*
>   * Reserve the memory associated with the TPM Event Log configuration table.
>   */
>  int __init efi_tpm_eventlog_init(void)
>  {
> struct linux_efi_tpm_eventlog *log_tbl;
> +   struct efi_tcg2_final_events_table *final_tbl;
> unsigned int tbl_size;
> +   int ret = 0;
>
> -   if (efi.tpm_log == EFI_INVALID_TABLE_ADDR)
> +   if (efi.tpm_log == EFI_INVALID_TABLE_ADDR) {
> +   /*
> +* We can't calculate the size of the final events without the
> +* first entry in the TPM log, so bail here.
> +*/
> return 0;
> +   }
>
> log_tbl = early_memremap(efi.tpm_log, sizeof(*log_tbl));
> if (!log_tbl) {
> pr_err("Failed to map TPM Event Log table @ 0x%lx\n",
> -   efi.tpm_log);
> +  efi.tpm_log);
> efi.tpm_log = EFI_INVALID_TABLE_ADDR;
> return -ENOMEM;
> }
>
> tbl_size = sizeof(*log_tbl) + log_tbl->size;
> memblock_reserve(efi.tpm_log, tbl_size)

Re: [PATCH V7 2/4] tpm: Reserve the TPM final events table

2019-05-21 Thread Ard Biesheuvel
On Mon, 20 May 2019 at 21:55, Matthew Garrett  wrote:
>
> From: Matthew Garrett 
>
> UEFI systems provide a boot services protocol for obtaining the TPM
> event log, but this is unusable after ExitBootServices() is called.
> Unfortunately ExitBootServices() itself triggers additional TPM events
> that then can't be obtained using this protocol. The platform provides a
> mechanism for the OS to obtain these events by recording them to a
> separate UEFI configuration table which the OS can then map.
>
> Unfortunately this table isn't self describing in terms of providing its
> length, so we need to parse the events inside it to figure out how long
> it is. Since the table isn't mapped at this point, we need to extend the
> length calculation function to be able to map the event as it goes
> along.
>
> (Fixes by Bartosz Szczepanek )
>
> Signed-off-by: Matthew Garrett 

Acked-by: Ard Biesheuvel 

> ---
>  drivers/char/tpm/eventlog/tpm2.c |   2 +-
>  drivers/firmware/efi/efi.c   |   2 +
>  drivers/firmware/efi/tpm.c   |  62 ++-
>  include/linux/efi.h  |   9 +++
>  include/linux/tpm_eventlog.h | 102 ---
>  5 files changed, 164 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/char/tpm/eventlog/tpm2.c 
> b/drivers/char/tpm/eventlog/tpm2.c
> index 1a977bdd3bd2..de1d9f7e5a92 100644
> --- a/drivers/char/tpm/eventlog/tpm2.c
> +++ b/drivers/char/tpm/eventlog/tpm2.c
> @@ -40,7 +40,7 @@
>  static size_t calc_tpm2_event_size(struct tcg_pcr_event2_head *event,
>struct tcg_pcr_event *event_header)
>  {
> -   return __calc_tpm2_event_size(event, event_header);
> +   return __calc_tpm2_event_size(event, event_header, false);
>  }
>
>  static void *tpm2_bios_measurements_start(struct seq_file *m, loff_t *pos)
> diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
> index 55b77c576c42..6b11c41e0575 100644
> --- a/drivers/firmware/efi/efi.c
> +++ b/drivers/firmware/efi/efi.c
> @@ -53,6 +53,7 @@ struct efi __read_mostly efi = {
> .mem_attr_table = EFI_INVALID_TABLE_ADDR,
> .rng_seed   = EFI_INVALID_TABLE_ADDR,
> .tpm_log= EFI_INVALID_TABLE_ADDR,
> +   .tpm_final_log  = EFI_INVALID_TABLE_ADDR,
> .mem_reserve= EFI_INVALID_TABLE_ADDR,
>  };
>  EXPORT_SYMBOL(efi);
> @@ -485,6 +486,7 @@ static __initdata efi_config_table_type_t common_tables[] 
> = {
> {EFI_MEMORY_ATTRIBUTES_TABLE_GUID, "MEMATTR", &efi.mem_attr_table},
> {LINUX_EFI_RANDOM_SEED_TABLE_GUID, "RNG", &efi.rng_seed},
> {LINUX_EFI_TPM_EVENT_LOG_GUID, "TPMEventLog", &efi.tpm_log},
> +   {LINUX_EFI_TPM_FINAL_LOG_GUID, "TPMFinalLog", &efi.tpm_final_log},
> {LINUX_EFI_MEMRESERVE_TABLE_GUID, "MEMRESERVE", &efi.mem_reserve},
> {NULL_GUID, NULL, NULL},
>  };
> diff --git a/drivers/firmware/efi/tpm.c b/drivers/firmware/efi/tpm.c
> index 3a689b40ccc0..2c912ea08166 100644
> --- a/drivers/firmware/efi/tpm.c
> +++ b/drivers/firmware/efi/tpm.c
> @@ -4,34 +4,90 @@
>   * Thiebaud Weksteen 
>   */
>
> +#define TPM_MEMREMAP(start, size) early_memremap(start, size)
> +#define TPM_MEMUNMAP(start, size) early_memunmap(start, size)
> +
>  #include 
>  #include 
>  #include 
> +#include 
>
>  #include 
>
> +int efi_tpm_final_log_size;
> +EXPORT_SYMBOL(efi_tpm_final_log_size);
> +
> +static int tpm2_calc_event_log_size(void *data, int count, void *size_info)
> +{
> +   struct tcg_pcr_event2_head *header;
> +   int event_size, size = 0;
> +
> +   while (count > 0) {
> +   header = data + size;
> +   event_size = __calc_tpm2_event_size(header, size_info, true);
> +   if (event_size == 0)
> +   return -1;
> +   size += event_size;
> +   count--;
> +   }
> +
> +   return size;
> +}
> +
>  /*
>   * Reserve the memory associated with the TPM Event Log configuration table.
>   */
>  int __init efi_tpm_eventlog_init(void)
>  {
> struct linux_efi_tpm_eventlog *log_tbl;
> +   struct efi_tcg2_final_events_table *final_tbl;
> unsigned int tbl_size;
> +   int ret = 0;
>
> -   if (efi.tpm_log == EFI_INVALID_TABLE_ADDR)
> +   if (efi.tpm_log == EFI_INVALID_TABLE_ADDR) {
> +   /*
> +* We can't calculate the size of the final events without the
> +* first entry in the TPM log, so bail here.
> +*/
> return 0;
> +   }
>
> log_tbl = early_memremap(efi.tpm_log, sizeof(*log_tbl));
> if (!log_tbl) {
> pr_err("Failed to map TPM Event Log table @ 0x%lx\n",
> -   efi.tpm_log);
> +  efi.tpm_log);
> efi.tpm_log = EFI_INVALID_TABLE_ADDR;
> return -ENOMEM;
> }
>
> tbl_size = sizeof(*log_tbl) + log_tbl->size;
> memblock_rese

[PATCH V7 2/4] tpm: Reserve the TPM final events table

2019-05-20 Thread Matthew Garrett
From: Matthew Garrett 

UEFI systems provide a boot services protocol for obtaining the TPM
event log, but this is unusable after ExitBootServices() is called.
Unfortunately ExitBootServices() itself triggers additional TPM events
that then can't be obtained using this protocol. The platform provides a
mechanism for the OS to obtain these events by recording them to a
separate UEFI configuration table which the OS can then map.

Unfortunately this table isn't self describing in terms of providing its
length, so we need to parse the events inside it to figure out how long
it is. Since the table isn't mapped at this point, we need to extend the
length calculation function to be able to map the event as it goes
along.

(Fixes by Bartosz Szczepanek )

Signed-off-by: Matthew Garrett 
---
 drivers/char/tpm/eventlog/tpm2.c |   2 +-
 drivers/firmware/efi/efi.c   |   2 +
 drivers/firmware/efi/tpm.c   |  62 ++-
 include/linux/efi.h  |   9 +++
 include/linux/tpm_eventlog.h | 102 ---
 5 files changed, 164 insertions(+), 13 deletions(-)

diff --git a/drivers/char/tpm/eventlog/tpm2.c b/drivers/char/tpm/eventlog/tpm2.c
index 1a977bdd3bd2..de1d9f7e5a92 100644
--- a/drivers/char/tpm/eventlog/tpm2.c
+++ b/drivers/char/tpm/eventlog/tpm2.c
@@ -40,7 +40,7 @@
 static size_t calc_tpm2_event_size(struct tcg_pcr_event2_head *event,
   struct tcg_pcr_event *event_header)
 {
-   return __calc_tpm2_event_size(event, event_header);
+   return __calc_tpm2_event_size(event, event_header, false);
 }
 
 static void *tpm2_bios_measurements_start(struct seq_file *m, loff_t *pos)
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 55b77c576c42..6b11c41e0575 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -53,6 +53,7 @@ struct efi __read_mostly efi = {
.mem_attr_table = EFI_INVALID_TABLE_ADDR,
.rng_seed   = EFI_INVALID_TABLE_ADDR,
.tpm_log= EFI_INVALID_TABLE_ADDR,
+   .tpm_final_log  = EFI_INVALID_TABLE_ADDR,
.mem_reserve= EFI_INVALID_TABLE_ADDR,
 };
 EXPORT_SYMBOL(efi);
@@ -485,6 +486,7 @@ static __initdata efi_config_table_type_t common_tables[] = 
{
{EFI_MEMORY_ATTRIBUTES_TABLE_GUID, "MEMATTR", &efi.mem_attr_table},
{LINUX_EFI_RANDOM_SEED_TABLE_GUID, "RNG", &efi.rng_seed},
{LINUX_EFI_TPM_EVENT_LOG_GUID, "TPMEventLog", &efi.tpm_log},
+   {LINUX_EFI_TPM_FINAL_LOG_GUID, "TPMFinalLog", &efi.tpm_final_log},
{LINUX_EFI_MEMRESERVE_TABLE_GUID, "MEMRESERVE", &efi.mem_reserve},
{NULL_GUID, NULL, NULL},
 };
diff --git a/drivers/firmware/efi/tpm.c b/drivers/firmware/efi/tpm.c
index 3a689b40ccc0..2c912ea08166 100644
--- a/drivers/firmware/efi/tpm.c
+++ b/drivers/firmware/efi/tpm.c
@@ -4,34 +4,90 @@
  * Thiebaud Weksteen 
  */
 
+#define TPM_MEMREMAP(start, size) early_memremap(start, size)
+#define TPM_MEMUNMAP(start, size) early_memunmap(start, size)
+
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
+int efi_tpm_final_log_size;
+EXPORT_SYMBOL(efi_tpm_final_log_size);
+
+static int tpm2_calc_event_log_size(void *data, int count, void *size_info)
+{
+   struct tcg_pcr_event2_head *header;
+   int event_size, size = 0;
+
+   while (count > 0) {
+   header = data + size;
+   event_size = __calc_tpm2_event_size(header, size_info, true);
+   if (event_size == 0)
+   return -1;
+   size += event_size;
+   count--;
+   }
+
+   return size;
+}
+
 /*
  * Reserve the memory associated with the TPM Event Log configuration table.
  */
 int __init efi_tpm_eventlog_init(void)
 {
struct linux_efi_tpm_eventlog *log_tbl;
+   struct efi_tcg2_final_events_table *final_tbl;
unsigned int tbl_size;
+   int ret = 0;
 
-   if (efi.tpm_log == EFI_INVALID_TABLE_ADDR)
+   if (efi.tpm_log == EFI_INVALID_TABLE_ADDR) {
+   /*
+* We can't calculate the size of the final events without the
+* first entry in the TPM log, so bail here.
+*/
return 0;
+   }
 
log_tbl = early_memremap(efi.tpm_log, sizeof(*log_tbl));
if (!log_tbl) {
pr_err("Failed to map TPM Event Log table @ 0x%lx\n",
-   efi.tpm_log);
+  efi.tpm_log);
efi.tpm_log = EFI_INVALID_TABLE_ADDR;
return -ENOMEM;
}
 
tbl_size = sizeof(*log_tbl) + log_tbl->size;
memblock_reserve(efi.tpm_log, tbl_size);
+
+   if (efi.tpm_final_log == EFI_INVALID_TABLE_ADDR)
+   goto out;
+
+   final_tbl = early_memremap(efi.tpm_final_log, sizeof(*final_tbl));
+
+   if (!final_tbl) {
+   pr_err("Failed to map TPM Final Event Log table @ 0x%lx\n",
+  efi.tpm