]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
efi: tell userspace where the stub measured the kernel command line/credentials into
authorLennart Poettering <lennart@poettering.net>
Tue, 26 Jul 2022 16:32:21 +0000 (18:32 +0200)
committerLennart Poettering <lennart@poettering.net>
Tue, 2 Aug 2022 08:28:49 +0000 (10:28 +0200)
This is useful for userspace to know, so that policies can be put
together safely, matching what the stub actually measured.

man/systemd-stub.xml
src/boot/efi/cpio.c
src/boot/efi/cpio.h
src/boot/efi/stub.c

index 92a20e259ed34c3814a4d8bba451b87d3761d34e..955fa6f98f49550eb88b4319aaba14cf23a8493f 100644 (file)
 
           <row>
             <entry>Credentials (synthesized initrd from companion files)</entry>
-            <entry>12 + 9</entry>
+            <entry>9 + 12</entry>
           </row>
 
           <row>
         <citerefentry><refentrytitle>bootctl</refentrytitle><manvolnum>1</manvolnum></citerefentry> to view
         this data.</para></listitem>
       </varlistentry>
+
+      <varlistentry>
+        <term><varname>StubPcrKernelParameters</varname></term>
+
+        <listitem><para>The PCR register index the kernel command line and credentials are measured into,
+        formatted as decimal ASCII string (i.e. <literal>12</literal>). This variable is set if a measurement
+        was successfully completed, and remains unset otherwise.</para></listitem>
+      </varlistentry>
     </variablelist>
 
     <para>Note that some of the variables above may also be set by the boot loader. The stub will only set
index 693b3816a49330f11892ddb6da5ba4978d15c108..0d41102d2d8c9e9ec493725a5b26d483015a2543 100644 (file)
@@ -315,7 +315,8 @@ EFI_STATUS pack_cpio(
                 UINTN n_tpm_pcr,
                 const char16_t *tpm_description,
                 void **ret_buffer,
-                UINTN *ret_buffer_size) {
+                UINTN *ret_buffer_size,
+                bool *ret_measured) {
 
         _cleanup_(file_closep) EFI_FILE *root = NULL, *extra_dir = NULL;
         UINTN dirent_size = 0, buffer_size = 0, n_items = 0, n_allocated = 0;
@@ -324,6 +325,7 @@ EFI_STATUS pack_cpio(
         _cleanup_(strv_freep) char16_t **items = NULL;
         _cleanup_free_ void *buffer = NULL;
         uint32_t inode = 1; /* inode counter, so that each item gets a new inode */
+        int measured = -1;
         EFI_STATUS err;
 
         assert(loaded_image);
@@ -432,24 +434,40 @@ EFI_STATUS pack_cpio(
                 return log_error_status_stall(err, L"Failed to pack cpio trailer: %r");
 
         for (UINTN i = 0; i < n_tpm_pcr; i++) {
+                bool m;
+
+                if (tpm_pcr[i] == UINT32_MAX) /* Disabled */
+                        continue;
+
                 err = tpm_log_event(
                                 tpm_pcr[i],
                                 POINTER_TO_PHYSICAL_ADDRESS(buffer),
                                 buffer_size,
                                 tpm_description,
-                                NULL);
-                if (err != EFI_SUCCESS)
+                                &m);
+                if (err != EFI_SUCCESS) {
                         log_error_stall(L"Unable to add initrd TPM measurement for PCR %u (%s), ignoring: %r", tpm_pcr[i], tpm_description, err);
+                        measured = false;
+                        continue;
+                }
+
+                measured = measured < 0 ? m : (measured && m);
         }
 
         *ret_buffer = TAKE_PTR(buffer);
         *ret_buffer_size = buffer_size;
 
+        if (ret_measured)
+                *ret_measured = measured;
+
         return EFI_SUCCESS;
 
 nothing:
         *ret_buffer = NULL;
         *ret_buffer_size = 0;
 
+        if (ret_measured)
+                *ret_measured = true;
+
         return EFI_SUCCESS;
 }
index e3d206d7e89c74254207488eaa5a65c4ab40e5cf..672a751825f903b9015f02f09684f50eee7b95d5 100644 (file)
@@ -2,6 +2,7 @@
 #pragma once
 
 #include <efi.h>
+#include <stdbool.h>
 #include <uchar.h>
 
 EFI_STATUS pack_cpio(
@@ -15,4 +16,5 @@ EFI_STATUS pack_cpio(
                 UINTN n_tpm_pcr,
                 const char16_t *tpm_description,
                 void **ret_buffer,
-                UINTN *ret_buffer_size);
+                UINTN *ret_buffer_size,
+                bool *ret_measured);
index 7f43678cb14001985716bc1abffedbc1939eeaf8..3673d163450550361999eddb0feadc4cb9d2d10c 100644 (file)
@@ -178,7 +178,9 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
         UINTN szs[_SECTION_MAX] = {};
         char *cmdline = NULL;
         _cleanup_free_ char *cmdline_owned = NULL;
+        int parameters_measured = -1;
         EFI_STATUS err;
+        bool m;
 
         InitializeLib(image, sys_table);
         debug_hook(L"systemd-stub");
@@ -223,34 +225,40 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
                  * duplicates what we already did in the boot menu, if that was already used. However, since
                  * we want the boot menu to support an EFI binary, and want to this stub to be usable from
                  * any boot menu, let's measure things anyway. */
-                (void) tpm_log_load_options(loaded_image->LoadOptions, NULL);
+                m = false;
+                (void) tpm_log_load_options(loaded_image->LoadOptions, &m);
+                parameters_measured = m;
         }
 
         export_variables(loaded_image);
 
-        (void) pack_cpio(loaded_image,
-                         NULL,
-                         L".cred",
-                         ".extra/credentials",
-                         /* dir_mode= */ 0500,
-                         /* access_mode= */ 0400,
-                         /* tpm_pcr= */ (uint32_t[]) { TPM_PCR_INDEX_KERNEL_PARAMETERS, TPM_PCR_INDEX_KERNEL_PARAMETERS_COMPAT },
-                         /* n_tpm_pcr= */ 2,
-                         L"Credentials initrd",
-                         &credential_initrd,
-                         &credential_initrd_size);
-
-        (void) pack_cpio(loaded_image,
-                         L"\\loader\\credentials",
-                         L".cred",
-                         ".extra/global_credentials",
-                         /* dir_mode= */ 0500,
-                         /* access_mode= */ 0400,
-                         /* tpm_pcr= */ (uint32_t[]) { TPM_PCR_INDEX_KERNEL_PARAMETERS, TPM_PCR_INDEX_KERNEL_PARAMETERS_COMPAT },
-                         /* n_tpm_pcr= */ 2,
-                         L"Global credentials initrd",
-                         &global_credential_initrd,
-                         &global_credential_initrd_size);
+        if (pack_cpio(loaded_image,
+                      NULL,
+                      L".cred",
+                      ".extra/credentials",
+                      /* dir_mode= */ 0500,
+                      /* access_mode= */ 0400,
+                      /* tpm_pcr= */ (uint32_t[]) { TPM_PCR_INDEX_KERNEL_PARAMETERS, TPM_PCR_INDEX_KERNEL_PARAMETERS_COMPAT },
+                      /* n_tpm_pcr= */ 2,
+                      L"Credentials initrd",
+                      &credential_initrd,
+                      &credential_initrd_size,
+                      &m) == EFI_SUCCESS)
+                parameters_measured = parameters_measured < 0 ? m : (parameters_measured && m);
+
+        if (pack_cpio(loaded_image,
+                      L"\\loader\\credentials",
+                      L".cred",
+                      ".extra/global_credentials",
+                      /* dir_mode= */ 0500,
+                      /* access_mode= */ 0400,
+                      /* tpm_pcr= */ (uint32_t[]) { TPM_PCR_INDEX_KERNEL_PARAMETERS, TPM_PCR_INDEX_KERNEL_PARAMETERS_COMPAT },
+                      /* n_tpm_pcr= */ 2,
+                      L"Global credentials initrd",
+                      &global_credential_initrd,
+                      &global_credential_initrd_size,
+                      &m) == EFI_SUCCESS)
+                parameters_measured = parameters_measured < 0 ? m : (parameters_measured && m);
 
         (void) pack_cpio(loaded_image,
                          NULL,
@@ -262,7 +270,11 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
                          /* n_tpm_pcr= */ 1,
                          L"System extension initrd",
                          &sysext_initrd,
-                         &sysext_initrd_size);
+                         &sysext_initrd_size,
+                         NULL);
+
+        if (parameters_measured > 0)
+                (void) efivar_set_uint_string(LOADER_GUID, L"StubPcrKernelParameters", TPM_PCR_INDEX_KERNEL_PARAMETERS, 0);
 
         linux_size = szs[SECTION_LINUX];
         linux_base = POINTER_TO_PHYSICAL_ADDRESS(loaded_image->ImageBase) + addrs[SECTION_LINUX];