summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDaan De Meyer <daan.j.demeyer@gmail.com>2024-10-21 18:55:33 +0200
committerGitHub <noreply@github.com>2024-10-21 18:55:33 +0200
commite8fb0643c1bea626d5f5e880c3338f32705fd46d (patch)
treed534e34c6f6262e044d78ee2654cf1ac0a9f0d83 /src
parentmachine: rework Operation logic to reuse in varlink interface (diff)
parentRework TEST-86-MULTI-PROFILE-UKI (diff)
downloadsystemd-e8fb0643c1bea626d5f5e880c3338f32705fd46d.tar.xz
systemd-e8fb0643c1bea626d5f5e880c3338f32705fd46d.zip
Merge pull request #34628 from DaanDeMeyer/measure
Rework TEST-86-MULTI-PROFILE-UKI + associated bugfixes
Diffstat (limited to 'src')
-rw-r--r--src/boot/measure.c33
-rw-r--r--src/cryptenroll/cryptenroll-tpm2.c2
-rw-r--r--src/pcrlock/pehash.c16
3 files changed, 48 insertions, 3 deletions
diff --git a/src/boot/measure.c b/src/boot/measure.c
index 36d42147a1..f2d644ff03 100644
--- a/src/boot/measure.c
+++ b/src/boot/measure.c
@@ -16,6 +16,7 @@
#include "openssl-util.h"
#include "parse-argument.h"
#include "parse-util.h"
+#include "pe-binary.h"
#include "pretty-print.h"
#include "sha256.h"
#include "strv.h"
@@ -517,6 +518,38 @@ static int measure_kernel(PcrState *pcr_states, size_t n) {
m += sz;
}
+ if (c == UNIFIED_SECTION_LINUX) {
+ _cleanup_free_ PeHeader *pe_header = NULL;
+
+ r = pe_load_headers(fd, /*ret_dos_header=*/ NULL, &pe_header);
+ if (r < 0)
+ log_warning_errno(r, "Failed to parse kernel image file '%s', ignoring: %m", arg_sections[c]);
+ else if (m < pe_header->optional.SizeOfImage) {
+ memzero(buffer, BUFFER_SIZE);
+
+ /* Our EFI stub measures VirtualSize bytes of the .linux section into PCR 11.
+ * Notably, VirtualSize can be larger than the section's size on disk. In
+ * that case the extra space is initialized with zeros, so the stub ends up
+ * measuring a bunch of zeros. To accomodate this, we have to measure the
+ * same number of zeros here. We opt to measure extra zeros here instead of
+ * modifying the stub to only measure the number of bytes on disk as we want
+ * newer ukify + systemd-measure to work with older versions of the stub and
+ * as of 6.12 the kernel image's VirtualSize won't be larger than its size on
+ * disk anymore (see https://github.com/systemd/systemd/issues/34578#issuecomment-2382459515).
+ */
+
+ while (m < pe_header->optional.SizeOfImage) {
+ uint64_t sz = MIN(BUFFER_SIZE, pe_header->optional.SizeOfImage - m);
+
+ for (size_t i = 0; i < n; i++)
+ if (EVP_DigestUpdate(mdctx[i], buffer, sz) != 1)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to run digest.");
+
+ m += sz;
+ }
+ }
+ }
+
fd = safe_close(fd);
if (m == 0) /* We skip over empty files, the stub does so too */
diff --git a/src/cryptenroll/cryptenroll-tpm2.c b/src/cryptenroll/cryptenroll-tpm2.c
index d58194fb85..ca163ef3c2 100644
--- a/src/cryptenroll/cryptenroll-tpm2.c
+++ b/src/cryptenroll/cryptenroll-tpm2.c
@@ -78,8 +78,6 @@ static int search_policy_hash(
j++;
}
- assert(j == n_policy_hash);
-
if (match) /* Found entry with the exact same set of hashes */
return keyslot;
}
diff --git a/src/pcrlock/pehash.c b/src/pcrlock/pehash.c
index 06d1f6afc7..7e9dade1f7 100644
--- a/src/pcrlock/pehash.c
+++ b/src/pcrlock/pehash.c
@@ -216,10 +216,24 @@ int uki_hash(int fd,
if (EVP_DigestInit_ex(mdctx, md, NULL) != 1)
return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to allocate message digest.");
- r = hash_file(fd, mdctx, section->PointerToRawData, section->VirtualSize);
+ r = hash_file(fd, mdctx, section->PointerToRawData, MIN(section->VirtualSize, section->SizeOfRawData));
if (r < 0)
return r;
+ if (section->SizeOfRawData < section->VirtualSize) {
+ uint8_t zeroes[1024] = {};
+ size_t remaining = section->VirtualSize - section->SizeOfRawData;
+
+ while (remaining > 0) {
+ size_t sz = MIN(sizeof(zeroes), remaining);
+
+ if (EVP_DigestUpdate(mdctx, zeroes, sz) != 1)
+ return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Unable to hash data.");
+
+ remaining -= sz;
+ }
+ }
+
hashes[i] = malloc(hsz);
if (!hashes[i])
return log_oom_debug();