summaryrefslogtreecommitdiffstats
path: root/lib/libutil/pw_util.c
diff options
context:
space:
mode:
authordillon <dillon@FreeBSD.org>1998-12-13 01:36:45 +0000
committerdillon <dillon@FreeBSD.org>1998-12-13 01:36:45 +0000
commit99ae894df3a3aa57ec1410174bbf65f764fbd9b5 (patch)
tree53a55f230731ff83dc38852a9be45279e2744374 /lib/libutil/pw_util.c
parent9bdc2c6395f2a14cb3f64472024d64f663780251 (diff)
downloadFreeBSD-src-99ae894df3a3aa57ec1410174bbf65f764fbd9b5.zip
FreeBSD-src-99ae894df3a3aa57ec1410174bbf65f764fbd9b5.tar.gz
Handle the race condition where vipw may lock a password file which has
just been replaced. After our lock succeeds we check if st_nlink is 0 and if it is we close the descriptor and retry our open/lock sequence.
Diffstat (limited to 'lib/libutil/pw_util.c')
-rw-r--r--lib/libutil/pw_util.c28
1 files changed, 22 insertions, 6 deletions
diff --git a/lib/libutil/pw_util.c b/lib/libutil/pw_util.c
index 8a74fc01..93bf4e1 100644
--- a/lib/libutil/pw_util.c
+++ b/lib/libutil/pw_util.c
@@ -36,7 +36,7 @@
static const char sccsid[] = "@(#)pw_util.c 8.3 (Berkeley) 4/2/94";
#endif
static const char rcsid[] =
- "$Id: pw_util.c,v 1.10 1998/10/13 14:52:33 des Exp $";
+ "$Id: pw_util.c,v 1.11 1998/10/20 11:34:11 des Exp $";
#endif /* not lint */
/*
@@ -115,11 +115,27 @@ pw_lock()
* that users can't get at the encrypted passwords while editing.
* Open should allow flock'ing the file; see 4.4BSD. XXX
*/
- lockfd = open(_PATH_MASTERPASSWD, O_RDONLY, 0);
- if (lockfd < 0 || fcntl(lockfd, F_SETFD, 1) == -1)
- err(1, "%s", _PATH_MASTERPASSWD);
- if (flock(lockfd, LOCK_EX|LOCK_NB))
- errx(1, "the password db file is busy");
+ for (;;) {
+ struct stat st;
+
+ lockfd = open(_PATH_MASTERPASSWD, O_RDONLY, 0);
+ if (lockfd < 0 || fcntl(lockfd, F_SETFD, 1) == -1)
+ err(1, "%s", _PATH_MASTERPASSWD);
+ if (flock(lockfd, LOCK_EX|LOCK_NB))
+ errx(1, "the password db file is busy");
+
+ /*
+ * If the password file was replaced while we were trying to
+ * get the lock, our hardlink count will be 0 and we have to
+ * close and retry.
+ */
+ if (fstat(lockfd, &st) < 0)
+ errx(1, "fstat() failed");
+ if (st.st_nlink != 0)
+ break;
+ close(lockfd);
+ lockfd = -1;
+ }
return (lockfd);
}
OpenPOWER on IntegriCloud