summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2014-07-07 18:57:09 +0200
committerLennart Poettering <lennart@poettering.net>2014-07-07 18:57:09 +0200
commit45035609fcfc3fe09324988c4929a3c147171c23 (patch)
tree17968a9f24515cef3f744eda4cb933778029f2ce
parent30f10abf42f9e4d251a0b45b07812aafdef6be7c (diff)
firstboot: follow lock protocol when changing /etc/shadow
-rw-r--r--src/firstboot/firstboot.c9
-rw-r--r--src/shared/util.c40
-rw-r--r--src/shared/util.h2
-rw-r--r--src/sysusers/sysusers.c38
4 files changed, 51 insertions, 38 deletions
diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c
index 57173a5669..6abffc528f 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 bef87304e6..88511b69c0 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 7c9842b3e6..fb852d6973 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 c0af69300a..1765f31a3a 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;