]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
basic: update in_first_boot() to return an error 42555/head
authorMichael Vogt <michael@amutable.com>
Fri, 3 Jul 2026 15:28:45 +0000 (17:28 +0200)
committerMichael Vogt <michael@amutable.com>
Thu, 9 Jul 2026 14:48:26 +0000 (16:48 +0200)
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
src/basic/initrd-util.h
src/random-seed/random-seed-tool.c
src/shared/condition.c
src/shared/creds-util.c

index fc497f59f5ee9a0cc35f8805d8b7c1487c60d58b..6c273c2e8a4b2f0f1b2a6c986b8b0336c8a49261 100644 (file)
@@ -1,13 +1,11 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 
-#include <stdlib.h>
 #include <unistd.h>
 
 #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");
 }
index ec55ec34028a9fc95b712ad8e3577a5708c10bbe..f83b5c9d5d039a45ba07184566564f7696e27697 100644 (file)
@@ -6,4 +6,4 @@
 bool in_initrd(void);
 void in_initrd_force(bool value);
 
-bool in_first_boot(void);
+int in_first_boot(void);
index 289291761f0297b3de95c7138acc8b110320136f..9f9439c8c5779efe2308f48c325b96588b3414b7 100644 (file)
@@ -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) {
index be2754c15eb0b886d2406f1eebaa43ac81c715ee..d879e24d9ef5a9edbe5d71cc00ab78d7488f9ef9 100644 (file)
@@ -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) {
index a11737148251835ed86eb7dce519cf2dba268249..d646c617f412a4a7b049fccf66938c818f6748b3 100644 (file)
@@ -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),