diff options
author | Lennart Poettering <lennart@poettering.net> | 2014-07-07 18:57:09 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2014-07-07 18:57:09 +0200 |
commit | 45035609fcfc3fe09324988c4929a3c147171c23 (patch) | |
tree | 17968a9f24515cef3f744eda4cb933778029f2ce /src/shared/util.c | |
parent | 30f10abf42f9e4d251a0b45b07812aafdef6be7c (diff) |
firstboot: follow lock protocol when changing /etc/shadow
Diffstat (limited to 'src/shared/util.c')
-rw-r--r-- | src/shared/util.c | 40 |
1 files changed, 40 insertions, 0 deletions
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; +} |