]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sysusers: make sp_lstchg shadow field reproducible
authorJohannes Schauer Marin Rodrigues <josch@mister-muffin.de>
Thu, 1 Sep 2022 09:49:19 +0000 (11:49 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 2 Sep 2022 05:17:25 +0000 (07:17 +0200)
If the environment variable SOURCE_DATE_EPOCH is set, use its value
instead of the current time.

docs/ENVIRONMENT.md
src/basic/env-util.c
src/basic/env-util.h
src/sysusers/sysusers.c

index 62e064e12bc6a1452f4d29830e813858586a7003..e229edc2aac9109a15e279ff6d73867e7ac1fab1 100644 (file)
@@ -310,6 +310,16 @@ All tools:
   subvolumes if the backing filesystem supports them. If set to `0`, these
   lines will always create directories.
 
+`systemd-sysusers`
+
+* `SOURCE_DATE_EPOCH` — if unset, the field of the date of last password change
+  in `/etc/shadow` will be the number of days from Jan 1, 1970 00:00 UTC until
+  today. If SOURCE_DATE_EPOCH is set to a valid UNIX epoch value in seconds,
+  then the field will be the number of days until that time instead. This is to
+  support creating bit-by-bit reproducible system images by choosing a
+  reproducible value for the field of the date of last password change in
+  `/etc/shadow`. See: https://reproducible-builds.org/specs/source-date-epoch/
+
 `systemd-sysv-generator`:
 
 * `$SYSTEMD_SYSVINIT_PATH` — Controls where `systemd-sysv-generator` looks for
index 62914f15878e516ce5a9f5d6c3b83cc453b3f577..55ac11a5124605eec6e1a536b33394dc4a7345b1 100644 (file)
@@ -776,6 +776,18 @@ int getenv_bool_secure(const char *p) {
         return parse_boolean(e);
 }
 
+int getenv_uint64_secure(const char *p, uint64_t *ret) {
+        const char *e;
+
+        assert(p);
+
+        e = secure_getenv(p);
+        if (!e)
+                return -ENXIO;
+
+        return safe_atou64(e, ret);
+}
+
 int set_unset_env(const char *name, const char *value, bool overwrite) {
         assert(name);
 
index 2bf0603f2127b1c46d8a25d43649fc4beda54bfe..b927ac7a4883f345868c47bc0aecabb2e6a0e046 100644 (file)
@@ -57,6 +57,8 @@ char *strv_env_pairs_get(char **l, const char *name) _pure_;
 int getenv_bool(const char *p);
 int getenv_bool_secure(const char *p);
 
+int getenv_uint64_secure(const char *p, uint64_t *ret);
+
 /* Like setenv, but calls unsetenv if value == NULL. */
 int set_unset_env(const char *name, const char *value, bool overwrite);
 
index 8b2c242e7cfe7364f5677bc1d56da98602c9ee1b..491e4a0ea284d6a16b69a370bbc92a30969c1b2b 100644 (file)
@@ -10,6 +10,7 @@
 #include "creds-util.h"
 #include "def.h"
 #include "dissect-image.h"
+#include "env-util.h"
 #include "fd-util.h"
 #include "fileio.h"
 #include "format-util.h"
@@ -525,6 +526,18 @@ static int write_temporary_passwd(const char *passwd_path, FILE **tmpfile, char
         return 0;
 }
 
+static usec_t epoch_or_now(void) {
+        uint64_t epoch;
+
+        if (getenv_uint64_secure("SOURCE_DATE_EPOCH", &epoch) >= 0) {
+                if (epoch > UINT64_MAX/USEC_PER_SEC) /* Overflow check */
+                        return USEC_INFINITY;
+                return (usec_t) epoch * USEC_PER_SEC;
+        }
+
+        return now(CLOCK_REALTIME);
+}
+
 static int write_temporary_shadow(const char *shadow_path, FILE **tmpfile, char **tmpfile_path) {
         _cleanup_fclose_ FILE *original = NULL, *shadow = NULL;
         _cleanup_(unlink_and_freep) char *shadow_tmp = NULL;
@@ -545,7 +558,7 @@ static int write_temporary_shadow(const char *shadow_path, FILE **tmpfile, char
         if (r < 0)
                 return log_debug_errno(r, "Failed to open temporary copy of %s: %m", shadow_path);
 
-        lstchg = (long) (now(CLOCK_REALTIME) / USEC_PER_DAY);
+        lstchg = (long) (epoch_or_now() / USEC_PER_DAY);
 
         original = fopen(shadow_path, "re");
         if (original) {