File fix_grub_bls_entry.patch of Package pcr-oracle

From b0c4c5fbdcc89b44cee2300c5a12cb5e8de0e446 Mon Sep 17 00:00:00 2001
From: Alberto Planas <aplanas@suse.com>
Date: Wed, 13 Mar 2024 22:57:17 +0100
Subject: [PATCH] GRUB with BLS measure boot entries

This includes the boot entry file, the kernel and the initrd specified
in the entry file.

Signed-off-by: Alberto Planas <aplanas@suse.com>
---
 src/eventlog.c | 21 +++++++++++++++++++--
 src/eventlog.h |  1 +
 src/oracle.c   | 12 +++++++++---
 src/sd-boot.c  | 28 ++++++++++++++++++++++++----
 src/sd-boot.h  |  2 ++
 src/uapi.h     |  3 ++-
 6 files changed, 57 insertions(+), 10 deletions(-)

diff --git a/src/eventlog.c b/src/eventlog.c
index 3574a4d..db18f41 100644
--- a/src/eventlog.c
+++ b/src/eventlog.c
@@ -33,6 +33,7 @@
 #include "digest.h"
 #include "util.h"
 #include "uapi.h"
+#include "sd-boot.h"
 
 #define TPM_EVENT_LOG_MAX_ALGOS		64
 
@@ -582,8 +583,24 @@ __tpm_event_grub_file_rehash(const tpm_event_t *ev, const tpm_parsed_event_t *pa
 		debug("  assuming the file resides on system partition\n");
 		md = runtime_digest_rootfs_file(ctx->algo, evspec->path);
 	} else {
-		debug("  assuming the file resides on EFI boot partition\n");
-		md = runtime_digest_efi_file(ctx->algo, evspec->path);
+		if (sdb_is_boot_entry(evspec->path) && ctx->boot_entry_path) {
+			debug("  getting different boot entry file from EFI boot partition: %s\n",
+			      ctx->boot_entry_path);
+			md = runtime_digest_rootfs_file(ctx->algo, ctx->boot_entry_path);
+		} else
+		if (sdb_is_kernel(evspec->path) && ctx->boot_entry) {
+			debug("  getting different kernel from EFI boot partition: %s\n",
+			      ctx->boot_entry->image_path);
+			md = runtime_digest_efi_file(ctx->algo, ctx->boot_entry->image_path);
+		} else
+		if (sdb_is_initrd(evspec->path) && ctx->boot_entry) {
+			debug("  getting different initrd from EFI boot partition: %s\n",
+			      ctx->boot_entry->initrd_path);
+			md = runtime_digest_efi_file(ctx->algo, ctx->boot_entry->initrd_path);
+		} else {
+			debug("  assuming the file resides on EFI boot partition\n");
+			md = runtime_digest_efi_file(ctx->algo, evspec->path);
+		}
 	}
 
 	return md;
diff --git a/src/eventlog.h b/src/eventlog.h
index 8af5eb0..d142744 100644
--- a/src/eventlog.h
+++ b/src/eventlog.h
@@ -202,6 +202,7 @@ typedef struct tpm_event_log_rehash_ctx {
 	const pecoff_image_info_t *next_stage_img;
 
 	/* This get set when the user specifies --next-kernel */
+	char *			boot_entry_path;
 	uapi_boot_entry_t *	boot_entry;
 } tpm_event_log_rehash_ctx_t;
 
diff --git a/src/oracle.c b/src/oracle.c
index 0afd910..ac48823 100644
--- a/src/oracle.c
+++ b/src/oracle.c
@@ -23,6 +23,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
+#include <limits.h>
 
 #include "oracle.h"
 #include "util.h"
@@ -653,6 +654,7 @@ predictor_update_eventlog(struct predictor *pred)
 	tpm_event_log_rehash_ctx_t rehash_ctx;
 	tpm_event_t *ev, *stop_event = NULL;
 	bool okay = true;
+	char boot_entry_path[PATH_MAX];
 
 	predictor_pre_scan_eventlog(pred, &stop_event);
 
@@ -663,9 +665,13 @@ predictor_update_eventlog(struct predictor *pred)
 	 * systemd ID of the next kernel entry to be booted.
 	 * FIXME: we should probably hide this behind a target_platform function.
 	 */
-	if (pred->boot_entry_id != NULL
-	 && !(rehash_ctx.boot_entry = sdb_identify_boot_entry(pred->boot_entry_id)))
-		fatal("unable to identify next kernel \"%s\"\n", pred->boot_entry_id);
+	if (pred->boot_entry_id != NULL) {
+		snprintf(boot_entry_path, sizeof(boot_entry_path),
+			 "%s/%s", UAPI_BOOT_DIRECTORY, pred->boot_entry_id);
+		assign_string(&rehash_ctx.boot_entry_path, boot_entry_path);
+		if (!(rehash_ctx.boot_entry = sdb_identify_boot_entry(pred->boot_entry_id)))
+			fatal("unable to identify next kernel \"%s\"\n", pred->boot_entry_id);
+	}
 
 	for (ev = pred->event_log; ev; ev = ev->next) {
 		tpm_evdigest_t *pcr;
diff --git a/src/sd-boot.c b/src/sd-boot.c
index ede2569..a16f814 100644
--- a/src/sd-boot.c
+++ b/src/sd-boot.c
@@ -130,10 +130,9 @@ get_valid_kernel_entry_tokens(void)
 /*
  * This should probably use UAPI boot entry logic as well
  */
-bool
-sdb_is_kernel(const char *application)
+static bool
+is_valid_entry_token(const char *application, const char *prefix)
 {
-	static const char prefix[] = "linux-";
 	const uapi_kernel_entry_tokens_t *match;
 	char *path_copy;
 	int found = 0;
@@ -151,7 +150,7 @@ sdb_is_kernel(const char *application)
 
 			if (!strcmp(ptr, token))
 				found |= 1;
-			else if (!strncmp(ptr, prefix, sizeof(prefix) - 1))
+			else if (!strncmp(ptr, prefix, strlen(prefix)))
 				found |= 2;
 		}
 	}
@@ -160,6 +159,27 @@ sdb_is_kernel(const char *application)
 	return (found == 3);
 }
 
+bool
+sdb_is_kernel(const char *application)
+{
+	return is_valid_entry_token(application, "linux-");
+}
+
+bool
+sdb_is_initrd(const char *application)
+{
+	return is_valid_entry_token(application, "initrd-");
+}
+
+bool
+sdb_is_boot_entry(const char *application)
+{
+	if (!application)
+		return false;
+
+	return !strncmp(application, UAPI_BOOT_DIRECTORY_EFI, sizeof(UAPI_BOOT_DIRECTORY_EFI) - 1);
+}
+
 /*
  * Identify the next kernel and initrd given an ID
  */
diff --git a/src/sd-boot.h b/src/sd-boot.h
index 0472320..ceab13d 100644
--- a/src/sd-boot.h
+++ b/src/sd-boot.h
@@ -43,7 +43,9 @@ typedef struct sdb_entry_list {
 } sdb_entry_list_t;
 
 extern uapi_boot_entry_t *	sdb_identify_boot_entry(const char *id);
+extern bool			sdb_is_boot_entry(const char *application);
 extern bool			sdb_is_kernel(const char *application);
+extern bool			sdb_is_initrd(const char *application);
 
 /* This will have to update the systemd json file, and add a new entry. */
 extern bool			sdb_policy_file_add_entry(const char *filename,
diff --git a/src/uapi.h b/src/uapi.h
index 96ca7ed..8bcb94f 100644
--- a/src/uapi.h
+++ b/src/uapi.h
@@ -41,7 +41,8 @@ typedef struct uapi_kernel_entry_tokens {
 	char *		entry_token[UAPI_MAX_ENTRY_TOKENS];
 } uapi_kernel_entry_tokens_t;
 
-#define UAPI_BOOT_DIRECTORY	"/boot/efi/loader/entries"
+#define UAPI_BOOT_DIRECTORY_EFI	"/loader/entries"
+#define UAPI_BOOT_DIRECTORY	"/boot/efi" UAPI_BOOT_DIRECTORY_EFI
 
 extern uapi_boot_entry_t *	uapi_get_boot_entry(const char *id);
 extern uapi_boot_entry_t *	uapi_find_boot_entry(const uapi_kernel_entry_tokens_t *match, const char *machine_id);
openSUSE Build Service is sponsored by