Date: Fri, 29 May 1998 11:44:37 -0700 (PDT) From: cts@internetcds.com To: freebsd-gnats-submit@FreeBSD.ORG Subject: bin/6787: race condition in pw command Message-ID: <199805291844.LAA07680@hub.freebsd.org>
index | next in thread | raw e-mail
>Number: 6787
>Category: bin
>Synopsis: race condition in pw command
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Fri May 29 11:50:03 PDT 1998
>Last-Modified:
>Originator: Craig Spannring
>Organization:
InternetCDS
>Release: 2.2.6
>Environment:
FreeBSD bangkok.office.cdsnet.net 2.2.6-STABLE FreeBSD 2.2.6-STABLE #1: Tue Apr 28 16:38:57 PDT 1998 root@bangkok.office.cdsnet.net:/usr/src/sys/compile/BANGKOK i386
>Description:
vipw, chpass and passwd all lock the /etc/master.passwd file for the
entire time they run. pw tries not to hold the lock the entire time.
Specifically it does not have the file locked when it calls pwd_mkdb.
This causes some race conditions since multiple instances of pwd_mkdb
can run at the same time.
I think pw should take a pessimistic approach and keep the
/etc/master.passwd file locked the entire time just like passwd, vipw
and chpass. My quick fix for pw opens /etc/master.passwd in main()
with the O_EXLOCK flag in pw.c and doesn't close the file descriptor.
I also had to make sure that fileupdate() in fileupd.c does not try to
lock the /etc/master.passwd file.
I tried to contact David L. Nugent, <davidn@blaze.net.au> last week
but I have heard back from him yet.
I believe this problem exists in the -current tree as well as -stable.
>How-To-Repeat:
The following perl5 script will demonstrate the race condition. It
forks 10 copies of itself and each one tries to create and delete 100
users. With a fixed version of pw there will be no error messages
from pwd_mkdb and it will delete all of the new accounts before it finishes.
With the current version of pw you wind up with a large number of
accounts that aren't deleted because of the race condition and a large
number of messages from pwd_mkdb such as-
pwd_mkdb: /etc/pwd.db.tmp: File exists
pwd_mkdb: /etc/pwd.db.tmp to /etc/pwd.db: No such file or directory
pwd_mkdb: /etc/pwd.db.tmp: No such file or directory
pwd_mkdb: /etc/spwd.db.tmp: File exists
#!/usr/local/bin/perl -w
#
#
# Demonstrate pw glitch that occurs when multiple instances of pw run
# at the same time.
#
use strict 'vars';
use strict 'subs';
use diagnostics;
use diagnostics -verbose;
enable diagnostics;
my $a;
my $b;
my $i;
my $notAdded = 0;
my $notDeleted = 0;
my $wasAdded = 0;
my $pwAddFailures = 0;
my $pwDelFailures = 0;
my $PW="/usr/sbin/pw";
for($i=0; $i<10; $i++)
{
my $rc = fork();
if ($rc == -1)
{
print STDERR "Couldn't fork\n";
exit(1);
}
elsif ($rc == 0)
{
next;
}
else
{
foreach $a ('0'..'9')
{
foreach $b ('0'..'9')
{
my $username = "u$a$b$$";
my $cmd = "$PW useradd $username -d /tmp/$a/$b/$username";
mkdir("/tmp/$a", 0755);
mkdir("/tmp/$a/$b", 0755);
print "system($cmd);\n";
system($cmd)==0 || $pwAddFailures++;
if (!defined(getpwnam($username)))
{
$notAdded++;
$wasAdded=1;
}
else
{
$wasAdded=1;
}
$cmd = "$PW userdel $username";
print "system($cmd);\n";
system($cmd)==0 || $pwDelFailures++;
if ($wasAdded && defined(getpwnam($username)))
{
$notDeleted++;
}
}
}
open (STATUS, ">/tmp/status.$$");
print STATUS "'pw adduser' recorded $pwAddFailures failures.\n";
print STATUS "'pw deluser' recorded $pwDelFailures failures.\n";
print STATUS "$notAdded accounts weren't added, $notDeleted accounts weren't deleted\n";
print STATUS "$notAdded accounts weren't added, $notDeleted accounts weren't deleted\n";
}
}
>Fix:
main() in pw.c should be modified to set an exclusive lock
on /etc/master.passwd.
The function fileupdate in fileupd.c should be modified so that it does not
lock /etc/master.passwd.
>Audit-Trail:
>Unformatted:
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message
help
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199805291844.LAA07680>
