[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#1720: adduser: races, and chmod/chown - patch provided



Package: adduser
Version: 1.94-1

Three different bugs fixed here:

 (1) There were a few race conditions in locking the password and
     group files.  A badly timed ^C could result in the lockfile
     not being cleared.

 (2) chown()/chmod() persistantly used in the wrong order throughout.
     Could people please take note: chown()ing a file removes the
     setuid and setgid bits on it!  It's no use chmod()ing a file to
     be setgid, then chown()ing it to someone else.

 (3) The copy_to_file() routine doesn't preserve permissions.  This
     means that giving user's a default .xsession (which must be rwx)
     isn't possible. I've modified copy_to_file() to now copy the
     permissions with the file - but the files are chown()ed later, so
     the setuid/setgid bit will be lost. (This is probably the right
     thing to happen, in this instance).


As always, patch included...


Austin


--- /usr/sbin/adduser	Thu Oct  5 20:02:18 1995
+++ adduser	Sat Oct 21 02:24:19 1995
@@ -328,8 +328,8 @@
 	exit 1;
     }
     # lock the password file
-    link $PASSWD, $PLOCK;
     $passwd_state = "locked";
+    link $PASSWD, $PLOCK;
 }
 ##
 ## check if the group file is locked, if necessary:
@@ -344,8 +344,8 @@
 	exit 1;
     }
     # lock the group file
-    link $GROUP, $GLOCK;
     $group_state = "locked";
+    link $GROUP, $GLOCK;
 }


@@ -508,11 +508,11 @@
     }

     if ($make_group_also) {
-	chmod (02775, $home_dir);
 	chown ($new_uid, $new_gid, $home_dir);
+	chmod (02775, $home_dir);
     } else {
-	chmod (0755, $home_dir);
 	chown ($new_uid, 0, $home_dir);
+	chmod (0755, $home_dir);
     }

     &clean_up();
@@ -651,6 +651,7 @@
 	}
 	mkdir ($home_dir, $dir_mode);
 	chown ($new_uid, $new_gid, $home_dir);
+	chmod ($home_dir, $dir_mode); # since chown() resets set{gu}id bit
 	print "done.\n" if ($verbose);

 	##
@@ -857,12 +858,20 @@
 ##
 sub copy_to_dir {
     local ($file, $dir) = @_;
+    local ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size,
+	   $atime, $mtime, $ctime, $blksize, $blocks);

     if ((! -f $file) || (! -d $dir)) {
 	return -1;
     }

     open (FILE, $file) || die "open: $!";
+
+    # grab access permissions for later
+    ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
+     $atime,$mtime,$ctime,$blksize,$blocks)
+	= stat($file);
+
     $file =~ s+.*/++;		# get the basename
     open (NEWFILE, ">$dir/$file") || die "open: $!";

@@ -872,6 +881,10 @@

     close FILE;
     close NEWFILE;
+
+    # now copy permissions saved earlier. Note setuid/setgid bit destroyed
+    # by a later chown call - maybe thats a good thing!
+    chmod($mode, "$dir/$file");

     return 1;
 }


Reply to: