[systemd-commits] src/firstboot src/shared src/sysusers

Lennart Poettering lennart at kemper.freedesktop.org
Mon Jul 7 10:01:05 PDT 2014


 src/firstboot/firstboot.c |    9 ++++++++-
 src/shared/util.c         |   40 ++++++++++++++++++++++++++++++++++++++++
 src/shared/util.h         |    2 ++
 src/sysusers/sysusers.c   |   38 +-------------------------------------
 4 files changed, 51 insertions(+), 38 deletions(-)

New commits:
commit 45035609fcfc3fe09324988c4929a3c147171c23
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Jul 7 18:57:09 2014 +0200

    firstboot: follow lock protocol when changing /etc/shadow

diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c
index 57173a5..6abffc5 100644
--- a/src/firstboot/firstboot.c
+++ b/src/firstboot/firstboot.c
@@ -530,7 +530,6 @@ static int write_root_shadow(const char *path, const struct spwd *p) {
         assert(path);
         assert(p);
 
-        mkdir_parents(path, 0755);
         RUN_WITH_UMASK(0777)
                 f = fopen(path, "wex");
         if (!f)
@@ -560,6 +559,8 @@ static int process_root_password(void) {
                 .sp_expire = -1,
                 .sp_flag = (unsigned long) -1, /* this appears to be what everybody does ... */
         };
+
+        _cleanup_close_ int lock = -1;
         char salt[3+16+1+1];
         uint8_t raw[16];
         unsigned i;
@@ -572,6 +573,12 @@ static int process_root_password(void) {
         if (faccessat(AT_FDCWD, etc_shadow, F_OK, AT_SYMLINK_NOFOLLOW) >= 0)
                 return 0;
 
+        mkdir_parents(etc_shadow, 0755);
+
+        lock = take_password_lock(arg_root);
+        if (lock < 0)
+                return lock;
+
         if (arg_copy_root_password && arg_root) {
                 struct spwd *p;
 
diff --git a/src/shared/util.c b/src/shared/util.c
index bef8730..88511b6 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -6823,3 +6823,43 @@ bool is_localhost(const char *hostname) {
                endswith(hostname, ".localdomain") ||
                endswith(hostname, ".localdomain.");
 }
+
+int take_password_lock(const char *root) {
+
+        struct flock flock = {
+                .l_type = F_WRLCK,
+                .l_whence = SEEK_SET,
+                .l_start = 0,
+                .l_len = 0,
+        };
+
+        const char *path;
+        int fd, r;
+
+        /* This is roughly the same as lckpwdf(), but not as awful. We
+         * don't want to use alarm() and signals, hence we implement
+         * our own trivial version of this.
+         *
+         * Note that shadow-utils also takes per-database locks in
+         * addition to lckpwdf(). However, we don't given that they
+         * are redundant as they they invoke lckpwdf() first and keep
+         * it during everything they do. The per-database locks are
+         * awfully racy, and thus we just won't do them. */
+
+        if (root)
+                path = strappenda(root, "/etc/.pwd.lock");
+        else
+                path = "/etc/.pwd.lock";
+
+        fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0600);
+        if (fd < 0)
+                return -errno;
+
+        r = fcntl(fd, F_SETLKW, &flock);
+        if (r < 0) {
+                safe_close(fd);
+                return -errno;
+        }
+
+        return fd;
+}
diff --git a/src/shared/util.h b/src/shared/util.h
index 7c9842b..fb852d6 100644
--- a/src/shared/util.h
+++ b/src/shared/util.h
@@ -964,3 +964,5 @@ char *tempfn_xxxxxx(const char *p);
 char *tempfn_random(const char *p);
 
 bool is_localhost(const char *hostname);
+
+int take_password_lock(const char *root);
diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c
index c0af693..1765f31 100644
--- a/src/sysusers/sysusers.c
+++ b/src/sysusers/sysusers.c
@@ -1379,42 +1379,6 @@ static int read_config_file(const char *fn, bool ignore_enoent) {
         return r;
 }
 
-static int take_lock(void) {
-
-        struct flock flock = {
-                .l_type = F_WRLCK,
-                .l_whence = SEEK_SET,
-                .l_start = 0,
-                .l_len = 0,
-        };
-
-        const char *path;
-        int fd, r;
-
-        /* This is roughly the same as lckpwdf(), but not as awful. We
-         * don't want to use alarm() and signals, hence we implement
-         * our own trivial version of this.
-         *
-         * Note that shadow-utils also takes per-database locks in
-         * addition to lckpwdf(). However, we don't given that they
-         * are redundant as they they invoke lckpwdf() first and keep
-         * it during everything they do. The per-database locks are
-         * awfully racy, and thus we just won't do them. */
-
-        path = fix_root("/etc/.pwd.lock");
-        fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0600);
-        if (fd < 0)
-                return -errno;
-
-        r = fcntl(fd, F_SETLKW, &flock);
-        if (r < 0) {
-                safe_close(fd);
-                return -errno;
-        }
-
-        return fd;
-}
-
 static void free_database(Hashmap *by_name, Hashmap *by_id) {
         char *name;
 
@@ -1548,7 +1512,7 @@ int main(int argc, char *argv[]) {
         if (r < 0)
                 goto finish;
 
-        lock = take_lock();
+        lock = take_password_lock(arg_root);
         if (lock < 0) {
                 log_error("Failed to take lock: %s", strerror(-lock));
                 goto finish;



More information about the systemd-commits mailing list