157 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			157 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
						|
From: Michael Chang <mchang@suse.com>
 | 
						|
Date: Wed, 22 Mar 2023 12:25:43 +0800
 | 
						|
Subject: [PATCH] tpm: Disable the tpm verifier if the TPM device is not
 | 
						|
 present
 | 
						|
 | 
						|
When the tpm module is loaded, the verifier reads entire file into
 | 
						|
memory, measures it and uses verified content as a backing buffer for
 | 
						|
file accesses. However, this process may result in high memory
 | 
						|
utilization for file operations, sometimes causing a system to run out
 | 
						|
of memory which may finally lead to boot failure. To address this issue,
 | 
						|
among others, the commit 887f98f0d (mm: Allow dynamically requesting
 | 
						|
additional memory regions) have optimized memory management by
 | 
						|
dynamically allocating heap space to maximize memory usage and reduce
 | 
						|
threat of memory exhaustion. But in some cases problems may still arise,
 | 
						|
e.g., when large ISO images are mounted using loopback or when dealing
 | 
						|
with embedded systems with limited memory resources.
 | 
						|
 | 
						|
Unfortunately current implementation of the tpm module doesn't allow
 | 
						|
elimination of the back buffer once it is loaded. Even if the TPM device
 | 
						|
is not present or it has been explicitly disabled. This may unnecessary
 | 
						|
allocate a lot memory. To solve this issue, a patch has been developed
 | 
						|
to detect the TPM status at module load and skip verifier registration
 | 
						|
if the device is missing or deactivated. This prevents allocation of
 | 
						|
memory for the back buffer, avoiding wasting memory when no real measure
 | 
						|
boot functionality is performed. Disabling the TPM device in the system
 | 
						|
can reduce memory usage in the GRUB. It is useful in scenarios where
 | 
						|
high memory utilization is a concern and measurements of loaded
 | 
						|
artifacts are not necessary.
 | 
						|
 | 
						|
Signed-off-by: Michael Chang <mchang@suse.com>
 | 
						|
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
 | 
						|
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
 | 
						|
(cherry picked from commit 30708dfe3bebd62a5487437554da8a24253f519f)
 | 
						|
---
 | 
						|
 grub-core/commands/efi/tpm.c          | 37 +++++++++++++++++++++++++++++++++++
 | 
						|
 grub-core/commands/ieee1275/ibmvtpm.c | 20 +++++++++----------
 | 
						|
 grub-core/commands/tpm.c              | 10 ++++++++++
 | 
						|
 include/grub/tpm.h                    |  1 +
 | 
						|
 4 files changed, 58 insertions(+), 10 deletions(-)
 | 
						|
 | 
						|
diff --git a/grub-core/commands/efi/tpm.c b/grub-core/commands/efi/tpm.c
 | 
						|
index ae09c1bf8bc5..e1f343fea3ff 100644
 | 
						|
--- a/grub-core/commands/efi/tpm.c
 | 
						|
+++ b/grub-core/commands/efi/tpm.c
 | 
						|
@@ -287,3 +287,40 @@ grub_tpm_measure (unsigned char *buf, grub_size_t size, grub_uint8_t pcr,
 | 
						|
   else
 | 
						|
     return grub_tpm2_log_event (tpm_handle, buf, size, pcr, description);
 | 
						|
 }
 | 
						|
+
 | 
						|
+int
 | 
						|
+grub_tpm_present (void)
 | 
						|
+{
 | 
						|
+  grub_efi_handle_t tpm_handle;
 | 
						|
+  grub_efi_uint8_t protocol_version;
 | 
						|
+
 | 
						|
+  if (!grub_tpm_handle_find (&tpm_handle, &protocol_version))
 | 
						|
+    return 0;
 | 
						|
+
 | 
						|
+  if (protocol_version == 1)
 | 
						|
+    {
 | 
						|
+      grub_efi_tpm_protocol_t *tpm;
 | 
						|
+
 | 
						|
+      tpm = grub_efi_open_protocol (tpm_handle, &tpm_guid,
 | 
						|
+				    GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
 | 
						|
+      if (!tpm)
 | 
						|
+	{
 | 
						|
+	  grub_dprintf ("tpm", "Cannot open TPM protocol\n");
 | 
						|
+	  return 0;
 | 
						|
+	}
 | 
						|
+      return grub_tpm1_present (tpm);
 | 
						|
+    }
 | 
						|
+  else
 | 
						|
+    {
 | 
						|
+      grub_efi_tpm2_protocol_t *tpm;
 | 
						|
+
 | 
						|
+      tpm = grub_efi_open_protocol (tpm_handle, &tpm2_guid,
 | 
						|
+				    GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
 | 
						|
+      if (!tpm)
 | 
						|
+	{
 | 
						|
+	  grub_dprintf ("tpm", "Cannot open TPM protocol\n");
 | 
						|
+	  return 0;
 | 
						|
+	}
 | 
						|
+      return grub_tpm2_present (tpm);
 | 
						|
+    }
 | 
						|
+}
 | 
						|
diff --git a/grub-core/commands/ieee1275/ibmvtpm.c b/grub-core/commands/ieee1275/ibmvtpm.c
 | 
						|
index 239942d27e55..a6fee5c516dc 100644
 | 
						|
--- a/grub-core/commands/ieee1275/ibmvtpm.c
 | 
						|
+++ b/grub-core/commands/ieee1275/ibmvtpm.c
 | 
						|
@@ -135,16 +135,6 @@ grub_err_t
 | 
						|
 grub_tpm_measure (unsigned char *buf, grub_size_t size, grub_uint8_t pcr,
 | 
						|
 		  const char *description)
 | 
						|
 {
 | 
						|
-  /*
 | 
						|
-   * Call tpm_init() 'late' rather than from GRUB_MOD_INIT() so that device nodes
 | 
						|
-   * can be found.
 | 
						|
-   */
 | 
						|
-  grub_err_t err = tpm_init ();
 | 
						|
-
 | 
						|
-  /* Absence of a TPM isn't a failure. */
 | 
						|
-  if (err != GRUB_ERR_NONE)
 | 
						|
-    return GRUB_ERR_NONE;
 | 
						|
-
 | 
						|
   grub_dprintf ("tpm", "log_event, pcr = %d, size = 0x%" PRIxGRUB_SIZE ", %s\n",
 | 
						|
 		pcr, size, description);
 | 
						|
 
 | 
						|
@@ -153,3 +143,13 @@ grub_tpm_measure (unsigned char *buf, grub_size_t size, grub_uint8_t pcr,
 | 
						|
 
 | 
						|
   return GRUB_ERR_NONE;
 | 
						|
 }
 | 
						|
+
 | 
						|
+int
 | 
						|
+grub_tpm_present (void)
 | 
						|
+{
 | 
						|
+  /*
 | 
						|
+   * Call tpm_init() "late" rather than from GRUB_MOD_INIT() so that device nodes
 | 
						|
+   * can be found.
 | 
						|
+   */
 | 
						|
+  return tpm_init() == GRUB_ERR_NONE;
 | 
						|
+}
 | 
						|
diff --git a/grub-core/commands/tpm.c b/grub-core/commands/tpm.c
 | 
						|
index e287d042e6b4..5839053d3df8 100644
 | 
						|
--- a/grub-core/commands/tpm.c
 | 
						|
+++ b/grub-core/commands/tpm.c
 | 
						|
@@ -86,10 +86,20 @@ struct grub_file_verifier grub_tpm_verifier = {
 | 
						|
 
 | 
						|
 GRUB_MOD_INIT (tpm)
 | 
						|
 {
 | 
						|
+  /*
 | 
						|
+   * Even though this now calls ibmvtpm's grub_tpm_present() from GRUB_MOD_INIT(),
 | 
						|
+   * it does seem to call it late enough in the initialization sequence so
 | 
						|
+   * that whatever discovered "device nodes" before this GRUB_MOD_INIT() is
 | 
						|
+   * called, enables the ibmvtpm driver to see the device nodes.
 | 
						|
+   */
 | 
						|
+  if (!grub_tpm_present())
 | 
						|
+    return;
 | 
						|
   grub_verifier_register (&grub_tpm_verifier);
 | 
						|
 }
 | 
						|
 
 | 
						|
 GRUB_MOD_FINI (tpm)
 | 
						|
 {
 | 
						|
+  if (!grub_tpm_present())
 | 
						|
+    return;
 | 
						|
   grub_verifier_unregister (&grub_tpm_verifier);
 | 
						|
 }
 | 
						|
diff --git a/include/grub/tpm.h b/include/grub/tpm.h
 | 
						|
index 5c285cbc5256..c19fcbd0a60d 100644
 | 
						|
--- a/include/grub/tpm.h
 | 
						|
+++ b/include/grub/tpm.h
 | 
						|
@@ -36,4 +36,5 @@
 | 
						|
 
 | 
						|
 grub_err_t grub_tpm_measure (unsigned char *buf, grub_size_t size,
 | 
						|
 			     grub_uint8_t pcr, const char *description);
 | 
						|
+int grub_tpm_present (void);
 | 
						|
 #endif
 |