* lib/mkdir-p.c (make_dir_parents): Fix race condition when making
authorPaul Eggert <eggert@cs.ucla.edu>
Mon, 4 Dec 2006 07:23:36 +0000 (07:23 +0000)
committerPaul Eggert <eggert@cs.ucla.edu>
Mon, 4 Dec 2006 07:23:36 +0000 (07:23 +0000)
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.

ChangeLog
lib/mkdir-p.c

index 51eec8691f25f03cf5d9db6dd40275308e296514..b6d4c6b7218d5139de499b72e327d926feb97b74 100644 (file)
--- 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.
index 19b962bf0fc9fa3a66581c728e3b853390c72a23..a927d5d571d4c3fe0721d0a90c12ef7d0e41a2ab 100644 (file)
@@ -115,7 +115,14 @@ make_dir_parents (char *dir,
 
       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 @@ make_dir_parents (char *dir,
                 | (mode & S_IRUSR ? SAVEWD_CHDIR_READABLE : 0));
            }
          else
-           mkdir_errno = errno;
+           {
+             mkdir_errno = errno;
+             mkdir_mode = -1;
+           }
 
          if (preserve_existing)
            {
@@ -163,7 +173,6 @@ make_dir_parents (char *dir,
                    }
                  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)