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>
next in thread | raw e-mail | index | archive | help
>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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199805291844.LAA07680>