diff options
author | dillon <dillon@FreeBSD.org> | 1998-12-13 01:53:50 +0000 |
---|---|---|
committer | dillon <dillon@FreeBSD.org> | 1998-12-13 01:53:50 +0000 |
commit | 4db40135ef077cff04415e111e2356591a49e08d (patch) | |
tree | 67c8973c05862bdcb47322c7b5bfa9289c36e77a /usr.sbin/pwd_mkdb | |
parent | 3fa521a2d22918cde2e1652bcc39d746469720ab (diff) | |
download | FreeBSD-src-4db40135ef077cff04415e111e2356591a49e08d.zip FreeBSD-src-4db40135ef077cff04415e111e2356591a49e08d.tar.gz |
PR: bin/3478
Have pwd_mkdb lock the source file while rebuilding the database. When
called by programs such as vipw, the source file is a temporary file and
this does not conflict with the lock on /etc/master.passwd already held
by vipw. When run manually, however, master.passwd is typically specified
as the argument and the locking prevents other programs from messing with
master.passwd during the database rebuild.
Also pwd_mkdb uses a blocking exclusive lock as it may be called from
a script. The -N option was added to cause pwd_mkdb to get the lock
non-blocking and exit with an error if the attempt fails, again useful
for scripts.
Diffstat (limited to 'usr.sbin/pwd_mkdb')
-rw-r--r-- | usr.sbin/pwd_mkdb/pwd_mkdb.8 | 7 | ||||
-rw-r--r-- | usr.sbin/pwd_mkdb/pwd_mkdb.c | 42 |
2 files changed, 43 insertions, 6 deletions
diff --git a/usr.sbin/pwd_mkdb/pwd_mkdb.8 b/usr.sbin/pwd_mkdb/pwd_mkdb.8 index 54abc76..7beecd7 100644 --- a/usr.sbin/pwd_mkdb/pwd_mkdb.8 +++ b/usr.sbin/pwd_mkdb/pwd_mkdb.8 @@ -40,6 +40,7 @@ .Sh SYNOPSIS .Nm pwd_mkdb .Op Fl C +.Op Fl N .Op Fl p .Op Fl d Ar directory .Op Fl s Ar cachesize @@ -67,6 +68,12 @@ The options are as follows: .It Fl C Check if the password file is in the correct format. Do not change, add, or remove any files. +.It Fl N +Tell +.Nm Pwd_mkdb +to exit with an error if it cannot obtain a lock on the file. By default, +we block waiting for a lock on the source file. The lock is held through +the rebuilding of the database. .It Fl p Create a Version 7 style password file and install it into .Pa /etc/passwd . diff --git a/usr.sbin/pwd_mkdb/pwd_mkdb.c b/usr.sbin/pwd_mkdb/pwd_mkdb.c index 9df6680..4c5a518 100644 --- a/usr.sbin/pwd_mkdb/pwd_mkdb.c +++ b/usr.sbin/pwd_mkdb/pwd_mkdb.c @@ -42,7 +42,7 @@ static const char copyright[] = static char sccsid[] = "@(#)pwd_mkdb.c 8.5 (Berkeley) 4/20/94"; #endif static const char rcsid[] = - "$Id: pwd_mkdb.c,v 1.27 1998/09/29 20:01:21 dt Exp $"; + "$Id: pwd_mkdb.c,v 1.28 1998/12/12 16:08:41 foxfair Exp $"; #endif /* not lint */ #include <sys/param.h> @@ -109,6 +109,7 @@ main(argc, argv) char *username; u_int method, methoduid; int Cflag; + int nblock = 0; Cflag = 0; strcpy(prefix, _PATH_PWD); @@ -133,6 +134,9 @@ main(argc, argv) break; case 'v': /* backward compatible */ break; + case 'N': /* do not wait for lock */ + nblock = LOCK_NB; + break; default: usage(); } @@ -158,9 +162,30 @@ main(argc, argv) (void)umask(0); pname = *argv; - /* Open the original password file */ - if (!(fp = fopen(pname, "r"))) - error(pname); + + /* + * Open and lock the original password file. We have to check + * the hardlink count after we get the lock to handle any potential + * unlink/rename race. + * + * This lock is necessary when someone runs pwd_mkdb manually, directly + * on master.passwd, to handle the case where a user might try to + * change his password while pwd_mkdb is running. + */ + for (;;) { + struct stat st; + + if (!(fp = fopen(pname, "r"))) + error(pname); + if (flock(fileno(fp), LOCK_EX|nblock) < 0) + error("flock"); + if (fstat(fileno(fp), &st) < 0) + error(pname); + if (st.st_nlink != 0) + break; + fclose(fp); + fp = NULL; + } /* check only if password database is valid */ if (Cflag) { @@ -431,8 +456,6 @@ main(argc, argv) /* Set master.passwd permissions, in case caller forgot. */ (void)fchmod(fileno(fp), S_IRUSR|S_IWUSR); - if (fclose(fp) == EOF) - error("close fp"); /* Install as the real password files. */ (void)snprintf(buf, sizeof(buf), "%s/%s.tmp", prefix, _MP_DB); @@ -454,6 +477,13 @@ main(argc, argv) */ (void)snprintf(buf, sizeof(buf), "%s/%s", prefix, _MASTERPASSWD); mv(pname, buf); + + /* + * Close locked password file after rename() + */ + if (fclose(fp) == EOF) + error("close fp"); + exit(0); } |