From 9d947d0a2afbbf5767e2fc5c82b9e21c20c41120 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 3 Jul 2026 17:28:45 +0200 Subject: [PATCH] basic: update in_first_boot() to return an error This commit tweaks the in_first_boot() code to make it a proper shared helper. It tweaks the comments about the caching policy. This is important because while this is simialr to `in_initrd()` there is a suble difference: we never cache the result of access() because other parts of systemd will use this file to signal if anything about firstboot changes. This also tweaks it to return an int instead of a bool. So any error is returned as -errno. This allows other parts of systemd (like the random-seed) that need to make decisions about "unknown" first-boot state. This also means that the consumers need to get updated and we can now also use the new helper in random-seed-tool.c and have only a single helper to check for first-boot. --- src/basic/initrd-util.c | 34 +++++++++++++++--------------- src/basic/initrd-util.h | 2 +- src/random-seed/random-seed-tool.c | 5 +++-- src/shared/condition.c | 2 +- src/shared/creds-util.c | 5 ++++- 5 files changed, 26 insertions(+), 22 deletions(-) diff --git a/src/basic/initrd-util.c b/src/basic/initrd-util.c index fc497f59f5e..6c273c2e8a4 100644 --- a/src/basic/initrd-util.c +++ b/src/basic/initrd-util.c @@ -1,13 +1,11 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ -#include #include #include "env-util.h" #include "errno-util.h" #include "initrd-util.h" #include "log.h" -#include "parse-util.h" static int saved_in_initrd = -1; @@ -41,24 +39,26 @@ void in_initrd_force(bool value) { saved_in_initrd = value; } -bool in_first_boot(void) { - static int first_boot = -1; +int in_first_boot(void) { + static int first_boot_env_parse_cached = -1; int r; - if (first_boot >= 0) - return first_boot; + if (first_boot_env_parse_cached >= 0) + return first_boot_env_parse_cached; - const char *e = secure_getenv("SYSTEMD_FIRST_BOOT"); - if (e) { - r = parse_boolean(e); - if (r < 0) - log_debug_errno(r, "Failed to parse $SYSTEMD_FIRST_BOOT, ignoring: %m"); - else - return (first_boot = r); - } + r = secure_getenv_bool("SYSTEMD_FIRST_BOOT"); + if (r >= 0) + return (first_boot_env_parse_cached = r); + if (r != -ENXIO) + log_debug_errno(r, "Failed to parse $SYSTEMD_FIRST_BOOT, ignoring: %m"); + /* This is not cached and must *never* be cached, other parts of systemd write it to signal + * an update to the first-boot state. */ r = RET_NERRNO(access("/run/systemd/first-boot", F_OK)); - if (r < 0 && r != -ENOENT) - log_debug_errno(r, "Failed to check if /run/systemd/first-boot exists, assuming no: %m"); - return r >= 0; + if (r >= 0) + return true; + if (r == -ENOENT) + return false; + + return log_debug_errno(r, "Failed to check /run/systemd/first-boot: %m"); } diff --git a/src/basic/initrd-util.h b/src/basic/initrd-util.h index ec55ec34028..f83b5c9d5d0 100644 --- a/src/basic/initrd-util.h +++ b/src/basic/initrd-util.h @@ -6,4 +6,4 @@ bool in_initrd(void); void in_initrd_force(bool value); -bool in_first_boot(void); +int in_first_boot(void); diff --git a/src/random-seed/random-seed-tool.c b/src/random-seed/random-seed-tool.c index 289291761f0..9f9439c8c57 100644 --- a/src/random-seed/random-seed-tool.c +++ b/src/random-seed/random-seed-tool.c @@ -15,6 +15,7 @@ #include "fd-util.h" #include "format-table.h" #include "fs-util.h" +#include "initrd-util.h" #include "io-util.h" #include "log.h" #include "main-func.h" @@ -88,8 +89,8 @@ static CreditEntropy may_credit(int seed_fd) { /* Don't credit the random seed if we are in first-boot mode, because we are supposed to start from * scratch. This is a safety precaution for cases where people ship "golden" images with empty * /etc but populated /var that contains a random seed. */ - r = RET_NERRNO(access("/run/systemd/first-boot", F_OK)); - if (r == -ENOENT) + r = in_first_boot(); + if (r == 0) /* All is good, we are not in first-boot mode. */ return CREDIT_ENTROPY_YES_PLEASE; if (r < 0) { diff --git a/src/shared/condition.c b/src/shared/condition.c index be2754c15eb..d879e24d9ef 100644 --- a/src/shared/condition.c +++ b/src/shared/condition.c @@ -974,7 +974,7 @@ static int condition_test_first_boot(Condition *c, char **env) { if (r < 0) return r; - return in_first_boot() == r; + return (in_first_boot() > 0) == r; } static int condition_test_environment(Condition *c, char **env) { diff --git a/src/shared/creds-util.c b/src/shared/creds-util.c index a1173714825..d646c617f41 100644 --- a/src/shared/creds-util.c +++ b/src/shared/creds-util.c @@ -1277,7 +1277,10 @@ static int check_null_key_policy(CredentialFlags flags) { * exists yet); the decision itself is made in credential_boot_policy_accepts_null(). */ CredentialBootPolicy policy = query_credential_boot_policy(); - bool first_boot = in_first_boot(), have_tpm2 = efi_has_tpm2(), secure_boot = is_efi_secure_boot(); + + bool have_tpm2 = efi_has_tpm2(), secure_boot = is_efi_secure_boot(); + /* in_first_boot() can return <0 on error: use the safe default in this case (not-first-boot). */ + bool first_boot = in_first_boot() > 0; if (!credential_boot_policy_accepts_null(policy, first_boot, have_tpm2, secure_boot)) return log_error_errno(SYNTHETIC_ERRNO(EHWPOISON), -- 2.47.3