Date: Thu, 26 Dec 1996 16:50:34 -0800 (PST) From: Matthew Dillon <dillon@backplane.com> To: FreeBSD-gnats-submit@freebsd.org Subject: bin/2291: Race condition in pw_lock (vipw, chpass, etc....) Message-ID: <199612270050.QAA09552@apollo.backplane.com> Resent-Message-ID: <199612270100.RAA21929@freefall.freebsd.org>
index | next in thread | raw e-mail
>Number: 2291
>Category: bin
>Synopsis: race condition in /etc/master.passwd locking code pw_lock()
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: freebsd-bugs
>State: open
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Thu Dec 26 17:00:01 PST 1996
>Last-Modified:
>Originator: Matthew Dillon
>Organization:
>Release: FreeBSD 2.1-STABLE i386
>Environment:
pentium-pro 200 / SCSI (irrelevent)
>Description:
In /usr/src/usr.sbin/vipw/pw_util.c, in the procedure
pw_lock():
int
pw_lock()
{
/*
* If the master password file doesn't exist, the system is hosed.
* Might as well try to build one. Set the close-on-exec bit so
* 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");
return (lockfd);
}
There is a race condition between the open() call and the flock()
call whereby one program may get access to the master.passwd file,
create a temporary-file copy, and rename() over and the second
program winds up with a valid lock to a file descriptor to a
now-unlinked file.
>How-To-Repeat:
>Fix:
The fix is simple. After you have obtained the exclusive lock
on the file, you must do an fstat() on the file descriptor and
check st_nlink. If st_nlink is 0, someone else renamed the file
out from under you and you must close your descriptor and loop
to try again.
This fix presumes that there are no other hardlinks to master.passwd.
--
Alternately, you can stat() the master.passwd file AND fstat() the
open descriptor and compare the inode numbers. If the inode numbers
do not match, you have to close the descriptor and try again. If
they do, you are ok.
This fix works even in the face of additional hardlinks.
-Matt
>Audit-Trail:
>Unformatted:
help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199612270050.QAA09552>
