Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 8 Jun 1998 13:10:18 -0700 (PDT)
From:      Craig Spannring <cts@internetcds.com>
To:        nate@mt.sri.com, phk@FreeBSD.ORG
Cc:        freebsd-bugs@FreeBSD.ORG
Subject:   Re: bin/6787: race condition in pw command 
Message-ID:  <199806082010.NAA21530@bangkok.office.cdsnet.net>
In-Reply-To: <199806011822.MAA10429@mt.sri.com>
References:  <199805291844.LAA07680@hub.freebsd.org> <199805300220.UAA28867@mt.sri.com> <199806011818.LAA28408@bangkok.office.cdsnet.net> <199806011822.MAA10429@mt.sri.com>

next in thread | previous in thread | raw e-mail | index | archive | help

Here are the patches for -current.  I have compiled them, but I don't
have a 3.0 machine available for testing so I haven't run them.
Sorry.

>---cut here---<
diff -c -r pw-cur.original/edgroup.c pw-cur/edgroup.c
*** pw-cur.original/edgroup.c	Mon Jun  8 10:39:32 1998
--- pw-cur/edgroup.c	Mon Jun  8 12:13:39 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-cur.original/fileupd.c pw-cur/fileupd.c
*** pw-cur.original/fileupd.c	Mon Jun  8 10:39:32 1998
--- pw-cur/fileupd.c	Mon Jun  8 12:32:27 1998
***************
*** 76,82 ****
  	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+");
--- 76,82 ----
  	if (pfxlen <= 1)
  		errno = EINVAL;
  	else {
! 		int             infd = open(filename, O_RDWR | O_CREAT, fmode);
  
  		if (infd != -1) {
  			FILE           *infp = fdopen(infd, "r+");
***************
*** 168,176 ****
  									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;
--- 168,187 ----
  									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-cur.original/pw.c pw-cur/pw.c
*** pw-cur.original/pw.c	Mon Jun  8 10:39:33 1998
--- pw-cur/pw.c	Mon Jun  8 12:30:05 1998
***************
*** 31,36 ****
--- 31,37 ----
  
  #include "pw.h"
  #include <err.h>
+ #include <fcntl.h>
  #include <paths.h>
  #include <sys/wait.h>
  
***************
*** 49,54 ****
--- 50,56 ----
  
  static int      getindex(const char *words[], const char *word);
  static void     cmdhelp(int mode, int which);
+ static int      filelock(const char *filename);
  
  
  int
***************
*** 147,153 ****
  	 * Now, let's do the common initialisation
  	 */
  	cnf = read_userconfig(getarg(&arglist, 'C') ? getarg(&arglist, 'C')->val : NULL);
! 	ch = funcs[which] (cnf, mode, &arglist);
  
  	/*
  	 * If everything went ok, and we've been asked to update
--- 149,168 ----
  	 * 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);
! 	}	
  
  	/*
  	 * If everything went ok, and we've been asked to update
***************
*** 175,180 ****
--- 190,201 ----
  		}
  	}
  	return ch;
+ }
+ 
+ static int
+ filelock(const char *filename)
+ {
+ 	return open(filename, O_RDONLY | O_EXLOCK, 0);
  }
  
  static int

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?199806082010.NAA21530>