From cts@bangkok.office.cdsnet.net  Fri Jul 10 11:25:09 1998
Received: from bangkok.office.cdsnet.net (bangkok.office.cdsnet.net [204.118.245.23])
          by hub.freebsd.org (8.8.8/8.8.8) with ESMTP id LAA18618;
          Fri, 10 Jul 1998 11:25:08 -0700 (PDT)
          (envelope-from cts@bangkok.office.cdsnet.net)
Received: (from cts@localhost)
	by bangkok.office.cdsnet.net (8.8.8/8.8.5) id LAA03790;
	Fri, 10 Jul 1998 11:25:02 -0700 (PDT)
Message-Id: <199807101825.LAA03790@bangkok.office.cdsnet.net>
Date: Fri, 10 Jul 1998 11:25:02 -0700 (PDT)
From: Craig Spannring <cts@internetcds.com>
To: Poul-Henning Kamp <phk@freebsd.org>, freebsd-gnats-submit@freebsd.org
Cc: paul@mu.org, nate@mt.sri.com
Subject:

>Number:         7236
>Category:       bin
>Synopsis:       
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    gnats-admin
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Fri Jul 10 11:30:01 PDT 1998
>Closed-Date:    Sun Jul 12 17:22:13 PDT 1998
>Last-Modified:  Wed Oct 26 05:43:37 GMT 2005
>Originator:     
>Release:        
>Organization:
>Environment:
>Description:
>How-To-Repeat:
>Fix:
>Release-Note:
>Audit-Trail:
State-Changed-From-To: open->closed 
State-Changed-By: steve 
State-Changed-When: Sun Jul 12 17:22:13 PDT 1998 
State-Changed-Why:  
Intended as a followup to PR #6787. 
>Unformatted:
 >---cut here---<
 diff -c -r pw-stable.original/edgroup.c pw-stable/edgroup.c
 *** pw-stable.original/edgroup.c	Mon Jun  8 10:44:35 1998
 --- pw-stable/edgroup.c	Mon Jun  8 11:33:27 1998
 ***************
 *** 64,70 ****
   	int             rc = 0;
   	int             infd;
   
 ! 	if ((infd = open(groupfile, O_RDWR | O_CREAT | O_EXLOCK, 0644)) != -1) {
   		FILE           *infp;
   
   		if ((infp = fdopen(infd, "r+")) == NULL)
 --- 64,70 ----
   	int             rc = 0;
   	int             infd;
   
 ! 	if ((infd = open(groupfile, O_RDWR | O_CREAT, 0644)) != -1) {
   		FILE           *infp;
   
   		if ((infp = fdopen(infd, "r+")) == NULL)
 diff -c -r pw-stable.original/fileupd.c pw-stable/fileupd.c
 *** pw-stable.original/fileupd.c	Mon Jun  8 10:44:36 1998
 --- pw-stable/fileupd.c	Mon Jun  8 11:40:40 1998
 ***************
 *** 49,55 ****
   	if (pfxlen <= 1)
   		errno = EINVAL;
   	else {
 ! 		int             infd = open(filename, O_RDWR | O_CREAT | O_EXLOCK, fmode);
   
   		if (infd != -1) {
   			FILE           *infp = fdopen(infd, "r+");
 --- 49,55 ----
   	if (pfxlen <= 1)
   		errno = EINVAL;
   	else {
 ! 		int             infd = open(filename, O_RDWR | O_CREAT, fmode);
   
   		if (infd != -1) {
   			FILE           *infp = fdopen(infd, "r+");
 ***************
 *** 134,142 ****
   									fputs(line, infp);
   
   								/*
   								 * This is a gross hack, but we may have
   								 * corrupted the original file
 ! 								 * Unfortunately, it will lose the inode.
   								 */
   								if (fflush(infp) == EOF || ferror(infp))
   									rc = rename(file, filename) == 0;
 --- 134,153 ----
   									fputs(line, infp);
   
   								/*
 +                                                                  * If there was a problem with copying
 +                                                                  * we will just rename 'file.new' 
 +                                                                  * to 'file'.
   								 * This is a gross hack, but we may have
   								 * corrupted the original file
 ! 								 * Unfortunately, it will lose the inode
 !                                                                  * and hence the lock.
 !                                                                  *
 !                                                                  * The implications of this is that this invocation of pw 
 !                                                                  * won't have the file locked and concurrent copies
 !                                                                  * of pw, vipw etc could clobber what this one is doing.
 !                                                                  *
 !                                                                  * It should probably just return an error instead
 !                                                                  * of going on like nothing is wrong.
   								 */
   								if (fflush(infp) == EOF || ferror(infp))
   									rc = rename(file, filename) == 0;
 diff -c -r pw-stable.original/pw.c pw-stable/pw.c
 *** pw-stable.original/pw.c	Mon Jun  8 10:44:36 1998
 --- pw-stable/pw.c	Mon Jun  8 12:31:09 1998
 ***************
 *** 31,36 ****
 --- 31,37 ----
   
   #include "pw.h"
   #include <err.h> 
 + #include <fcntl.h>
   
   const char     *Modes[] = {"add", "del", "mod", "show", "next", NULL};
   const char     *Which[] = {"user", "group", NULL};
 ***************
 *** 47,52 ****
 --- 48,54 ----
   
   static int      getindex(const char *words[], const char *word);
   static void     cmdhelp(int mode, int which);
 + static int      filelock(const char *filename);
   
   
   int
 ***************
 *** 145,151 ****
   	 * Now, let's do the common initialisation
   	 */
   	cnf = read_userconfig(getarg(&arglist, 'C') ? getarg(&arglist, 'C')->val : NULL);
 ! 	return funcs[which] (cnf, mode, &arglist);
   }
   
   static int
 --- 147,172 ----
   	 * Now, let's do the common initialisation
   	 */
   	cnf = read_userconfig(getarg(&arglist, 'C') ? getarg(&arglist, 'C')->val : NULL);
 ! 
 ! 	/*
 ! 	 * Be pessimistic and lock the master passowrd and group
 ! 	 * files right away.  Keep it locked for the duration.
 ! 	 */
 ! 	if (-1 == filelock(_PATH_GROUP) || -1 == filelock(_PATH_MASTERPASSWD))
 ! 	{
 ! 		ch = EX_IOERR;
 ! 	}
 ! 	else
 ! 	{
 ! 		ch = funcs[which] (cnf, mode, &arglist);
 ! 	}
 !         return ch;
 ! }
 ! 
 ! static int
 ! filelock(const char *filename)
 ! {
 ! 	return open(filename, O_RDONLY | O_EXLOCK, 0);
   }
   
   static int
 
 Subject Re: bin/6787: race condition in pw command
 In-Reply-To: <199806020959.CAA15603@freefall.freebsd.org>
 References: <199806020959.CAA15603@freefall.freebsd.org>
 X-Mailer: VM 6.31 under Emacs 20.2.1
 
 
 
 Poul-Henning Kamp writes:
  > Synopsis: race condition in pw command
  > 
  > State-Changed-From-To: open-suspended
  > State-Changed-By: phk
  > State-Changed-When: Tue Jun 2 02:59:22 PDT 1998
  > State-Changed-Why: 
  > awaiting patches & committer
 
 Poul, 
 
 Was there a problem with the patches I sent to you and Nate Williams
 on June 8, 1998?
 
 BTW-  I don't think the patch submitted by Paul Saab <paul@mu.org> will
 work.  When the function fileupd in fileupd.c tries to get an
 exclusive lock on the file it will block forever.  You can easily test
 it with the Perl program given in the "How-To-Repeat" section of the
 PR.
 
 In case you don't have it here is my patch for 2.2.6 and description
 from June 2.
 -----------------------------------------
 
 These are the patches to pw for -stable.  I will send the patches for
 -current in the next mail message.
 
 I tried to follow the same style as charnier(?).  One spot where I
 disagree with the style is near the end of the main function in pw.c.
 He reuses the 'ch' variable to hold the return status of the
 
   funcs[which] (cnf, mode, &arglist)
 
 call.  It overloads the meaning of 'ch' and is not very descriptive,
 but I left it as is.
 
 The fileupdate function is still somewhat broken.  Instead of returning
 a failure code if it can't modify the original file it renames the
 .new file and continues as though nothing is wrong.  This will cause
 the lock on the original file to be lost and could lead to a similar
 race condition.  I left that portion of the code alone since I feel
 that the maintainer of the code would have a better concept of how he
 wants to handle errors in that function than I do.
 
 BTW-  I used 'diff -c -r pw-stable.original pw-stable' to generate
 this patch.
 
 
