bless-boot: skip gracefully on kexec

If KExecsCount > 0 then do not attempt to mark a UKI, as the stub (and also
any addon and the bootloader) will not have been exercised, so there's no
guaranteed a full reboot with the same image will actually work.

Fixes https://github.com/systemd/systemd/issues/43738
This commit is contained in:
Luca Boccassi
2026-09-22 21:25:20 +02:00
parent f0f521c147
commit 06c2dfa73c
3 changed files with 43 additions and 0 deletions
+33
View File
@@ -3,6 +3,7 @@
#include <unistd.h>
#include "sd-json.h"
#include "sd-varlink.h"
#include "alloc-util.h"
#include "build.h"
@@ -20,6 +21,7 @@
#include "string-util.h"
#include "strv.h"
#include "sync-util.h"
#include "varlink-util.h"
#include "verbs.h"
#include "virt.h"
@@ -443,6 +445,8 @@ VERB_FULL(verb_set, "indeterminate", NULL, VERB_ANY, 1, 0, STATUS_INDETERMINATE,
"Undo any marking as good or bad");
static int verb_set(int argc, char *argv[], uintptr_t data, void *userdata) {
_cleanup_free_ char *path = NULL, *prefix = NULL, *suffix = NULL, *good = NULL, *bad = NULL;
_cleanup_(sd_varlink_unrefp) sd_varlink *link = NULL;
sd_json_variant *reply = NULL;
const char *target = NULL, *source1 = NULL, *source2 = NULL; /* avoid false maybe-uninitialized warning */
uint64_t left, done;
Status status = data;
@@ -454,6 +458,35 @@ static int verb_set(int argc, char *argv[], uintptr_t data, void *userdata) {
if (r < 0)
return r;
/* kexec doesn't go through the EFI loaders, so we shouldn't try to mark an image as good/bad.
* E.g.: booting the kernel+initrd might work, but the EFI stub might not, and we wouldn't notice */
r = sd_varlink_connect_address(&link, "/run/systemd/io.systemd.Manager");
if (r < 0)
return log_error_errno(r, "Failed to connect to service manager: %m");
r = varlink_call_and_log(link, "io.systemd.Manager.Describe", /* parameters= */ NULL, &reply);
if (r < 0)
return r;
static const sd_json_dispatch_field dispatch_table[] = {
{ "KExecCount", SD_JSON_VARIANT_UNSIGNED, sd_json_dispatch_uint64, 0, 0 },
{},
};
uint64_t kexec_count = 0;
r = sd_json_dispatch(
sd_json_variant_by_key(reply, "runtime"),
dispatch_table,
SD_JSON_LOG|SD_JSON_ALLOW_EXTENSIONS,
&kexec_count);
if (r < 0)
return r;
if (kexec_count > 0) {
log_info("System was booted via kexec, skipping boot entry marking.");
return 0;
}
r = acquire_boot_count_path(&path, &prefix, &left, &done, &suffix);
if (r == -EUNATCH) /* acquire_boot_count_path() won't log on its own for this specific error */
return log_error_errno(r, "Not booted with boot counting in effect.");