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>