From dillon@backplane.com  Thu Dec 26 16:50:39 1996
Received: from apollo.backplane.com (dillon@apollo.backplane.com [204.156.134.254])
          by freefall.freebsd.org (8.8.4/8.8.4) with ESMTP id QAA21661
          for <FreeBSD-gnats-submit@freebsd.org>; Thu, 26 Dec 1996 16:50:36 -0800 (PST)
Received: (dillon@localhost) by apollo.backplane.com (8.7.5/8.6.5) id QAA09552; Thu, 26 Dec 1996 16:50:34 -0800 (PST)
Message-Id: <199612270050.QAA09552@apollo.backplane.com>
Date: Thu, 26 Dec 1996 16:50:34 -0800 (PST)
From: Matthew Dillon <dillon@backplane.com>
Reply-To: dillon@backplane.com
To: FreeBSD-gnats-submit@freebsd.org
Subject: Race condition in pw_lock (vipw, chpass, etc....)
X-Send-Pr-Version: 3.2

>Number:         2291
>Category:       bin
>Synopsis:       [PATCH?] race condition in /etc/master.passwd locking code pw_lock()
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Dec 26 17:00:01 PST 1996
>Closed-Date:    Tue Jul 6 18:37:57 PDT 1999
>Last-Modified:  Tue Jul  6 18:38:57 PDT 1999
>Originator:     Matthew Dillon
>Release:        FreeBSD 2.1-STABLE i386
>Organization:
>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

>Release-Note:
>Audit-Trail:

From: J Wunsch <j@uriah.heep.sax.de>
To: dillon@backplane.com
Cc: FreeBSD-gnats-submit@freebsd.org
Subject: Re: bin/2291: Race condition in pw_lock (vipw, chpass, etc....)
Date: Fri, 27 Dec 1996 09:20:55 +0100 (MET)

 As Matthew Dillon wrote:
 
 >         /*
 >          * 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,
 
 > 	The fix is simple.
 
 Why not using the O_EXLOCK flag in open(2)?
 
 -- 
 cheers, J"org
 
 joerg_wunsch@uriah.heep.sax.de -- http://www.sax.de/~joerg/ -- NIC: JW11-RIPE
 Never trust an operating system you don't have sources for. ;-)

From: Matthew Dillon <dillon@backplane.com>
To: joerg_wunsch@uriah.heep.sax.de (Joerg Wunsch)
Cc: FreeBSD-gnats-submit@freebsd.org
Subject: Re: bin/2291: Race condition in pw_lock (vipw, chpass, etc....)
Date: Fri, 27 Dec 1996 01:21:07 -0800 (PST)

 :
 :Why not using the O_EXLOCK flag in open(2)?
 :
 :-- 
 :cheers, J"org
 :
 :joerg_wunsch@uriah.heep.sax.de -- http://www.sax.de/~joerg/ -- NIC: JW11-RIPE
 :Never trust an operating system you don't have sources for. ;-)
 
     I don't think O_EXLOCK avoids the rename()-over race condition... you
     still have to do the stat()/fstat() check afterwords.
 
 					-Matt
 
     Matthew Dillon   Engineering, BEST Internet Communications, Inc.
 		     <dillon@apollo.backplane.com>
     [always include a portion of the original email in any response!]
State-Changed-From-To: open->suspended 
State-Changed-By: phk 
State-Changed-When: Mon May 25 01:15:06 PDT 1998 
State-Changed-Why:  
Awaiting committer 
State-Changed-From-To: suspended->closed 
State-Changed-By: nrahlstr 
State-Changed-When: Tue Jul 6 18:37:57 PDT 1999 
State-Changed-Why:  
Fixed by Matt in revision 1.12. 
>Unformatted:
