summaryrefslogtreecommitdiffstats
path: root/usr.sbin/pwd_mkdb
diff options
context:
space:
mode:
authordillon <dillon@FreeBSD.org>1998-12-13 01:53:50 +0000
committerdillon <dillon@FreeBSD.org>1998-12-13 01:53:50 +0000
commit4db40135ef077cff04415e111e2356591a49e08d (patch)
tree67c8973c05862bdcb47322c7b5bfa9289c36e77a /usr.sbin/pwd_mkdb
parent3fa521a2d22918cde2e1652bcc39d746469720ab (diff)
downloadFreeBSD-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.87
-rw-r--r--usr.sbin/pwd_mkdb/pwd_mkdb.c42
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);
}
OpenPOWER on IntegriCloud