changeset 7711:17e5da0fb096

* lib/mkdir-p.c (make_dir_parents): Fix race condition when making a directory that is about to be chowned. Such a directory's initial file permissions should permit the owner only and this should not be changed until after the chown, since the group and other bits would be incorrect if they granted permission before the chown.
author Paul Eggert <eggert@cs.ucla.edu>
date Mon, 04 Dec 2006 07:23:36 +0000
parents b78602e93aef
children aead3397193a
files ChangeLog lib/mkdir-p.c
diffstat 2 files changed, 19 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2006-12-03  Paul Eggert  <eggert@cs.ucla.edu>
 
+	* lib/mkdir-p.c (make_dir_parents): Fix race condition when making
+	a directory that is about to be chowned.  Such a directory's
+	initial file permissions should permit the owner only and this
+	should not be changed until after the chown, since the group and
+	other bits would be incorrect if they granted permission before
+	the chown.
+
 	Fix porting problem for iswctype reported by Georg Schwarz in:
 	http://lists.gnu.org/archive/html/bug-coreutils/2006-12/msg00017.html
 	* lib/fnmatch.c (WIDE_CHAR_SUPPORT): Require HAVE_ISWCTYPE, too.
--- a/lib/mkdir-p.c
+++ b/lib/mkdir-p.c
@@ -115,7 +115,14 @@
 
       if (0 <= prefix_len)
 	{
-	  if (mkdir (dir + prefix_len, mode) == 0)
+	  /* If the ownership will change, create the directory with
+	     more restrictive permissions at first, so unauthorized
+	     users cannot nip in before the directory is ready.  */
+	  mode_t mkdir_mode = mode;
+	  if (! (owner == (uid_t) -1 && group == (gid_t) -1))
+	    mkdir_mode &= S_IRWXU;
+
+	  if (mkdir (dir + prefix_len, mkdir_mode) == 0)
 	    {
 	      announce (dir, options);
 	      preserve_existing =
@@ -126,7 +133,10 @@
 		 | (mode & S_IRUSR ? SAVEWD_CHDIR_READABLE : 0));
 	    }
 	  else
-	    mkdir_errno = errno;
+	    {
+	      mkdir_errno = errno;
+	      mkdir_mode = -1;
+	    }
 
 	  if (preserve_existing)
 	    {
@@ -163,7 +173,6 @@
 		    }
 		  else
 		    {
-		      mode_t mkdir_mode = (mkdir_errno == 0 ? mode : -1);
 		      char const *subdir = (chdir_ok ? "." : dir + prefix_len);
 		      if (dirchownmod (fd, subdir, mkdir_mode, owner, group,
 				       mode, mode_bits)