]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-boot: measure kernel cmdline into PCR 12 rather than 8
authorLennart Poettering <lennart@poettering.net>
Wed, 16 Mar 2022 09:51:03 +0000 (10:51 +0100)
committerLennart Poettering <lennart@poettering.net>
Wed, 16 Mar 2022 16:44:32 +0000 (17:44 +0100)
Apparently Grub is measuring all kinds of garbage into PCR 8. Since people
apparently chainload sd-boot from grub, let's thus stay away from PCR 8,
and use PCR 12 instead for the kernel command line.

As discussed here: #22635

Fixes: #22635
meson_options.txt
src/boot/efi/cpio.c
src/boot/efi/cpio.h
src/boot/efi/measure.c
src/boot/efi/measure.h
src/boot/efi/meson.build
src/boot/efi/stub.c
src/boot/efi/util.h

index 5d635748d58cc8eb72d74a718dd183cd237898bf..284109cadf4f3a11330c621d9811e770f1da6b43 100644 (file)
@@ -426,6 +426,8 @@ option('efi-libdir', type : 'string',
        description : 'path to the EFI lib directory')
 option('efi-includedir', type : 'string', value : '/usr/include/efi',
        description : 'path to the EFI header directory')
+option('efi-tpm-pcr-compat', type : 'boolean', value : 'false',
+       description : 'Measure kernel command line also into TPM PCR 8 (in addition to 12)')
 option('sbat-distro', type : 'string', value : 'auto',
        description : 'SBAT distribution ID, e.g. fedora, or auto for autodetection')
 option('sbat-distro-generation', type : 'integer', value : 1,
index a4da4a97fecfeb51b296dd4c1b7fb1629b580f5a..14957130be00bc9ba8bfec918b6610f906c53138 100644 (file)
@@ -311,7 +311,8 @@ EFI_STATUS pack_cpio(
                 const CHAR8 *target_dir_prefix,
                 UINT32 dir_mode,
                 UINT32 access_mode,
-                UINT32 tpm_pcr,
+                const UINT32 tpm_pcr[],
+                UINTN n_tpm_pcr,
                 const CHAR16 *tpm_description,
                 void **ret_buffer,
                 UINTN *ret_buffer_size) {
@@ -328,6 +329,7 @@ EFI_STATUS pack_cpio(
 
         assert(loaded_image);
         assert(target_dir_prefix);
+        assert(tpm_pcr || n_tpm_pcr == 0);
         assert(ret_buffer);
         assert(ret_buffer_size);
 
@@ -449,13 +451,15 @@ EFI_STATUS pack_cpio(
         if (EFI_ERROR(err))
                 return log_error_status_stall(err, L"Failed to pack cpio trailer: %r");
 
-        err = tpm_log_event(
-                        tpm_pcr,
-                        POINTER_TO_PHYSICAL_ADDRESS(buffer),
-                        buffer_size,
-                        tpm_description);
-        if (EFI_ERROR(err))
-                log_error_stall(L"Unable to add initrd TPM measurement for PCR %u (%s), ignoring: %r", tpm_pcr, tpm_description, err);
+        for (UINTN i = 0; i < n_tpm_pcr; i++) {
+                err = tpm_log_event(
+                                tpm_pcr[i],
+                                POINTER_TO_PHYSICAL_ADDRESS(buffer),
+                                buffer_size,
+                                tpm_description);
+                if (EFI_ERROR(err))
+                        log_error_stall(L"Unable to add initrd TPM measurement for PCR %u (%s), ignoring: %r", tpm_pcr[i], tpm_description, err);
+        }
 
         *ret_buffer = TAKE_PTR(buffer);
         *ret_buffer_size = buffer_size;
index 93ee4c431067e58dbd31a7a474bebf99089e6270..5f6698fd128f4fd0d1e7ec8f663fbdfac8ee7252 100644 (file)
@@ -10,7 +10,8 @@ EFI_STATUS pack_cpio(
                 const CHAR8 *target_dir_prefix,
                 UINT32 dir_mode,
                 UINT32 access_mode,
-                UINT32 tpm_pcr,
+                const UINT32 tpm_pcr[],
+                UINTN n_tpm_pcr,
                 const CHAR16 *tpm_description,
                 void **ret_buffer,
                 UINTN *ret_buffer_size);
index 5c082b537c75867d527b8869a9c1f3aabcaa8b53..da4fd18ea8c28e45ef1451c044b4370d07f20bfb 100644 (file)
@@ -145,6 +145,10 @@ EFI_STATUS tpm_log_event(UINT32 pcrindex, EFI_PHYSICAL_ADDRESS buffer, UINTN buf
 
         assert(description);
 
+        /* PCR disabled */
+        if (pcrindex == UINT32_MAX)
+                return EFI_SUCCESS;
+
         tpm2 = tcg2_interface_check();
         if (tpm2)
                 return tpm2_measure_to_pcr_and_event_log(tpm2, pcrindex, buffer, buffer_size, description);
@@ -162,11 +166,15 @@ EFI_STATUS tpm_log_load_options(const CHAR16 *load_options) {
 
         /* Measures a load options string into the TPM2, i.e. the kernel command line */
 
-        err = tpm_log_event(TPM_PCR_INDEX_KERNEL_PARAMETERS,
-                            POINTER_TO_PHYSICAL_ADDRESS(load_options),
-                            StrSize(load_options), load_options);
-        if (EFI_ERROR(err))
-                return log_error_status_stall(err, L"Unable to add load options (i.e. kernel command) line measurement: %r", err);
+        for (UINTN i = 0; i < 2; i++) {
+                UINT32 pcr = i == 0 ? TPM_PCR_INDEX_KERNEL_PARAMETERS : TPM_PCR_INDEX_KERNEL_PARAMETERS_COMPAT;
+
+                err = tpm_log_event(pcr,
+                                    POINTER_TO_PHYSICAL_ADDRESS(load_options),
+                                    StrSize(load_options), load_options);
+                if (EFI_ERROR(err))
+                        return log_error_status_stall(err, L"Unable to add load options (i.e. kernel command) line measurement to PCR %u: %r", pcr, err);
+        }
 
         return EFI_SUCCESS;
 }
index 33c98aaf73323a558814ef55b608a74d6f1bb797..7a817b22d8d0d5ebafe0c6a0bdeeb1a834f8ba0d 100644 (file)
@@ -3,6 +3,20 @@
 
 #include <efi.h>
 
+/* This TPM PCR is where we extend the kernel command line and any passed credentials here. */
+#define TPM_PCR_INDEX_KERNEL_PARAMETERS 12U
+
+/* We used to write the the kernel command line/credentials into PCR 8, in systemd <= 250. Let's provide for
+ * some compatibility. (Remove in 2023!) */
+#if EFI_TPM_PCR_COMPAT
+#define TPM_PCR_INDEX_KERNEL_PARAMETERS_COMPAT 8U
+#else
+#define TPM_PCR_INDEX_KERNEL_PARAMETERS_COMPAT UINT32_MAX
+#endif
+
+/* This TPM PCR is where most Linux infrastructure extends the initrd binary images into, and so do we. */
+#define TPM_PCR_INDEX_INITRD 4U
+
 #if ENABLE_TPM
 
 BOOLEAN tpm_present(void);
index f6004e47ecc0f61e663aab8c3657426fd241eaf2..ffee98bbb83e6cf0aab1caddb06ae2254a23aa26 100644 (file)
@@ -104,6 +104,7 @@ conf.set_quoted('EFI_MACHINE_TYPE_NAME', efi_arch[0])
 efi_conf = configuration_data()
 efi_conf.set_quoted('EFI_MACHINE_TYPE_NAME', efi_arch[0])
 efi_conf.set10('ENABLE_TPM', get_option('tpm'))
+efi_conf.set10('EFI_TPM_PCR_COMPAT', get_option('efi-tpm-pcr-compat'))
 
 foreach ctype : ['color-normal', 'color-entry', 'color-highlight', 'color-edit']
         c = get_option('efi-' + ctype).split(',')
index 22554a4860443d4b66f19a1875fb069cb1f4f1a9..73d06de7f11cb80e94d389bd223da73b13eb5b12 100644 (file)
@@ -234,7 +234,8 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
                          (const CHAR8*) ".extra/credentials",
                          /* dir_mode= */ 0500,
                          /* access_mode= */ 0400,
-                         /* tpm_pcr= */ TPM_PCR_INDEX_KERNEL_PARAMETERS,
+                         /* tpm_pcr= */ (UINT32[]) { TPM_PCR_INDEX_KERNEL_PARAMETERS, TPM_PCR_INDEX_KERNEL_PARAMETERS_COMPAT },
+                         /* n_tpm_pcr= */ 2,
                          L"Credentials initrd",
                          &credential_initrd,
                          &credential_initrd_size);
@@ -245,7 +246,8 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
                          (const CHAR8*) ".extra/global_credentials",
                          /* dir_mode= */ 0500,
                          /* access_mode= */ 0400,
-                         /* tpm_pcr= */ TPM_PCR_INDEX_KERNEL_PARAMETERS,
+                         /* tpm_pcr= */ (UINT32[]) { 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);
@@ -256,7 +258,8 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
                          (const CHAR8*) ".extra/sysext",
                          /* dir_mode= */ 0555,
                          /* access_mode= */ 0444,
-                         /* tpm_pcr= */ TPM_PCR_INDEX_INITRD,
+                         /* tpm_pcr= */ (UINT32[]) { TPM_PCR_INDEX_INITRD },
+                         /* n_tpm_pcr= */ 1,
                          L"System extension initrd",
                          &sysext_initrd,
                          &sysext_initrd_size);
index 33b17d04fbb78e826ebe98d4f3f11deed528c7b1..93dd2da566fc238ea15c63ea1e9d8f768363f1c4 100644 (file)
@@ -6,13 +6,6 @@
 
 #include "string-util-fundamental.h"
 
-/* This TPM PCR is where most Linux infrastructure extends the kernel command line into, and so do we. We also extend
- * any passed credentials here. */
-#define TPM_PCR_INDEX_KERNEL_PARAMETERS 8
-
-/* This TPM PCR is where most Linux infrastructure extends the initrd binary images into, and so do we. */
-#define TPM_PCR_INDEX_INITRD 4
-
 #define offsetof(type, member) __builtin_offsetof(type, member)
 
 #define UINTN_MAX (~(UINTN)0)