From 4eb2926a474ed3ac95e782921c1ef81030668ba8720356565674f15be205f57c Mon Sep 17 00:00:00 2001 From: Alberto Planas Dominguez Date: Mon, 25 Mar 2024 20:42:46 +0000 Subject: [PATCH] Accepting request 1161555 from home:aplanas:branches:Base:System - Add fix_grub_bls_cmdline.patch to include the measurements of the cmdline and the linux and initrd grub commands OBS-URL: https://build.opensuse.org/request/show/1161555 OBS-URL: https://build.opensuse.org/package/show/Base:System/pcr-oracle?expand=0&rev=30 --- fix_grub_bls_cmdline.patch | 335 +++++++++++++++++++++++++++++++++++++ pcr-oracle.changes | 6 + pcr-oracle.spec | 2 + 3 files changed, 343 insertions(+) create mode 100644 fix_grub_bls_cmdline.patch diff --git a/fix_grub_bls_cmdline.patch b/fix_grub_bls_cmdline.patch new file mode 100644 index 0000000..2996eb9 --- /dev/null +++ b/fix_grub_bls_cmdline.patch @@ -0,0 +1,335 @@ +From fca4a51b9aac712b3adc5b6b187cc31a8391bcf6 Mon Sep 17 00:00:00 2001 +From: Alberto Planas +Date: Fri, 22 Mar 2024 22:44:41 +0100 +Subject: [PATCH] GRUB: predict cmdline, linux and initrd lines + +Signed-off-by: Alberto Planas +--- + src/eventlog.c | 195 ++++++++++++++++++++++++++++++++++++++----------- + src/eventlog.h | 26 ++++--- + 2 files changed, 169 insertions(+), 52 deletions(-) + +diff --git a/src/eventlog.c b/src/eventlog.c +index db18f41..727f6a9 100644 +--- a/src/eventlog.c ++++ b/src/eventlog.c +@@ -549,14 +549,66 @@ tpm_event_decode_uuid(const unsigned char *data) + return uuid; + } + ++/* ++ * For files residing on the EFI partition, grub usually formats these as ++ * (hdX,gptY)/EFI/BOOT/some.file ++ * Once it has determined the final root device, the device part will be ++ * omitted (eg for kernel and initrd). ++ */ ++static bool ++__grub_file_parse(grub_file_t *grub_file, const char *value) ++{ ++ if (value[0] == '/') { ++ grub_file->device = NULL; ++ grub_file->path = strdup(value); ++ } else if (value[0] == '(') { ++ char *copy = strdup(value); ++ char *path; ++ ++ if ((path = strchr(copy, ')')) == NULL) { ++ free(copy); ++ return false; ++ } ++ ++ *path++ = '\0'; ++ ++ grub_file->device = strdup(copy + 1); ++ grub_file->path = strdup(path); ++ free(copy); ++ } else { ++ return false; ++ } ++ ++ return true; ++} ++ ++static const char * ++__grub_file_join(grub_file_t grub_file) ++{ ++ static char path[PATH_MAX]; ++ ++ if (grub_file.device == NULL) ++ snprintf(path, sizeof(path), "%s", grub_file.path); ++ else ++ snprintf(path, sizeof(path), "(%s)%s", grub_file.device, grub_file.path); ++ ++ return path; ++} ++ ++static void ++__grub_file_destroy(grub_file_t *grub_file) ++{ ++ drop_string(&grub_file->device); ++ drop_string(&grub_file->path); ++} ++ + /* + * Handle IPL events, which grub2 and sd-boot uses to hide its stuff in + */ + static void + __tpm_event_grub_file_destroy(tpm_parsed_event_t *parsed) + { +- drop_string(&parsed->grub_file.device); +- drop_string(&parsed->grub_file.path); ++ __grub_file_destroy(&parsed->grub_file); + } + + const char * +@@ -564,10 +616,7 @@ __tpm_event_grub_file_describe(const tpm_parsed_event_t *parsed) + { + static char buffer[1024]; + +- if (parsed->grub_file.device == NULL) +- snprintf(buffer, sizeof(buffer), "grub2 file load from %s", parsed->grub_file.path); +- else +- snprintf(buffer, sizeof(buffer), "grub2 file load from (%s)%s", parsed->grub_file.device, parsed->grub_file.path); ++ snprintf(buffer, sizeof(buffer), "grub2 file load from %s", __grub_file_join(parsed->grub_file)); + return buffer; + } + +@@ -575,7 +624,7 @@ __tpm_event_grub_file_describe(const tpm_parsed_event_t *parsed) + static const tpm_evdigest_t * + __tpm_event_grub_file_rehash(const tpm_event_t *ev, const tpm_parsed_event_t *parsed, tpm_event_log_rehash_ctx_t *ctx) + { +- const struct grub_file_event *evspec = &parsed->grub_file; ++ const grub_file_event *evspec = &parsed->grub_file; + const tpm_evdigest_t *md = NULL; + + debug(" re-hashing %s\n", __tpm_event_grub_file_describe(parsed)); +@@ -606,35 +655,11 @@ __tpm_event_grub_file_rehash(const tpm_event_t *ev, const tpm_parsed_event_t *pa + return md; + } + +-/* +- * For files residing on the EFI partition, grub usually formats these as +- * (hdX,gptY)/EFI/BOOT/some.file +- * Once it has determined the final root device, the device part will be +- * omitted (eg for kernel and initrd). +- */ + static bool + __tpm_event_grub_file_event_parse(tpm_event_t *ev, tpm_parsed_event_t *parsed, const char *value) + { +- if (value[0] == '/') { +- parsed->grub_file.device = NULL; +- parsed->grub_file.path = strdup(value); +- } else if (value[0] == '(') { +- char *copy = strdup(value); +- char *path; +- +- if ((path = strchr(copy, ')')) == NULL) { +- free(copy); +- return false; +- } +- +- *path++ = '\0'; +- +- parsed->grub_file.device = strdup(copy + 1); +- parsed->grub_file.path = strdup(path); +- free(copy); +- } else { ++ if (!__grub_file_parse(&parsed->grub_file, value)) + return false; +- } + + parsed->event_subtype = GRUB_EVENT_FILE; + parsed->destroy = __tpm_event_grub_file_destroy; +@@ -658,21 +683,87 @@ static const char * + __tpm_event_grub_command_describe(const tpm_parsed_event_t *parsed) + { + static char buffer[128]; ++ static char *topic = NULL; ++ ++ switch (parsed->event_subtype) { ++ case GRUB_EVENT_COMMAND: ++ topic = "grub2 command"; ++ break; ++ case GRUB_EVENT_COMMAND_LINUX: ++ topic = "grub2 linux command"; ++ break; ++ case GRUB_EVENT_COMMAND_INITRD: ++ topic = "grub2 initrd command"; ++ break; ++ case GRUB_EVENT_KERNEL_CMDLINE: ++ topic = "grub2 kernel cmdline"; ++ break; ++ } ++ ++ snprintf(buffer, sizeof(buffer), "%s \"%s\"", topic, parsed->grub_command.string); + +- if (parsed->event_subtype == GRUB_EVENT_COMMAND) +- snprintf(buffer, sizeof(buffer), "grub2 command \"%s\"", parsed->grub_command.string); +- else +- snprintf(buffer, sizeof(buffer), "grub2 kernel cmdline \"%s\"", parsed->grub_command.string); + return buffer; + } + + static const tpm_evdigest_t * + __tpm_event_grub_command_rehash(const tpm_event_t *ev, const tpm_parsed_event_t *parsed, tpm_event_log_rehash_ctx_t *ctx) + { +- if (parsed->grub_command.string == NULL) +- return NULL; ++ char *str = NULL; ++ size_t sz = 0; ++ const tpm_evdigest_t *digest = NULL; ++ grub_file_t file; ++ ++ switch (parsed->event_subtype) { ++ case GRUB_EVENT_COMMAND: ++ str = strdup(parsed->grub_command.string); ++ break; ++ case GRUB_EVENT_COMMAND_LINUX: ++ if (ctx->boot_entry && parsed->grub_command.file.path) { ++ file = (grub_file_t) { ++ .device = parsed->grub_command.file.device, ++ .path = ctx->boot_entry->image_path, ++ }; ++ sz = snprintf(NULL, 0, "linux %s %s", __grub_file_join(file), ctx->boot_entry->options); ++ str = malloc(sz + 1); ++ snprintf(str, sz + 1, "linux %s %s", __grub_file_join(file), ctx->boot_entry->options); ++ debug("Hashed linux command: %s\n", str); ++ } else ++ str = strdup(parsed->grub_command.string); ++ break; ++ case GRUB_EVENT_COMMAND_INITRD: ++ if (ctx->boot_entry && parsed->grub_command.file.path) { ++ file = (grub_file_t) { ++ .device = parsed->grub_command.file.device, ++ .path = ctx->boot_entry->initrd_path, ++ }; ++ sz = snprintf(NULL, 0, "initrd %s", __grub_file_join(file)); ++ str = malloc(sz + 1); ++ snprintf(str, sz + 1, "initrd %s", __grub_file_join(file)); ++ debug("Hashed initrd command: %s\n", str); ++ } else ++ str = strdup(parsed->grub_command.string); ++ break; ++ case GRUB_EVENT_KERNEL_CMDLINE: ++ if (ctx->boot_entry && parsed->grub_command.file.path) { ++ file = (grub_file_t) { ++ .device = parsed->grub_command.file.device, ++ .path = ctx->boot_entry->image_path, ++ }; ++ sz = snprintf(NULL, 0, "%s %s", __grub_file_join(file), ctx->boot_entry->options); ++ str = malloc(sz + 1); ++ snprintf(str, sz + 1, "%s %s", __grub_file_join(file), ctx->boot_entry->options); ++ debug("Hashed kernel cmdline: %s\n", str); ++ } else ++ str = strdup(parsed->grub_command.string); ++ break; ++ } ++ ++ if (str) { ++ digest = digest_compute(ctx->algo, str, strlen(str)); ++ free(str); ++ } + +- return digest_compute(ctx->algo, parsed->grub_command.string, strlen(parsed->grub_command.string)); ++ return digest; + } + + /* +@@ -703,15 +794,29 @@ __tpm_event_grub_command_event_parse(tpm_event_t *ev, tpm_parsed_event_t *parsed + keyword = copy; + arg = copy + wordlen; + ++ if (!strcmp(keyword, "grub_cmd") && !strncmp(arg, "linux", strlen("linux"))) { ++ for (wordlen = 0; (cc = arg[wordlen]) && (cc != ' '); ++wordlen) ++ ; ++ if (arg[wordlen] == ' ' && !__grub_file_parse(&parsed->grub_command.file, arg + wordlen + 1)) ++ goto failed; ++ parsed->event_subtype = GRUB_EVENT_COMMAND_LINUX; ++ } else ++ if (!strcmp(keyword, "grub_cmd") && !strncmp(arg, "initrd", strlen("initrd"))) { ++ for (wordlen = 0; (cc = arg[wordlen]) && (cc != ' '); ++wordlen) ++ ; ++ if (arg[wordlen] == ' ' && !__grub_file_parse(&parsed->grub_command.file, arg + wordlen + 1)) ++ goto failed; ++ parsed->event_subtype = GRUB_EVENT_COMMAND_INITRD; ++ } else + if (!strcmp(keyword, "grub_cmd")) { + parsed->event_subtype = GRUB_EVENT_COMMAND; + } else + if (!strcmp(keyword, "kernel_cmdline")) { ++ if (!__grub_file_parse(&parsed->grub_command.file, arg)) ++ goto failed; + parsed->event_subtype = GRUB_EVENT_KERNEL_CMDLINE; +- } else { +- free(copy); +- return false; +- } ++ } else ++ goto failed; + + parsed->grub_command.string = strdup(arg); + for (argc = 0, s = strtok(arg, " \t"); s && argc < GRUB_COMMAND_ARGV_MAX - 1; s = strtok(NULL, " \t")) { +@@ -725,6 +830,10 @@ __tpm_event_grub_command_event_parse(tpm_event_t *ev, tpm_parsed_event_t *parsed + + free(copy); + return true; ++ ++failed: ++ free(copy); ++ return false; + } + + static void +diff --git a/src/eventlog.h b/src/eventlog.h +index d142744..6a8c3a4 100644 +--- a/src/eventlog.h ++++ b/src/eventlog.h +@@ -89,10 +89,12 @@ enum { + enum { + /* IPL subtypes for grub */ + GRUB_EVENT_COMMAND = 0x0001, +- GRUB_EVENT_FILE = 0x0002, +- GRUB_EVENT_KERNEL_CMDLINE = 0x0003, +- SHIM_EVENT_VARIABLE = 0x0004, +- SYSTEMD_EVENT_VARIABLE = 0x0005, ++ GRUB_EVENT_COMMAND_LINUX = 0x0002, ++ GRUB_EVENT_COMMAND_INITRD = 0x0003, ++ GRUB_EVENT_FILE = 0x0004, ++ GRUB_EVENT_KERNEL_CMDLINE = 0x0005, ++ SHIM_EVENT_VARIABLE = 0x0006, ++ SYSTEMD_EVENT_VARIABLE = 0x0007, + }; + + enum { +@@ -208,6 +210,13 @@ typedef struct tpm_event_log_rehash_ctx { + + #define GRUB_COMMAND_ARGV_MAX 32 + ++typedef struct grub_file { ++ char * device; ++ char * path; ++} grub_file_t; ++ ++typedef grub_file_t grub_file_event; ++ + /* + * Parsed event types + */ +@@ -247,13 +256,12 @@ typedef struct tpm_parsed_event { + /* for GRUB_COMMAND, GRUB_KERNEL_CMDLINE */ + struct grub_command_event { + char * string; +- char * argv[GRUB_COMMAND_ARGV_MAX]; ++ char * argv[GRUB_COMMAND_ARGV_MAX]; ++ grub_file_t file; + } grub_command; + +- struct grub_file_event { +- char * device; +- char * path; +- } grub_file; ++ /* for GRUB_FILE */ ++ grub_file_event grub_file; + + struct shim_event { + char * string; diff --git a/pcr-oracle.changes b/pcr-oracle.changes index fb2e148..5a57245 100644 --- a/pcr-oracle.changes +++ b/pcr-oracle.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Mon Mar 25 20:16:53 UTC 2024 - Alberto Planas Dominguez + +- Add fix_grub_bls_cmdline.patch to include the measurements of the + cmdline and the linux and initrd grub commands + ------------------------------------------------------------------- Thu Mar 14 10:33:23 UTC 2024 - Alberto Planas Dominguez diff --git a/pcr-oracle.spec b/pcr-oracle.spec index 73912aa..ec4af33 100644 --- a/pcr-oracle.spec +++ b/pcr-oracle.spec @@ -32,6 +32,8 @@ Patch0: fix_efi_measure_and_shim.patch Patch1: fix_loader_conf.patch # PATCH-FIX-UPSTREAM fix_grub_bls_entry.patch gh#okirch/pcr-oracle!52 Patch2: fix_grub_bls_entry.patch +# PATCH-FIX-UPSTREAM fix_grub_bls_cmdline.patch gh#okirch/pcr-oracle!52 (cont) +Patch3: fix_grub_bls_cmdline.patch BuildRequires: libopenssl-devel >= 0.9.8 BuildRequires: tpm2-0-tss-devel >= 2.4.0 Requires: libtss2-tcti-device0