diff options
author | Daan De Meyer <daan.j.demeyer@gmail.com> | 2024-10-04 10:22:37 +0200 |
---|---|---|
committer | Daan De Meyer <daan.j.demeyer@gmail.com> | 2024-10-20 13:22:54 +0200 |
commit | 0005411352f9bda0d9887c37b9e75a2bce6c1133 (patch) | |
tree | 571347a53dc85ddb86783991c606941dd1a57b15 /src/boot/measure.c | |
parent | TEST-55-OOMD: workaround for kernel regression in 6.12-rcX (diff) | |
download | systemd-0005411352f9bda0d9887c37b9e75a2bce6c1133.tar.xz systemd-0005411352f9bda0d9887c37b9e75a2bce6c1133.zip |
measure: Take SizeOfImage into account as well for .linux section
Same change as https://github.com/systemd/systemd/pull/34583 but for
systemd-measure. Otherwise we end up with PCR policy digest mismatches
as systemd-stub will measure the full virtual size of the kernel image
after it has been loaded while systemd-measure will disregard the extra
size introduced by SizeOfImage.
While ideally the stub would only measure the data that's actually on
disk and not the uninitialized data introduced by VirtualSize > SizeOfRawData,
we want newer systemd-measure to work with older stubs so we have to fix
systemd-measure and can't fix this in the stub.
Diffstat (limited to '')
-rw-r--r-- | src/boot/measure.c | 33 |
1 files changed, 33 insertions, 0 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 */ |