pcr-oracle/boot_entry.patch
Marcus Meissner 07fa94a1ef Accepting request 1130043 from home:aplanas:branches:Base:System
- Update to 0.5.3
  - Improve documentation
  - Detect key format store via extension
  - Replace --key-format and --policy-format options with a single
    --target-platform option
  - The json file can contain multiple predictions
- Remove fix_rsa.patch as is already upstream
- Add boot_entry.patch to add new parameter to point to a new systemd
  boot entry
- Add fix_pcr_index.patch to fix the PCR index number in the JSON file

OBS-URL: https://build.opensuse.org/request/show/1130043
OBS-URL: https://build.opensuse.org/package/show/Base:System/pcr-oracle?expand=0&rev=17
2023-12-05 10:46:40 +00:00

2094 lines
61 KiB
Diff

From 0be3db467f042cc030f9a4a840854ce36a0f8317 Mon Sep 17 00:00:00 2001
From: Olaf Kirch <okir@suse.com>
Date: Mon, 27 Nov 2023 16:48:28 +0100
Subject: [PATCH 01/13] Remove obsolete pcr_policy_sign_systemd()
Signed-off-by: Olaf Kirch <okir@suse.com>
---
src/pcr-policy.c | 51 ------------------------------------------------
src/pcr.h | 3 ---
2 files changed, 54 deletions(-)
diff --git a/src/pcr-policy.c b/src/pcr-policy.c
index 95a4299..8f2c42c 100644
--- a/src/pcr-policy.c
+++ b/src/pcr-policy.c
@@ -1539,57 +1539,6 @@ pcr_unseal_secret(const target_platform_t *platform,
return platform->unseal_secret(input_path, output_path, pcr_selection, signed_policy_path, public_key_file);
}
-bool
-pcr_policy_sign_systemd(const tpm_pcr_bank_t *bank,
- const stored_key_t *private_key_file,
- const char *output_path)
-{
- bool ok = false;
- FILE *fp = NULL;
- tpm_rsa_key_t *rsa_key = NULL;
- const tpm_evdigest_t *digest;
- ESYS_CONTEXT *esys_context = tss_esys_context();
- TPM2B_DIGEST *pcr_policy = NULL;
- TPMT_SIGNATURE *signed_policy = NULL;
-
- if (!(fp = fopen(output_path, "w"))) {
- error("Cannot open systemd JSON file %s: %m\n", output_path);
- goto out;
- }
-
- if (!(rsa_key = stored_key_read_rsa_private(private_key_file)))
- goto out;
- digest = tpm_rsa_key_public_digest(rsa_key);
-
- if (!(pcr_policy = __pcr_policy_make(esys_context, bank)))
- goto out;
-
- if (!__pcr_policy_sign(rsa_key, pcr_policy, &signed_policy))
- goto out;
-
- fprintf(fp, "{\n");
- fprintf(fp, "\t\"%s\": [\n", bank->algo_name);
- fprintf(fp, "\t\t\{\n");
- fprintf(fp, "\t\t\t\"pcrs\": [\n");
- fprintf(fp, "\t\t\t\t%s\n", print_pcr_mask(bank->pcr_mask));
- fprintf(fp, "\t\t\t],\n");
- fprintf(fp, "\t\t\t\"pkfp\": \"%s\",\n", print_hex_string(digest->data, digest->size));
- fprintf(fp, "\t\t\t\"pol\": \"%s\",\n", print_hex_string(pcr_policy->buffer, pcr_policy->size));
- fprintf(fp, "\t\t\t\"sig\": \"%s\"\n", print_base64_value(signed_policy->signature.rsassa.sig.buffer, signed_policy->signature.rsassa.sig.size));
- fprintf(fp, "\t\t}\n");
- fprintf(fp, "\t]\n");
- fprintf(fp, "}\n");
-
- ok = true;
-
-out:
- if (rsa_key)
- tpm_rsa_key_free(rsa_key);
-
- fclose(fp);
- return ok;
-}
-
/*
* Depending on the target platform, sealed data, authorized policies etc are
* written to different types of files.
diff --git a/src/pcr.h b/src/pcr.h
index 1b0f544..4d8f816 100644
--- a/src/pcr.h
+++ b/src/pcr.h
@@ -65,9 +65,6 @@ extern bool pcr_policy_sign(const target_platform_t *platform, const tpm_pcr_ba
const stored_key_t *private_key_file,
const char *input_path,
const char *output_path, const char *policy_name);
-extern bool pcr_policy_sign_systemd(const tpm_pcr_bank_t *bank,
- const stored_key_t *private_key_file,
- const char *output_path);
extern bool pcr_authorized_policy_seal_secret(const target_platform_t *platform,
const char *authorized_policy, const char *input_path,
const char *output_path);
From 3a66b6e1dc953ac95a715a4b1123e772024fba2c Mon Sep 17 00:00:00 2001
From: Olaf Kirch <okir@suse.com>
Date: Mon, 27 Nov 2023 17:18:14 +0100
Subject: [PATCH 02/13] Introduce read_single_line_file() and use it in
sd-boot.c
Signed-off-by: Olaf Kirch <okir@suse.com>
---
src/sd-boot.c | 30 ++----------------------------
src/util.c | 19 +++++++++++++++++++
src/util.h | 1 +
3 files changed, 22 insertions(+), 28 deletions(-)
diff --git a/src/sd-boot.c b/src/sd-boot.c
index 3eea1a1..bbdb498 100644
--- a/src/sd-boot.c
+++ b/src/sd-boot.c
@@ -37,21 +37,8 @@ static const char *
read_entry_token(void)
{
static char id[SDB_LINE_MAX];
- FILE *fp;
-
- if (!(fp = fopen("/etc/kernel/entry-token", "r"))) {
- debug("Cannot open /etc/kernel/entry-token\n");
- goto fail;
- }
-
- if (fgets(id, SDB_LINE_MAX, fp))
- id[strcspn(id, "\n")] = 0;
- fclose(fp);
- return id;
-
-fail:
- return NULL;
+ return read_single_line_file("/etc/kernel/entry-token", id, sizeof(id));
}
static const char *
@@ -109,21 +96,8 @@ static const char *
read_machine_id(void)
{
static char id[SDB_LINE_MAX];
- FILE *fp;
-
- if (!(fp = fopen("/etc/machine-id", "r"))) {
- error("Cannot open /etc/machine_id: %m\n");
- goto fail;
- }
-
- if (fgets(id, SDB_LINE_MAX, fp))
- id[strcspn(id, "\n")] = 0;
- fclose(fp);
- return id;
-
-fail:
- return NULL;
+ return read_single_line_file("/etc/machine-id", id, sizeof(id));
}
static bool
diff --git a/src/util.c b/src/util.c
index 1f2640f..644d138 100644
--- a/src/util.c
+++ b/src/util.c
@@ -514,3 +514,22 @@ path_has_file_extension(const char *path, const char *suffix)
return !strcasecmp(path + n, suffix);
}
+
+const char *
+read_single_line_file(const char *path, char *buffer, size_t size)
+{
+ FILE *fp;
+
+ if (!(fp = fopen(path, "r"))) {
+ debug("Cannot open %s: %m\n", path);
+ return NULL;
+ }
+
+ if (fgets(buffer, size, fp) != NULL)
+ buffer[strcspn(buffer, "\n")] = 0;
+ else
+ buffer[0] = '\0';
+
+ fclose(fp);
+ return buffer;
+}
diff --git a/src/util.h b/src/util.h
index c98017f..e63ef16 100644
--- a/src/util.h
+++ b/src/util.h
@@ -142,6 +142,7 @@ extern double timing_since(double);
extern const char * path_unix2dos(const char *path);
extern const char * path_dos2unix(const char *path);
extern bool path_has_file_extension(const char *path, const char *suffix);
+extern const char * read_single_line_file(const char *path, char *buffer, size_t size);
extern int version_string_compare(const char *, const char *);
From 32680d9efa0b866bd78d7ad5bd362aca511efc05 Mon Sep 17 00:00:00 2001
From: Olaf Kirch <okir@suse.com>
Date: Mon, 27 Nov 2023 18:26:36 +0100
Subject: [PATCH 03/13] tpm_event_get_digest: changed second argument from
algo_name to an algo_info pointer
Signed-off-by: Olaf Kirch <okir@suse.com>
---
src/efi-application.c | 2 +-
src/efi-variable.c | 6 +++---
src/eventlog.c | 6 +-----
src/eventlog.h | 2 +-
src/oracle.c | 2 +-
5 files changed, 7 insertions(+), 11 deletions(-)
diff --git a/src/efi-application.c b/src/efi-application.c
index 14a2450..06ac9ff 100644
--- a/src/efi-application.c
+++ b/src/efi-application.c
@@ -287,7 +287,7 @@ __tpm_event_efi_bsa_rehash(const tpm_event_t *ev, const tpm_parsed_event_t *pars
*/
if (!evspec->efi_application) {
debug("Unable to locate boot service application - probably not a file\n");
- return tpm_event_get_digest(ev, ctx->algo->openssl_name);
+ return tpm_event_get_digest(ev, ctx->algo);
}
/* The next boot can have a different kernel */
diff --git a/src/efi-variable.c b/src/efi-variable.c
index 7e9e38b..6c08cde 100644
--- a/src/efi-variable.c
+++ b/src/efi-variable.c
@@ -141,7 +141,7 @@ __tpm_event_efi_variable_detect_hash_strategy(const tpm_event_t *ev, const tpm_p
{
const tpm_evdigest_t *md, *old_md;
- old_md = tpm_event_get_digest(ev, algo->openssl_name);
+ old_md = tpm_event_get_digest(ev, algo);
if (old_md == NULL) {
debug("Event does not provide a digest for algorithm %s\n", algo->openssl_name);
return -1;
@@ -199,7 +199,7 @@ __tpm_event_efi_variable_rehash(const tpm_event_t *ev, const tpm_parsed_event_t
* For the time being, just pretend these cannot be changed from
* within the running system.
*/
- md = tpm_event_get_digest(ev, algo->openssl_name);
+ md = tpm_event_get_digest(ev, algo);
goto out;
}
} else {
@@ -214,7 +214,7 @@ __tpm_event_efi_variable_rehash(const tpm_event_t *ev, const tpm_parsed_event_t
/* The content of the variable doesn't exist during the measurement
* and is also not available at runtime. Let's skip this event.
*/
- md = tpm_event_get_digest(ev, algo->openssl_name);
+ md = tpm_event_get_digest(ev, algo);
}
goto out;
}
diff --git a/src/eventlog.c b/src/eventlog.c
index e99a20f..32cc75c 100644
--- a/src/eventlog.c
+++ b/src/eventlog.c
@@ -406,14 +406,10 @@ tpm_event_type_to_string(unsigned int event_type)
}
const tpm_evdigest_t *
-tpm_event_get_digest(const tpm_event_t *ev, const char *algo_name)
+tpm_event_get_digest(const tpm_event_t *ev, const tpm_algo_info_t *algo_info)
{
- const tpm_algo_info_t *algo_info;
unsigned int i;
- if ((algo_info = digest_by_name(algo_name)) < 0)
- fatal("Unknown algo name \"%s\"\n", algo_name);
-
for (i = 0; i < ev->pcr_count; ++i) {
const tpm_evdigest_t *md = &ev->pcr_values[i];
diff --git a/src/eventlog.h b/src/eventlog.h
index 8951765..bd1106f 100644
--- a/src/eventlog.h
+++ b/src/eventlog.h
@@ -291,7 +291,7 @@ extern void tpm_event_log_scan_ctx_init(tpm_event_log_scan_ctx_t *);
extern void tpm_event_log_scan_ctx_destroy(tpm_event_log_scan_ctx_t *);
extern tpm_parsed_event_t * tpm_event_parse(tpm_event_t *ev, tpm_event_log_scan_ctx_t *);
extern const char * tpm_event_type_to_string(unsigned int event_type);
-extern const tpm_evdigest_t * tpm_event_get_digest(const tpm_event_t *ev, const char *algo_name);
+extern const tpm_evdigest_t * tpm_event_get_digest(const tpm_event_t *ev, const tpm_algo_info_t *algo_info);
extern void tpm_parsed_event_print(tpm_parsed_event_t *parsed,
tpm_event_bit_printer *);
extern const char * tpm_parsed_event_describe(tpm_parsed_event_t *parsed);
diff --git a/src/oracle.c b/src/oracle.c
index 52fe261..c4e4873 100644
--- a/src/oracle.c
+++ b/src/oracle.c
@@ -670,7 +670,7 @@ predictor_update_eventlog(struct predictor *pred)
debug("\n");
__tpm_event_print(ev, debug);
- if (!(old_digest = tpm_event_get_digest(ev, pred->algo)))
+ if (!(old_digest = tpm_event_get_digest(ev, pred->algo_info)))
fatal("Event log lacks a hash for digest algorithm %s\n", pred->algo);
if (false) {
From 4d88450e9da882c759a68ba8c15267b22a377cdc Mon Sep 17 00:00:00 2001
From: Olaf Kirch <okir@suse.com>
Date: Mon, 27 Nov 2023 18:31:42 +0100
Subject: [PATCH 04/13] Add uapi_ types and functions for dealing with UAPI
boot entries
Signed-off-by: Olaf Kirch <okir@suse.com>
---
Makefile.in | 3 +-
src/types.h | 1 +
src/uapi.c | 323 ++++++++++++++++++++++++++++++++++++++++++++++++++++
src/uapi.h | 43 +++++++
4 files changed, 369 insertions(+), 1 deletion(-)
create mode 100644 src/uapi.c
create mode 100644 src/uapi.h
diff --git a/Makefile.in b/Makefile.in
index a0508e9..02a915b 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -33,7 +33,8 @@ ORACLE_SRCS = oracle.c \
bufparser.c \
store.c \
util.c \
- sd-boot.c
+ sd-boot.c \
+ uapi.c
ORACLE_OBJS = $(addprefix build/,$(patsubst %.c,%.o,$(ORACLE_SRCS)))
all: $(TOOLS) $(MANPAGES)
diff --git a/src/types.h b/src/types.h
index e76903a..5b01079 100644
--- a/src/types.h
+++ b/src/types.h
@@ -35,6 +35,7 @@ typedef struct pecoff_image_info pecoff_image_info_t;
typedef struct testcase testcase_t;
typedef struct stored_key stored_key_t;
typedef struct target_platform target_platform_t;
+typedef struct uapi_boot_entry uapi_boot_entry_t;
#endif /* TYPES_H */
diff --git a/src/uapi.c b/src/uapi.c
new file mode 100644
index 0000000..bbcaea9
--- /dev/null
+++ b/src/uapi.c
@@ -0,0 +1,323 @@
+/*
+ * Copyright (C) 2022, 2023 SUSE LLC
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Written by Alberto Planas <aplanas@suse.com>, Olaf Kirch <okir@suse.com>
+ */
+
+
+#include <stdlib.h>
+#include <sys/dir.h>
+#include <sys/param.h>
+#include <sys/utsname.h>
+#include <limits.h>
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include "uapi.h"
+#include "util.h"
+
+#define UAPI_LINE_MAX 1024
+
+
+static int vercmp(const void *va, const void *vb);
+
+static uapi_boot_entry_t *
+uapi_boot_entry_new(void)
+{
+ uapi_boot_entry_t *ube;
+
+ ube = calloc(1, sizeof(*ube));
+ return ube;
+}
+
+static void
+drop_boot_entry(uapi_boot_entry_t **entry_p)
+{
+ if (*entry_p) {
+ uapi_boot_entry_free(*entry_p);
+ *entry_p = NULL;
+ }
+}
+
+static uapi_boot_entry_t *
+uapi_boot_entry_load(const char *path)
+{
+ uapi_boot_entry_t *result = NULL;
+ char line[UAPI_LINE_MAX];
+ FILE *fp;
+
+ if (!(fp = fopen(path, "r"))) {
+ error("Unable to open %s: %m\n", path);
+ return NULL;
+ }
+
+ result = uapi_boot_entry_new();
+ while (fgets(line, sizeof(line), fp)) {
+ char *key, *value;
+ unsigned int i;
+
+ if (!isalpha(line[0]))
+ continue;
+
+ /* strip white space off the end */
+ i = strlen(line);
+ while (i > 0 && isspace(line[i-1]))
+ line[--i] = '\0';
+
+ key = line;
+ for (i = 0; line[i]; ++i) {
+ if (isspace(line[i])) {
+ line[i++] = '\0';
+ break;
+ }
+ }
+
+ while (isspace(line[i]))
+ ++i;
+ value = line + i;
+ if (*value == '\0')
+ value = NULL;
+
+ if (!strcmp("sort-key", key))
+ assign_string(&result->sort_key, value);
+ else
+ if (!strcmp("machine-id", key))
+ assign_string(&result->machine_id, value);
+ else
+ if (!strcmp("version", key))
+ assign_string(&result->version, value);
+ else
+ if (!strcmp("options", key))
+ assign_string(&result->options, value);
+ else
+ if (!strcmp("linux", key))
+ assign_string(&result->image_path, value);
+ else
+ if (!strcmp("initrd", key))
+ assign_string(&result->initrd_path, value);
+ }
+
+ fclose(fp);
+ return result;
+}
+
+static bool
+uapi_boot_entry_applies(const uapi_boot_entry_t *entry, const char *machine_id, const char *architecture)
+{
+ if (entry->machine_id && machine_id && strcmp(entry->machine_id, machine_id))
+ return false;
+ if (entry->architecture && architecture && strcmp(entry->architecture, architecture))
+ return false;
+ /* We don't check the efi key because it can only express "entry is EFI only"; it cannot express
+ * "this is a legacy BIOS entry" */
+ return true;
+}
+
+/*
+ * Returns true iff entry_a is "more recent" or "better" than entry_b
+ */
+static bool
+uapi_boot_entry_more_recent(const uapi_boot_entry_t *entry_a, const uapi_boot_entry_t *entry_b)
+{
+ int r = 0;
+
+ /* having a sort key is better than not having one. */
+ r = strcmp(entry_a->sort_key? : "", entry_b->sort_key? : "");
+
+ if (r == 0)
+ r = vercmp(entry_a->version? : "", entry_b->version? : "");
+
+ return r > 0;
+}
+
+/*
+ * We pass in a best_ret pointer in case we need to extend this
+ * to search more than on directory
+ */
+uapi_boot_entry_t *
+uapi_find_matching_boot_entry(const char *dir_path,
+ const char *entry_id, const char *machine_id, const char *architecture,
+ uapi_boot_entry_t **best_ret)
+{
+ uapi_boot_entry_t *best = *best_ret;
+ unsigned int entry_id_len = 0;
+ struct dirent *d;
+ DIR *dir;
+
+ if (!(dir = opendir(dir_path))) {
+ if (errno != ENOENT)
+ error("Cannot open %s for reading: %m\n", dir_path);
+ return NULL;
+ }
+
+ if (entry_id)
+ entry_id_len = strlen(entry_id);
+
+ while ((d = readdir(dir)) != NULL) {
+ char config_path[PATH_MAX];
+ uapi_boot_entry_t *entry;
+
+ if (d->d_type != DT_REG)
+ continue;
+
+ if (entry_id && strncmp(d->d_name, entry_id, entry_id_len))
+ continue;
+
+ snprintf(config_path, sizeof(config_path), "%s/%s", dir_path, d->d_name);
+ if (!(entry = uapi_boot_entry_load(config_path))) {
+ warning("Unable to process UAPI boot entry file at \"%s\"\n", config_path);
+ continue;
+ }
+
+ if (uapi_boot_entry_applies(entry, machine_id, architecture)) {
+ if (best == NULL || uapi_boot_entry_more_recent(entry, best)) {
+ /* swap best and entry */
+ uapi_boot_entry_t *tmp = best;
+ best = entry;
+ entry = tmp;
+ }
+ }
+
+ drop_boot_entry(&entry);
+ }
+
+ closedir(dir);
+
+ *best_ret = best;
+ return best;
+}
+
+uapi_boot_entry_t *
+uapi_find_boot_entry(const char *id, const char *machine_id)
+{
+ uapi_boot_entry_t *best = NULL;
+ struct utsname uts;
+ const char *architecture;
+
+ if (uname(&uts) >= 0)
+ architecture = uts.machine;
+
+ return uapi_find_matching_boot_entry(UAPI_BOOT_DIRECTORY,
+ id, machine_id, architecture,
+ &best);
+}
+
+void
+uapi_boot_entry_free(uapi_boot_entry_t *ube)
+{
+ drop_string(&ube->title);
+ drop_string(&ube->version);
+ drop_string(&ube->machine_id);
+ drop_string(&ube->image_path);
+ drop_string(&ube->initrd_path);
+ drop_string(&ube->options);
+ free(ube);
+}
+
+/*
+ * Version comparison
+ */
+static int
+cmp(int a, int b)
+{
+ return a - b;
+}
+
+static bool
+isvalid(char a)
+{
+ return isalnum(a) || a == '~' || a == '-' || a == '^' || a == '.';
+}
+
+static int
+natoi(const char *a, unsigned int n)
+{
+ char line[UAPI_LINE_MAX];
+
+ strncpy(line, a, MIN(UAPI_LINE_MAX, n));
+ return atoi(line);
+}
+
+static int
+vercmp(const void *va, const void *vb)
+{
+ /* https://uapi-group.org/specifications/specs/version_format_specification/ */
+ /* This code is based on strverscmp_improved from systemd */
+
+ const char *a = va;
+ const char *b = vb;
+ const char *sep = "~-^.";
+
+ assert(a != NULL);
+ assert(b != NULL);
+
+ for(;;) {
+ const char *aa, *bb;
+ int r;
+
+ while (*a != '\0' && !isvalid(*a))
+ a++;
+ while (*b != '\0' && !isvalid(*b))
+ b++;
+
+ /* The longer string is considered new */
+ if (*a == '\0' || *b == '\0')
+ return cmp(*a, *b);
+
+ for (int i = 0; i < strlen(sep); i++) {
+ char s = sep[i];
+
+ if (*a == s || *b == s) {
+ r = cmp(*a != s, *b != s);
+ if (r != 0)
+ return r;
+
+ a++;
+ b++;
+ }
+ }
+
+ if (isdigit(*a) || isdigit(*b)) {
+ for (aa = a; isdigit(*aa); aa++);
+ for (bb = b; isdigit(*bb); bb++);
+
+ r = cmp(a != aa, b != bb);
+ if (r != 0)
+ return r;
+
+ r = cmp(natoi(a, aa - a), natoi(b, bb - b));
+ if (r != 0)
+ return r;
+ } else {
+ for (aa = a; isalpha(*aa); aa++);
+ for (bb = b; isalpha(*bb); bb++);
+
+ r = cmp(strncmp(a, b, MIN(aa - a, bb - b)), 0);
+ if (r != 0)
+ return r;
+
+ r = cmp(aa - a, bb - b);
+ if (r != 0)
+ return r;
+ }
+
+ a = aa;
+ b = bb;
+ }
+}
+
diff --git a/src/uapi.h b/src/uapi.h
new file mode 100644
index 0000000..ba1147e
--- /dev/null
+++ b/src/uapi.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2022, 2023 SUSE LLC
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Written by Olaf Kirch <okir@suse.com>
+ */
+
+#ifndef UAPI_H
+#define UAPI_H
+
+#include "types.h"
+
+struct uapi_boot_entry {
+ char * title;
+ bool efi;
+ char * sort_key;
+ char * version;
+ char * machine_id;
+ char * architecture;
+ char * image_path;
+ char * initrd_path;
+ char * options;
+};
+
+#define UAPI_BOOT_DIRECTORY "/boot/efi/loader/entries"
+
+extern uapi_boot_entry_t * uapi_find_boot_entry(const char *id, const char *machine_id);
+extern void uapi_boot_entry_free(uapi_boot_entry_t *);
+
+#endif /* UAPI_H */
From a7a4c854c9668900c8eb9ea9c99d51b6e822f376 Mon Sep 17 00:00:00 2001
From: Olaf Kirch <okir@suse.com>
Date: Mon, 27 Nov 2023 18:33:38 +0100
Subject: [PATCH 05/13] Add --next-kernel command line option; use uapi to
locate next kernel when given
Signed-off-by: Olaf Kirch <okir@suse.com>
---
man/pcr-oracle.8.in | 12 ++++++++++++
src/eventlog.h | 3 +++
src/oracle.c | 23 +++++++++++++++++++++--
src/sd-boot.c | 19 +++++++++++++++++++
src/sd-boot.h | 3 +++
5 files changed, 58 insertions(+), 2 deletions(-)
diff --git a/man/pcr-oracle.8.in b/man/pcr-oracle.8.in
index eda3cfb..4bd60ba 100644
--- a/man/pcr-oracle.8.in
+++ b/man/pcr-oracle.8.in
@@ -495,6 +495,18 @@ events (tracked in PCR9). In this case, it would be totally sufficient
to stop processing after grub loaded \fPgrub.cfg\fP from the EFI
System Partition.
.TP
+.BI --next-kernel " id
+In a systemd-boot environment, the values of PCR registers also depend on
+the contents of the kernel and initrd image, as well as the kernel command line
+options. After a kernel update or an initrd rebuild, these values will change.
+So when predicting PCR values in this case, \fBpcr-oracle\fP needs to be
+instructed to refer to the future kernel rather than the current one.
+.IP
+This is what the \fB--next-kernel\fP option is for. It takes one argument, which
+is either an ID (in the sense of systemd-boot IDs), or \fBauto\fP. When
+the latter is given, \fBpcr-oracle\fP will make a best guess as to what
+kernel image will be used on next boot.
+.TP
.BI --authorized-policy " path
Specify the location of the authorized policy. In conjunction with
the \fBcreate-authorized-policy\fP action, the newly created policy
diff --git a/src/eventlog.h b/src/eventlog.h
index bd1106f..65e5322 100644
--- a/src/eventlog.h
+++ b/src/eventlog.h
@@ -200,6 +200,9 @@ typedef struct tpm_event_log_rehash_ctx {
bool use_pesign; /* compute authenticode FP using external pesign application */
const pecoff_image_info_t *next_stage_img;
+
+ /* This get set when the user specifies --next-kernel */
+ uapi_boot_entry_t * next_kernel;
} tpm_event_log_rehash_ctx_t;
#define GRUB_COMMAND_ARGV_MAX 32
diff --git a/src/oracle.c b/src/oracle.c
index c4e4873..2cc53c1 100644
--- a/src/oracle.c
+++ b/src/oracle.c
@@ -34,6 +34,7 @@
#include "rsa.h"
#include "store.h"
#include "testcase.h"
+#include "sd-boot.h"
enum {
ACTION_NONE,
@@ -58,6 +59,7 @@ struct predictor {
const char * initial_source;
const char * tpm_event_log_path;
+ const char * next_kernel_id;
const char * algo;
const tpm_algo_info_t * algo_info;
@@ -98,6 +100,7 @@ enum {
OPT_POLICY_NAME,
OPT_POLICY_FORMAT,
OPT_TARGET_PLATFORM,
+ OPT_NEXT_KERNEL,
};
static struct option options[] = {
@@ -114,6 +117,7 @@ static struct option options[] = {
{ "before", no_argument, 0, OPT_BEFORE },
{ "verify", required_argument, 0, OPT_VERIFY },
{ "use-pesign", no_argument, 0, OPT_USE_PESIGN },
+ { "next-kernel", required_argument, 0, OPT_NEXT_KERNEL },
{ "create-testcase", required_argument, 0, OPT_CREATE_TESTCASE },
{ "replay-testcase", required_argument, 0, OPT_REPLAY_TESTCASE },
@@ -129,6 +133,7 @@ static struct option options[] = {
{ "policy-name", required_argument, 0, OPT_POLICY_NAME },
{ "policy-format", required_argument, 0, OPT_POLICY_FORMAT },
{ "target-platform", required_argument, 0, OPT_TARGET_PLATFORM },
+ { "next-kernel", required_argument, 0, OPT_NEXT_KERNEL },
{ NULL }
};
@@ -250,7 +255,8 @@ predictor_load_eventlog(struct predictor *pred)
static struct predictor *
predictor_new(const tpm_pcr_selection_t *pcr_selection, const char *source,
const char *tpm_eventlog_path,
- const char *output_format)
+ const char *output_format,
+ const char *next_kernel_id)
{
struct predictor *pred;
@@ -260,6 +266,7 @@ predictor_new(const tpm_pcr_selection_t *pcr_selection, const char *source,
pred = calloc(1, sizeof(*pred));
pred->pcr_mask = pcr_selection->pcr_mask;
pred->initial_source = source;
+ pred->next_kernel_id = next_kernel_id;
pred->algo = pcr_selection->algo_info->openssl_name;
pred->algo_info = pcr_selection->algo_info;
@@ -651,6 +658,14 @@ predictor_update_eventlog(struct predictor *pred)
tpm_event_log_rehash_ctx_init(&rehash_ctx, pred->algo_info);
rehash_ctx.use_pesign = opt_use_pesign;
+ /* The argument given to --next-kernel will be either "auto" or the
+ * systemd ID of the next kernel entry to be booted.
+ * FIXME: we should probably hide this behind a target_platform function.
+ */
+ if (pred->next_kernel_id != NULL
+ && !(rehash_ctx.next_kernel = sdb_identify_next_kernel(pred->next_kernel_id)))
+ fatal("unable to identify next kernel \"%s\"\n", pred->next_kernel_id);
+
for (ev = pred->event_log; ev; ev = ev->next) {
tpm_evdigest_t *pcr;
bool stop = false;
@@ -1021,6 +1036,7 @@ main(int argc, char **argv)
char *opt_rsa_bits = NULL;
char *opt_policy_name = NULL;
char *opt_target_platform = NULL;
+ char *opt_next_kernel = NULL;
const target_platform_t *target;
unsigned int action_flags = 0;
unsigned int rsa_bits = 2048;
@@ -1055,6 +1071,9 @@ main(int argc, char **argv)
case OPT_USE_PESIGN:
opt_use_pesign = 1;
break;
+ case OPT_NEXT_KERNEL:
+ opt_next_kernel = optarg;
+ break;
case OPT_STOP_EVENT:
opt_stop_event = optarg;
break;
@@ -1296,7 +1315,7 @@ main(int argc, char **argv)
fatal("BUG: action %u should have parsed a PCR selection argument", action);
pred = predictor_new(pcr_selection, opt_from, opt_eventlog_path,
- opt_output_format);
+ opt_output_format, opt_next_kernel);
if (opt_stop_event)
predictor_set_stop_event(pred, opt_stop_event, !opt_stop_before);
diff --git a/src/sd-boot.c b/src/sd-boot.c
index bbdb498..2e7ec61 100644
--- a/src/sd-boot.c
+++ b/src/sd-boot.c
@@ -387,6 +387,25 @@ sdb_get_next_kernel(void)
return NULL;
}
+/*
+ * Identify the next kernel and initrd given an ID
+ */
+uapi_boot_entry_t *
+sdb_identify_next_kernel(const char *id)
+{
+ const char *machine_id;
+
+ if (id == NULL || !strcasecmp(id, "default")) {
+ if (!(id = get_token_id()))
+ return NULL;
+ }
+
+ if (!(machine_id = read_machine_id()))
+ return NULL;
+
+ return uapi_find_boot_entry(id, machine_id);
+}
+
/*
* Update the systemd json file
*/
diff --git a/src/sd-boot.h b/src/sd-boot.h
index ef36ce7..fa56751 100644
--- a/src/sd-boot.h
+++ b/src/sd-boot.h
@@ -21,6 +21,8 @@
#define SD_BOOT_H
#include <limits.h>
+#include "uapi.h"
+#include "types.h"
#define SDB_MAX_ENTRIES 16
#define SDB_LINE_MAX 512
@@ -40,6 +42,7 @@ typedef struct sdb_entry_list {
sdb_entry_data_t entries[SDB_MAX_ENTRIES];
} sdb_entry_list_t;
+extern uapi_boot_entry_t * sdb_identify_next_kernel(const char *id);
extern bool sdb_get_entry_list(sdb_entry_list_t *result);
extern bool sdb_is_kernel(const char *application);
extern const char * sdb_get_next_kernel(void);
From dcfc751ac78400d5bca53b560768f6a3603443f7 Mon Sep 17 00:00:00 2001
From: Olaf Kirch <okir@suse.com>
Date: Mon, 27 Nov 2023 18:41:26 +0100
Subject: [PATCH 06/13] Adjust EFI BSA and systemd event rehashing to use
rehash_ctx->next_kernel
Signed-off-by: Olaf Kirch <okir@suse.com>
---
src/efi-application.c | 4 ++--
src/eventlog.c | 38 +++++++++++++++++++++-----------------
2 files changed, 23 insertions(+), 19 deletions(-)
diff --git a/src/efi-application.c b/src/efi-application.c
index 06ac9ff..9d7e531 100644
--- a/src/efi-application.c
+++ b/src/efi-application.c
@@ -291,8 +291,8 @@ __tpm_event_efi_bsa_rehash(const tpm_event_t *ev, const tpm_parsed_event_t *pars
}
/* The next boot can have a different kernel */
- if (sdb_is_kernel(evspec->efi_application)) {
- new_application = sdb_get_next_kernel();
+ if (sdb_is_kernel(evspec->efi_application) && ctx->next_kernel) {
+ new_application = ctx->next_kernel->image_path;
if (new_application) {
evspec_clone = *evspec;
evspec_clone.efi_application = strdup(new_application);
diff --git a/src/eventlog.c b/src/eventlog.c
index 32cc75c..3498790 100644
--- a/src/eventlog.c
+++ b/src/eventlog.c
@@ -32,7 +32,7 @@
#include "runtime.h"
#include "digest.h"
#include "util.h"
-#include "sd-boot.h"
+#include "uapi.h"
#define TPM_EVENT_LOG_MAX_ALGOS 64
@@ -789,21 +789,24 @@ __tpm_event_systemd_describe(const tpm_parsed_event_t *parsed)
static const tpm_evdigest_t *
__tpm_event_systemd_rehash(const tpm_event_t *ev, const tpm_parsed_event_t *parsed, tpm_event_log_rehash_ctx_t *ctx)
{
- sdb_entry_list_t entry_list;
+ const uapi_boot_entry_t *next_kernel = ctx->next_kernel;
char initrd[2048];
char initrd_utf16[4096];
unsigned int len;
- memset(&entry_list, 0, sizeof(entry_list));
- if (!sdb_get_entry_list(&entry_list)) {
- error("Error generating the list of boot entries\n");
+ /* If no --next-kernel option was given, do not rehash anything */
+ if (next_kernel == NULL)
+ return tpm_event_get_digest(ev, ctx->algo);
+
+ if (!next_kernel->image_path) {
+ error("Unable to identify the next kernel\n");
return NULL;
}
- debug("Next boot entry expected from: %s\n", entry_list.entries[0].path);
+ debug("Next boot entry expected from: %s %s\n", next_kernel->title, next_kernel->version? : "");
snprintf(initrd, sizeof(initrd), "initrd=%s %s",
- path_unix2dos(entry_list.entries[0].path),
- entry_list.entries[0].options);
+ path_unix2dos(next_kernel->initrd_path),
+ next_kernel->options? : "");
len = (strlen(initrd) + 1) << 1;
assert(len <= sizeof(initrd_utf16));
@@ -860,19 +863,20 @@ __tpm_event_tag_initrd_describe(const tpm_parsed_event_t *parsed)
static const tpm_evdigest_t *
__tpm_event_tag_initrd_rehash(const tpm_event_t *ev, const tpm_parsed_event_t *parsed, tpm_event_log_rehash_ctx_t *ctx)
{
- sdb_entry_list_t entry_list;
- const tpm_evdigest_t *md = NULL;
+ const uapi_boot_entry_t *next_kernel = ctx->next_kernel;
+
+ /* If no --next-kernel option was given, do not rehash anything */
+ if (next_kernel == NULL)
+ return tpm_event_get_digest(ev, ctx->algo);
- memset(&entry_list, 0, sizeof(entry_list));
- if (!sdb_get_entry_list(&entry_list)) {
- error("Error generating the list of boot entries\n");
+ if (!next_kernel->initrd_path) {
+ /* Can this happen eg when going from a split kernel to a unified kernel? */
+ error("Unable to identify the next initrd\n");
return NULL;
}
- debug("Next boot entry expected from: %s\n", entry_list.entries[0].path);
- md = runtime_digest_efi_file(ctx->algo, entry_list.entries[0].initrd);
-
- return md;
+ debug("Next boot entry expected from: %s %s\n", next_kernel->title, next_kernel->version? : "");
+ return runtime_digest_efi_file(ctx->algo, next_kernel->initrd_path);
}
/*
From 13f67d840ffadccbd0daf4fb133f9471a5b1a439 Mon Sep 17 00:00:00 2001
From: Olaf Kirch <okir@suse.com>
Date: Mon, 27 Nov 2023 18:44:05 +0100
Subject: [PATCH 07/13] Remove old code from sd-boot.*
Signed-off-by: Olaf Kirch <okir@suse.com>
---
src/sd-boot.c | 222 +-------------------------------------------------
src/sd-boot.h | 2 -
2 files changed, 3 insertions(+), 221 deletions(-)
diff --git a/src/sd-boot.c b/src/sd-boot.c
index 2e7ec61..c878f6c 100644
--- a/src/sd-boot.c
+++ b/src/sd-boot.c
@@ -100,163 +100,6 @@ read_machine_id(void)
return read_single_line_file("/etc/machine-id", id, sizeof(id));
}
-static bool
-read_entry(sdb_entry_data_t *result)
-{
- FILE *fp;
- char line[SDB_LINE_MAX];
-
- if (!(fp = fopen(result->path, "r"))) {
- error("Cannot open %s: %m\n", result->path);
- goto fail;
- }
-
- while (fgets(line, SDB_LINE_MAX, fp)) {
- char *dest = NULL;
-
- if (!strncmp("sort-key", line, strlen("sort-key")))
- dest = result->sort_key;
- else
- if (!strncmp("machine-id", line, strlen("machine-id")))
- dest = result->machine_id;
- else
- if (!strncmp("version", line, strlen("version")))
- dest = result->version;
- else
- if (!strncmp("options", line, strlen("options")))
- dest = result->options;
- else
- if (!strncmp("linux", line, strlen("linux")))
- dest = result->image;
- else
- if (!strncmp("initrd", line, strlen("initrd")))
- dest = result->initrd;
- else
- continue;
-
- /* Position the index on the value section of the line */
- unsigned int index = 0;
- while (line[++index] != ' ');
- while (line[++index] == ' ');
- strncpy(dest, &line[index], strlen(&line[index]) - 1);
- }
-
- fclose(fp);
- return true;
-
-fail:
- return false;
-}
-
-static int
-cmp(int a, int b)
-{
- return a - b;
-}
-
-static bool
-isvalid(char a)
-{
- return isalnum(a) || a == '~' || a == '-' || a == '^' || a == '.';
-}
-
-static int
-natoi(const char *a, unsigned int n)
-{
- char line[SDB_LINE_MAX];
-
- strncpy(line, a, MIN(SDB_LINE_MAX, n));
- return atoi(line);
-}
-
-static int
-vercmp(const void *va, const void *vb)
-{
- /* https://uapi-group.org/specifications/specs/version_format_specification/ */
- /* This code is based on strverscmp_improved from systemd */
-
- const char *a = va;
- const char *b = vb;
- const char *sep = "~-^.";
-
- assert(a != NULL);
- assert(b != NULL);
-
- for(;;) {
- const char *aa, *bb;
- int r;
-
- while (*a != '\0' && !isvalid(*a))
- a++;
- while (*b != '\0' && !isvalid(*b))
- b++;
-
- /* The longer string is considered new */
- if (*a == '\0' || *b == '\0')
- return cmp(*a, *b);
-
- for (int i = 0; i < strlen(sep); i++) {
- char s = sep[i];
-
- if (*a == s || *b == s) {
- r = cmp(*a != s, *b != s);
- if (r != 0)
- return r;
-
- a++;
- b++;
- }
- }
-
- if (isdigit(*a) || isdigit(*b)) {
- for (aa = a; isdigit(*aa); aa++);
- for (bb = b; isdigit(*bb); bb++);
-
- r = cmp(a != aa, b != bb);
- if (r != 0)
- return r;
-
- r = cmp(natoi(a, aa - a), natoi(b, bb - b));
- if (r != 0)
- return r;
- } else {
- for (aa = a; isalpha(*aa); aa++);
- for (bb = b; isalpha(*bb); bb++);
-
- r = cmp(strncmp(a, b, MIN(aa - a, bb - b)), 0);
- if (r != 0)
- return r;
-
- r = cmp(aa - a, bb - b);
- if (r != 0)
- return r;
- }
-
- a = aa;
- b = bb;
- }
-}
-
-static int
-entrycmp(const void *va, const void *vb)
-{
- /* https://uapi-group.org/specifications/specs/boot_loader_specification/#sorting */
- int result;
- const sdb_entry_data_t *a = va;
- const sdb_entry_data_t *b = vb;
-
- result = strcmp(a->sort_key, b->sort_key);
-
- if (result == 0)
- result = strcmp(a->machine_id, b->machine_id);
-
- if (result == 0)
- result = vercmp(a->version, b->version);
-
- /* Reverse the order, so new kernels appears first */
- return -result;
-}
-
static bool
exists_efi_dir(const char *path)
{
@@ -302,49 +145,9 @@ get_token_id(void)
return token_id;
}
-bool
-sdb_get_entry_list(sdb_entry_list_t *result)
-{
- const char *token_id = NULL;
- DIR *d = NULL;
- struct dirent *dir;
- char *path = "/boot/efi/loader/entries";
-
- if (!(token_id = get_token_id()))
- goto fail;
-
- if (!(d = opendir(path))) {
- error("Cannot read directory contents from /boot/efi/loader/entries: %m\n");
- goto fail;
- }
-
- while ((dir = readdir(d)) != NULL) {
- if (result->num_entries >= SDB_MAX_ENTRIES)
- break;
-
- if (strncmp(token_id, dir->d_name, strlen(token_id)))
- continue;
-
- debug("Bootloader entry %s\n", dir->d_name);
-
- snprintf(result->entries[result->num_entries].path, PATH_MAX, "%s/%s", path, dir->d_name);
- if (!read_entry(&result->entries[result->num_entries])) {
- error("Cannot read bootloader entry %s\n", dir->d_name);
- continue;
- }
-
- result->num_entries++;
- }
-
- qsort(result->entries, result->num_entries, sizeof(result->entries[0]), entrycmp);
-
- closedir(d);
- return true;
-
-fail:
- return false;
-}
-
+/*
+ * This should probably use UAPI boot entry logic as well
+ */
bool
sdb_is_kernel(const char *application)
{
@@ -368,25 +171,6 @@ sdb_is_kernel(const char *application)
return false;
}
-const char *
-sdb_get_next_kernel(void)
-{
- static char result[SDB_LINE_MAX];
- sdb_entry_list_t entry_list;
-
- memset(&entry_list, 0, sizeof(entry_list));
- if (!sdb_get_entry_list(&entry_list)) {
- error("Error generating the list of boot entries\n");
- goto fail;
- }
-
- strncpy(result, entry_list.entries[0].image, SDB_LINE_MAX);
- return result;
-
-fail:
- return NULL;
-}
-
/*
* Identify the next kernel and initrd given an ID
*/
diff --git a/src/sd-boot.h b/src/sd-boot.h
index fa56751..2b11dc1 100644
--- a/src/sd-boot.h
+++ b/src/sd-boot.h
@@ -43,9 +43,7 @@ typedef struct sdb_entry_list {
} sdb_entry_list_t;
extern uapi_boot_entry_t * sdb_identify_next_kernel(const char *id);
-extern bool sdb_get_entry_list(sdb_entry_list_t *result);
extern bool sdb_is_kernel(const char *application);
-extern const char * sdb_get_next_kernel(void);
/* This will have to update the systemd json file, and add a new entry. */
extern bool sdb_policy_file_add_entry(const char *filename,
From 737d8d561cfbd1dd03e7c4d37d7c515b709cce11 Mon Sep 17 00:00:00 2001
From: Olaf Kirch <okir@suse.com>
Date: Tue, 28 Nov 2023 10:30:10 +0100
Subject: [PATCH 08/13] Manpage fixes
Signed-off-by: Olaf Kirch <okir@suse.com>
---
man/pcr-oracle.8.in | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/man/pcr-oracle.8.in b/man/pcr-oracle.8.in
index 4bd60ba..3682afa 100644
--- a/man/pcr-oracle.8.in
+++ b/man/pcr-oracle.8.in
@@ -82,7 +82,7 @@ object in a native format defined in the TPM specification.
Finally, the systemd-boot implementation for unlocking disk partitions
stores policies in a JSON formatted file, which can be fed to the
\fBsystemd-cryptenroll\fP tool. This file will contain any number of
-signed policies that we want \fBsystemd-cryptsetup\fB to recognize during
+signed policies that we want \fBsystemd-cryptsetup\fP to recognize during
boot time. Each entry contains the list of PCRs that compose the PCR policy, a
finger print of the public key, the hash of the policy and the signature (in
base64) of the PCR policy.
@@ -366,7 +366,7 @@ that. The main difference is in the way the signed policy is stored:
--from eventlog \\
--output tpm2-pcr-signature.json \\
--policy-format systemd \\
- sign 0,2,4,7,9,11
+ sign 0,2,4,7,9,12
.fi
.P
This will predict a set of PCR values, sign them using the specified
@@ -384,9 +384,8 @@ These policies can then be enrolled for future system boots using
# systemd-cryptenroll \\
--tpm2-device=auto \\
--tpm2-public-key=public-key.pem \\
- --tpm2-public-key-pcrs="0,2,4,7,9,11" \
+ --tpm2-public-key-pcrs="0,2,4,7,9,12" \
--tpm2-signature=tpm2-pcr-signature.json \\
- --policy-format systemd \\
/dev/sda3
.fi
.\" ##################################################################
@@ -510,7 +509,7 @@ kernel image will be used on next boot.
.BI --authorized-policy " path
Specify the location of the authorized policy. In conjunction with
the \fBcreate-authorized-policy\fP action, the newly created policy
-is written to this location. For subsequent actions, such as \fBseal\fB,
+is written to this location. For subsequent actions, such as \fBseal\fP,
the policy will be read from this location.
.TP
.BI --private-key " path
From c0011884d8685d4f59523e45f69bd77d2c113838 Mon Sep 17 00:00:00 2001
From: Olaf Kirch <okir@suse.com>
Date: Tue, 28 Nov 2023 10:42:12 +0100
Subject: [PATCH 09/13] Several fixes resulting from review by alberto
Signed-off-by: Olaf Kirch <okir@suse.com>
---
src/uapi.c | 4 +---
src/util.c | 2 +-
2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/src/uapi.c b/src/uapi.c
index bbcaea9..a12ad21 100644
--- a/src/uapi.c
+++ b/src/uapi.c
@@ -123,8 +123,6 @@ uapi_boot_entry_applies(const uapi_boot_entry_t *entry, const char *machine_id,
return false;
if (entry->architecture && architecture && strcmp(entry->architecture, architecture))
return false;
- /* We don't check the efi key because it can only express "entry is EFI only"; it cannot express
- * "this is a legacy BIOS entry" */
return true;
}
@@ -147,7 +145,7 @@ uapi_boot_entry_more_recent(const uapi_boot_entry_t *entry_a, const uapi_boot_en
/*
* We pass in a best_ret pointer in case we need to extend this
- * to search more than on directory
+ * to search more than one directory
*/
uapi_boot_entry_t *
uapi_find_matching_boot_entry(const char *dir_path,
diff --git a/src/util.c b/src/util.c
index 644d138..7343ffb 100644
--- a/src/util.c
+++ b/src/util.c
@@ -526,7 +526,7 @@ read_single_line_file(const char *path, char *buffer, size_t size)
}
if (fgets(buffer, size, fp) != NULL)
- buffer[strcspn(buffer, "\n")] = 0;
+ buffer[strcspn(buffer, "\n")] = '\0';
else
buffer[0] = '\0';
From f0c09557aa72794c7149529056e6fc9ea1cd2763 Mon Sep 17 00:00:00 2001
From: Olaf Kirch <okir@suse.com>
Date: Tue, 28 Nov 2023 10:45:15 +0100
Subject: [PATCH 10/13] When matching UAPI boot entries, check against all
possible entry-tokens
Signed-off-by: Olaf Kirch <okir@suse.com>
---
src/sd-boot.c | 87 +++++++++++++++++++++++++++++++++++++--------------
src/uapi.c | 50 ++++++++++++++++++++++++-----
src/uapi.h | 11 ++++++-
3 files changed, 115 insertions(+), 33 deletions(-)
diff --git a/src/sd-boot.c b/src/sd-boot.c
index c878f6c..8dc9bf1 100644
--- a/src/sd-boot.c
+++ b/src/sd-boot.c
@@ -32,7 +32,6 @@
#include "sd-boot.h"
#include "util.h"
-
static const char *
read_entry_token(void)
{
@@ -100,6 +99,34 @@ read_machine_id(void)
return read_single_line_file("/etc/machine-id", id, sizeof(id));
}
+/*
+ * Kernels installed by kernel-install can use a variety of IDs as entry-token.
+ * Try to cater to all of them.
+ */
+static const uapi_kernel_entry_tokens_t *
+get_valid_kernel_entry_tokens(void)
+{
+ static uapi_kernel_entry_tokens_t valid_tokens;
+ const char *token;
+
+ if (valid_tokens.count != 0)
+ return &valid_tokens; /* I've been here before */
+
+ if ((token = read_entry_token()) != NULL)
+ uapi_kernel_entry_tokens_add(&valid_tokens, token);
+
+ if ((token = read_machine_id()) != NULL)
+ uapi_kernel_entry_tokens_add(&valid_tokens, token);
+
+ if ((token = read_os_release("ID")) != NULL)
+ uapi_kernel_entry_tokens_add(&valid_tokens, token);
+
+ if ((token = read_os_release("IMAGE_ID")) != NULL)
+ uapi_kernel_entry_tokens_add(&valid_tokens, token);
+
+ return &valid_tokens;
+}
+
static bool
exists_efi_dir(const char *path)
{
@@ -151,24 +178,28 @@ get_token_id(void)
bool
sdb_is_kernel(const char *application)
{
- const char *token_id;
- const char *prefix = "linux-";
- char path[PATH_MAX];
-
- if (!(token_id = get_token_id()))
- goto fail;
-
- snprintf(path, PATH_MAX, "/%s/", token_id);
- if (strncmp(path, application, strlen(path)))
- goto fail;
-
- strncpy(path, application, PATH_MAX);
- for (char *ptr = strtok(path, "/"); ptr; ptr = strtok(NULL, "/"))
- if (!strncmp(ptr, prefix, strlen(prefix)))
- return true;
+ static const char prefix[] = "linux-";
+ const uapi_kernel_entry_tokens_t *match;
+ char *path_copy;
+ int found = 0;
+
+ match = get_valid_kernel_entry_tokens();
+ path_copy = strdup(application);
+
+ for (char *ptr = strtok(path_copy, "/"); ptr; ptr = strtok(NULL, "/")) {
+ unsigned int i;
+ for (i = 0; i < match->count; ++i) {
+ const char *token = match->entry_token[i];
+
+ if (!strcmp(ptr, token))
+ found |= 1;
+ else if (!strncmp(ptr, prefix, sizeof(prefix) - 1))
+ found |= 2;
+ }
+ }
-fail:
- return false;
+ free(path_copy);
+ return (found == 3);
}
/*
@@ -177,17 +208,25 @@ sdb_is_kernel(const char *application)
uapi_boot_entry_t *
sdb_identify_next_kernel(const char *id)
{
+ uapi_kernel_entry_tokens_t id_match = { 0 };
+ const uapi_kernel_entry_tokens_t *match;
const char *machine_id;
+ uapi_boot_entry_t *result = NULL;
- if (id == NULL || !strcasecmp(id, "default")) {
- if (!(id = get_token_id()))
- return NULL;
+ if (id == NULL || !strcasecmp(id, "auto")) {
+ match = get_valid_kernel_entry_tokens();
+ } else {
+ uapi_kernel_entry_tokens_add(&id_match, id);
+ match = &id_match;
}
- if (!(machine_id = read_machine_id()))
- return NULL;
+ machine_id = read_machine_id();
+
+ if (machine_id != NULL)
+ result = uapi_find_boot_entry(match, machine_id);
- return uapi_find_boot_entry(id, machine_id);
+ uapi_kernel_entry_tokens_destroy(&id_match);
+ return result;
}
/*
diff --git a/src/uapi.c b/src/uapi.c
index a12ad21..acba37a 100644
--- a/src/uapi.c
+++ b/src/uapi.c
@@ -149,11 +149,10 @@ uapi_boot_entry_more_recent(const uapi_boot_entry_t *entry_a, const uapi_boot_en
*/
uapi_boot_entry_t *
uapi_find_matching_boot_entry(const char *dir_path,
- const char *entry_id, const char *machine_id, const char *architecture,
+ const uapi_kernel_entry_tokens_t *match, const char *machine_id, const char *architecture,
uapi_boot_entry_t **best_ret)
{
uapi_boot_entry_t *best = *best_ret;
- unsigned int entry_id_len = 0;
struct dirent *d;
DIR *dir;
@@ -163,9 +162,6 @@ uapi_find_matching_boot_entry(const char *dir_path,
return NULL;
}
- if (entry_id)
- entry_id_len = strlen(entry_id);
-
while ((d = readdir(dir)) != NULL) {
char config_path[PATH_MAX];
uapi_boot_entry_t *entry;
@@ -173,7 +169,7 @@ uapi_find_matching_boot_entry(const char *dir_path,
if (d->d_type != DT_REG)
continue;
- if (entry_id && strncmp(d->d_name, entry_id, entry_id_len))
+ if (match && !uapi_kernel_entry_tokens_match_filename(match, d->d_name))
continue;
snprintf(config_path, sizeof(config_path), "%s/%s", dir_path, d->d_name);
@@ -201,7 +197,7 @@ uapi_find_matching_boot_entry(const char *dir_path,
}
uapi_boot_entry_t *
-uapi_find_boot_entry(const char *id, const char *machine_id)
+uapi_find_boot_entry(const uapi_kernel_entry_tokens_t *match, const char *machine_id)
{
uapi_boot_entry_t *best = NULL;
struct utsname uts;
@@ -211,7 +207,7 @@ uapi_find_boot_entry(const char *id, const char *machine_id)
architecture = uts.machine;
return uapi_find_matching_boot_entry(UAPI_BOOT_DIRECTORY,
- id, machine_id, architecture,
+ match, machine_id, architecture,
&best);
}
@@ -227,6 +223,44 @@ uapi_boot_entry_free(uapi_boot_entry_t *ube)
free(ube);
}
+/*
+ * Manage list of valid entry-tokens
+ */
+void
+uapi_kernel_entry_tokens_add(uapi_kernel_entry_tokens_t *match, const char *id)
+{
+ if (id == NULL)
+ return;
+
+ if (match->count >= UAPI_MAX_ENTRY_TOKENS)
+ fatal("%s: too many tokens\n", __func__);
+
+ match->entry_token[match->count++] = strdup(id);
+}
+
+void
+uapi_kernel_entry_tokens_destroy(uapi_kernel_entry_tokens_t *match)
+{
+ while (match->count)
+ drop_string(&match->entry_token[--(match->count)]);
+}
+
+bool
+uapi_kernel_entry_tokens_match_filename(const uapi_kernel_entry_tokens_t *token_list, const char *filename)
+{
+ unsigned int i;
+
+ for (i = 0; i < token_list->count; ++i) {
+ const char *token = token_list->entry_token[i];
+ int len = strlen(token);
+
+ if (!strncmp(filename, token, len) && filename[len] == '-')
+ return true;
+ }
+
+ return false;
+}
+
/*
* Version comparison
*/
diff --git a/src/uapi.h b/src/uapi.h
index ba1147e..cc38395 100644
--- a/src/uapi.h
+++ b/src/uapi.h
@@ -35,9 +35,18 @@ struct uapi_boot_entry {
char * options;
};
+#define UAPI_MAX_ENTRY_TOKENS 8
+typedef struct uapi_kernel_entry_tokens {
+ unsigned int count;
+ char * entry_token[UAPI_MAX_ENTRY_TOKENS];
+} uapi_kernel_entry_tokens_t;
+
#define UAPI_BOOT_DIRECTORY "/boot/efi/loader/entries"
-extern uapi_boot_entry_t * uapi_find_boot_entry(const char *id, const char *machine_id);
+extern uapi_boot_entry_t * uapi_find_boot_entry(const uapi_kernel_entry_tokens_t *match, const char *machine_id);
extern void uapi_boot_entry_free(uapi_boot_entry_t *);
+extern void uapi_kernel_entry_tokens_add(uapi_kernel_entry_tokens_t *, const char *);
+extern void uapi_kernel_entry_tokens_destroy(uapi_kernel_entry_tokens_t *);
+extern bool uapi_kernel_entry_tokens_match_filename(const uapi_kernel_entry_tokens_t *, const char *filename);
#endif /* UAPI_H */
From 8a0d1e8050340034e4690123c205a8b98abd7d24 Mon Sep 17 00:00:00 2001
From: Olaf Kirch <okir@suse.com>
Date: Tue, 28 Nov 2023 10:46:20 +0100
Subject: [PATCH 11/13] Remove code that's been obsoleted by
uapi_kernel_entry_tokens stuff
Signed-off-by: Olaf Kirch <okir@suse.com>
---
src/sd-boot.c | 45 ---------------------------------------------
1 file changed, 45 deletions(-)
diff --git a/src/sd-boot.c b/src/sd-boot.c
index 8dc9bf1..3b72e37 100644
--- a/src/sd-boot.c
+++ b/src/sd-boot.c
@@ -127,51 +127,6 @@ get_valid_kernel_entry_tokens(void)
return &valid_tokens;
}
-static bool
-exists_efi_dir(const char *path)
-{
- DIR *d = NULL;
- char full_path[PATH_MAX];
-
- if (path == NULL)
- return false;
-
- snprintf(full_path, PATH_MAX, "/boot/efi/%s", path);
- if (!(d = opendir(full_path)))
- return false;
-
- closedir(d);
- return true;
-}
-
-static const char *
-get_token_id(void)
-{
- static const char *token_id = NULL;
- const char *id = NULL;
- const char *image_id = NULL;
- const char *machine_id = NULL;
-
- /* All IDs are optional (cannot be present), except machine_id */
- token_id = read_entry_token();
- id = read_os_release("ID");
- image_id = read_os_release("IMAGE_ID");
- if (!(machine_id = read_machine_id()))
- return NULL;
-
- /* The order is not correct, and it is using some heuristics
- * to find the correct prefix. Other tools like sdbootutil
- * seems to use parameters to decide */
- if (token_id == NULL && exists_efi_dir(id))
- token_id = id;
- if (token_id == NULL && exists_efi_dir(image_id))
- token_id = id;
- if (token_id == NULL && exists_efi_dir(machine_id))
- token_id = machine_id;
-
- return token_id;
-}
-
/*
* This should probably use UAPI boot entry logic as well
*/
From 07203a598a95a11afb4cf4a6f50bb92c7d4ae981 Mon Sep 17 00:00:00 2001
From: Olaf Kirch <okir@suse.com>
Date: Tue, 28 Nov 2023 14:01:40 +0100
Subject: [PATCH 12/13] Fix an issue with not being able to find an entry
referenced exactly by the boot id
Signed-off-by: Olaf Kirch <okir@suse.com>
---
src/sd-boot.c | 8 ++++++++
src/uapi.c | 31 ++++++++++++++++++++++++++++++-
src/uapi.h | 1 +
3 files changed, 39 insertions(+), 1 deletion(-)
diff --git a/src/sd-boot.c b/src/sd-boot.c
index 3b72e37..e3e0568 100644
--- a/src/sd-boot.c
+++ b/src/sd-boot.c
@@ -171,6 +171,13 @@ sdb_identify_next_kernel(const char *id)
if (id == NULL || !strcasecmp(id, "auto")) {
match = get_valid_kernel_entry_tokens();
} else {
+ /* Try to load the entry referenced _exactly_ by the
+ * given id. */
+ result = uapi_get_boot_entry(id);
+ if (result != NULL)
+ goto done;
+
+ /* No cigar, revert to a prefix based search */
uapi_kernel_entry_tokens_add(&id_match, id);
match = &id_match;
}
@@ -180,6 +187,7 @@ sdb_identify_next_kernel(const char *id)
if (machine_id != NULL)
result = uapi_find_boot_entry(match, machine_id);
+done:
uapi_kernel_entry_tokens_destroy(&id_match);
return result;
}
diff --git a/src/uapi.c b/src/uapi.c
index acba37a..f0db62a 100644
--- a/src/uapi.c
+++ b/src/uapi.c
@@ -24,6 +24,7 @@
#include <sys/param.h>
#include <sys/utsname.h>
#include <limits.h>
+#include <unistd.h>
#include <assert.h>
#include <ctype.h>
#include <errno.h>
@@ -196,6 +197,29 @@ uapi_find_matching_boot_entry(const char *dir_path,
return best;
}
+/*
+ * Get the exact boot entry identified by id.
+ * This is mainly for iterating over entries like
+ * for name in "/boot/efi/loader/entries/"*.conf; do
+ * pcr-oracle --boot-entry $(basename $name .conf) ...
+ * done
+ */
+uapi_boot_entry_t *
+uapi_get_boot_entry(const char *id)
+{
+ char path[PATH_MAX];
+
+ if (path_has_file_extension(id, ".conf"))
+ snprintf(path, sizeof(path), "%s/%s", UAPI_BOOT_DIRECTORY, id);
+ else
+ snprintf(path, sizeof(path), "%s/%s.conf", UAPI_BOOT_DIRECTORY, id);
+
+ if (access(path, R_OK) < 0)
+ return NULL;
+
+ return uapi_boot_entry_load(path);
+}
+
uapi_boot_entry_t *
uapi_find_boot_entry(const uapi_kernel_entry_tokens_t *match, const char *machine_id)
{
@@ -253,8 +277,13 @@ uapi_kernel_entry_tokens_match_filename(const uapi_kernel_entry_tokens_t *token_
for (i = 0; i < token_list->count; ++i) {
const char *token = token_list->entry_token[i];
int len = strlen(token);
+ char cc;
+
+ if (strncmp(filename, token, len))
+ continue;
- if (!strncmp(filename, token, len) && filename[len] == '-')
+ cc = filename[len];
+ if (cc == '\0' || cc == '-' || cc == '.')
return true;
}
diff --git a/src/uapi.h b/src/uapi.h
index cc38395..96ca7ed 100644
--- a/src/uapi.h
+++ b/src/uapi.h
@@ -43,6 +43,7 @@ typedef struct uapi_kernel_entry_tokens {
#define UAPI_BOOT_DIRECTORY "/boot/efi/loader/entries"
+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);
extern void uapi_boot_entry_free(uapi_boot_entry_t *);
extern void uapi_kernel_entry_tokens_add(uapi_kernel_entry_tokens_t *, const char *);
From 0db6dae5c065944506255b92033314c97b45e4e4 Mon Sep 17 00:00:00 2001
From: Olaf Kirch <okir@suse.com>
Date: Tue, 28 Nov 2023 14:04:43 +0100
Subject: [PATCH 13/13] Rename --next-kernel to --boot-entry
Signed-off-by: Olaf Kirch <okir@suse.com>
---
man/pcr-oracle.8.in | 4 ++--
src/efi-application.c | 4 ++--
src/eventlog.c | 22 +++++++++++-----------
src/eventlog.h | 2 +-
src/oracle.c | 26 +++++++++++++-------------
src/sd-boot.c | 2 +-
src/sd-boot.h | 2 +-
7 files changed, 31 insertions(+), 31 deletions(-)
diff --git a/man/pcr-oracle.8.in b/man/pcr-oracle.8.in
index 3682afa..86ac275 100644
--- a/man/pcr-oracle.8.in
+++ b/man/pcr-oracle.8.in
@@ -494,14 +494,14 @@ events (tracked in PCR9). In this case, it would be totally sufficient
to stop processing after grub loaded \fPgrub.cfg\fP from the EFI
System Partition.
.TP
-.BI --next-kernel " id
+.BI --boot-entry " id
In a systemd-boot environment, the values of PCR registers also depend on
the contents of the kernel and initrd image, as well as the kernel command line
options. After a kernel update or an initrd rebuild, these values will change.
So when predicting PCR values in this case, \fBpcr-oracle\fP needs to be
instructed to refer to the future kernel rather than the current one.
.IP
-This is what the \fB--next-kernel\fP option is for. It takes one argument, which
+This is what the \fB--boot-entry\fP option is for. It takes one argument, which
is either an ID (in the sense of systemd-boot IDs), or \fBauto\fP. When
the latter is given, \fBpcr-oracle\fP will make a best guess as to what
kernel image will be used on next boot.
diff --git a/src/efi-application.c b/src/efi-application.c
index 9d7e531..3e80083 100644
--- a/src/efi-application.c
+++ b/src/efi-application.c
@@ -291,8 +291,8 @@ __tpm_event_efi_bsa_rehash(const tpm_event_t *ev, const tpm_parsed_event_t *pars
}
/* The next boot can have a different kernel */
- if (sdb_is_kernel(evspec->efi_application) && ctx->next_kernel) {
- new_application = ctx->next_kernel->image_path;
+ if (sdb_is_kernel(evspec->efi_application) && ctx->boot_entry) {
+ new_application = ctx->boot_entry->image_path;
if (new_application) {
evspec_clone = *evspec;
evspec_clone.efi_application = strdup(new_application);
diff --git a/src/eventlog.c b/src/eventlog.c
index 3498790..4277d42 100644
--- a/src/eventlog.c
+++ b/src/eventlog.c
@@ -789,24 +789,24 @@ __tpm_event_systemd_describe(const tpm_parsed_event_t *parsed)
static const tpm_evdigest_t *
__tpm_event_systemd_rehash(const tpm_event_t *ev, const tpm_parsed_event_t *parsed, tpm_event_log_rehash_ctx_t *ctx)
{
- const uapi_boot_entry_t *next_kernel = ctx->next_kernel;
+ const uapi_boot_entry_t *boot_entry = ctx->boot_entry;
char initrd[2048];
char initrd_utf16[4096];
unsigned int len;
/* If no --next-kernel option was given, do not rehash anything */
- if (next_kernel == NULL)
+ if (boot_entry == NULL)
return tpm_event_get_digest(ev, ctx->algo);
- if (!next_kernel->image_path) {
+ if (!boot_entry->image_path) {
error("Unable to identify the next kernel\n");
return NULL;
}
- debug("Next boot entry expected from: %s %s\n", next_kernel->title, next_kernel->version? : "");
+ debug("Next boot entry expected from: %s %s\n", boot_entry->title, boot_entry->version? : "");
snprintf(initrd, sizeof(initrd), "initrd=%s %s",
- path_unix2dos(next_kernel->initrd_path),
- next_kernel->options? : "");
+ path_unix2dos(boot_entry->initrd_path),
+ boot_entry->options? : "");
len = (strlen(initrd) + 1) << 1;
assert(len <= sizeof(initrd_utf16));
@@ -863,20 +863,20 @@ __tpm_event_tag_initrd_describe(const tpm_parsed_event_t *parsed)
static const tpm_evdigest_t *
__tpm_event_tag_initrd_rehash(const tpm_event_t *ev, const tpm_parsed_event_t *parsed, tpm_event_log_rehash_ctx_t *ctx)
{
- const uapi_boot_entry_t *next_kernel = ctx->next_kernel;
+ const uapi_boot_entry_t *boot_entry = ctx->boot_entry;
/* If no --next-kernel option was given, do not rehash anything */
- if (next_kernel == NULL)
+ if (boot_entry == NULL)
return tpm_event_get_digest(ev, ctx->algo);
- if (!next_kernel->initrd_path) {
+ if (!boot_entry->initrd_path) {
/* Can this happen eg when going from a split kernel to a unified kernel? */
error("Unable to identify the next initrd\n");
return NULL;
}
- debug("Next boot entry expected from: %s %s\n", next_kernel->title, next_kernel->version? : "");
- return runtime_digest_efi_file(ctx->algo, next_kernel->initrd_path);
+ debug("Next boot entry expected from: %s %s\n", boot_entry->title, boot_entry->version? : "");
+ return runtime_digest_efi_file(ctx->algo, boot_entry->initrd_path);
}
/*
diff --git a/src/eventlog.h b/src/eventlog.h
index 65e5322..3741b58 100644
--- a/src/eventlog.h
+++ b/src/eventlog.h
@@ -202,7 +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 */
- uapi_boot_entry_t * next_kernel;
+ uapi_boot_entry_t * boot_entry;
} tpm_event_log_rehash_ctx_t;
#define GRUB_COMMAND_ARGV_MAX 32
diff --git a/src/oracle.c b/src/oracle.c
index 2cc53c1..1cafafc 100644
--- a/src/oracle.c
+++ b/src/oracle.c
@@ -59,7 +59,7 @@ struct predictor {
const char * initial_source;
const char * tpm_event_log_path;
- const char * next_kernel_id;
+ const char * boot_entry_id;
const char * algo;
const tpm_algo_info_t * algo_info;
@@ -100,7 +100,7 @@ enum {
OPT_POLICY_NAME,
OPT_POLICY_FORMAT,
OPT_TARGET_PLATFORM,
- OPT_NEXT_KERNEL,
+ OPT_BOOT_ENTRY,
};
static struct option options[] = {
@@ -117,7 +117,7 @@ static struct option options[] = {
{ "before", no_argument, 0, OPT_BEFORE },
{ "verify", required_argument, 0, OPT_VERIFY },
{ "use-pesign", no_argument, 0, OPT_USE_PESIGN },
- { "next-kernel", required_argument, 0, OPT_NEXT_KERNEL },
+ { "boot-entry", required_argument, 0, OPT_BOOT_ENTRY },
{ "create-testcase", required_argument, 0, OPT_CREATE_TESTCASE },
{ "replay-testcase", required_argument, 0, OPT_REPLAY_TESTCASE },
@@ -133,7 +133,7 @@ static struct option options[] = {
{ "policy-name", required_argument, 0, OPT_POLICY_NAME },
{ "policy-format", required_argument, 0, OPT_POLICY_FORMAT },
{ "target-platform", required_argument, 0, OPT_TARGET_PLATFORM },
- { "next-kernel", required_argument, 0, OPT_NEXT_KERNEL },
+ { "next-kernel", required_argument, 0, OPT_BOOT_ENTRY },
{ NULL }
};
@@ -256,7 +256,7 @@ static struct predictor *
predictor_new(const tpm_pcr_selection_t *pcr_selection, const char *source,
const char *tpm_eventlog_path,
const char *output_format,
- const char *next_kernel_id)
+ const char *boot_entry_id)
{
struct predictor *pred;
@@ -266,7 +266,7 @@ predictor_new(const tpm_pcr_selection_t *pcr_selection, const char *source,
pred = calloc(1, sizeof(*pred));
pred->pcr_mask = pcr_selection->pcr_mask;
pred->initial_source = source;
- pred->next_kernel_id = next_kernel_id;
+ pred->boot_entry_id = boot_entry_id;
pred->algo = pcr_selection->algo_info->openssl_name;
pred->algo_info = pcr_selection->algo_info;
@@ -662,9 +662,9 @@ 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->next_kernel_id != NULL
- && !(rehash_ctx.next_kernel = sdb_identify_next_kernel(pred->next_kernel_id)))
- fatal("unable to identify next kernel \"%s\"\n", pred->next_kernel_id);
+ 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);
for (ev = pred->event_log; ev; ev = ev->next) {
tpm_evdigest_t *pcr;
@@ -1036,7 +1036,7 @@ main(int argc, char **argv)
char *opt_rsa_bits = NULL;
char *opt_policy_name = NULL;
char *opt_target_platform = NULL;
- char *opt_next_kernel = NULL;
+ char *opt_boot_entry = NULL;
const target_platform_t *target;
unsigned int action_flags = 0;
unsigned int rsa_bits = 2048;
@@ -1071,8 +1071,8 @@ main(int argc, char **argv)
case OPT_USE_PESIGN:
opt_use_pesign = 1;
break;
- case OPT_NEXT_KERNEL:
- opt_next_kernel = optarg;
+ case OPT_BOOT_ENTRY:
+ opt_boot_entry = optarg;
break;
case OPT_STOP_EVENT:
opt_stop_event = optarg;
@@ -1315,7 +1315,7 @@ main(int argc, char **argv)
fatal("BUG: action %u should have parsed a PCR selection argument", action);
pred = predictor_new(pcr_selection, opt_from, opt_eventlog_path,
- opt_output_format, opt_next_kernel);
+ opt_output_format, opt_boot_entry);
if (opt_stop_event)
predictor_set_stop_event(pred, opt_stop_event, !opt_stop_before);
diff --git a/src/sd-boot.c b/src/sd-boot.c
index e3e0568..ad13617 100644
--- a/src/sd-boot.c
+++ b/src/sd-boot.c
@@ -161,7 +161,7 @@ sdb_is_kernel(const char *application)
* Identify the next kernel and initrd given an ID
*/
uapi_boot_entry_t *
-sdb_identify_next_kernel(const char *id)
+sdb_identify_boot_entry(const char *id)
{
uapi_kernel_entry_tokens_t id_match = { 0 };
const uapi_kernel_entry_tokens_t *match;
diff --git a/src/sd-boot.h b/src/sd-boot.h
index 2b11dc1..0472320 100644
--- a/src/sd-boot.h
+++ b/src/sd-boot.h
@@ -42,7 +42,7 @@ typedef struct sdb_entry_list {
sdb_entry_data_t entries[SDB_MAX_ENTRIES];
} sdb_entry_list_t;
-extern uapi_boot_entry_t * sdb_identify_next_kernel(const char *id);
+extern uapi_boot_entry_t * sdb_identify_boot_entry(const char *id);
extern bool sdb_is_kernel(const char *application);
/* This will have to update the systemd json file, and add a new entry. */