Skip site navigation (1)Skip section navigation (2)
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>

next in thread | raw e-mail | index | archive | help

>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:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199612270050.QAA09552>