]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
(main) Avoid a minor race condition when `-m MODE' is specified, by using
authorJim Meyering <jim@meyering.net>
Mon, 19 Dec 2005 18:18:03 +0000 (18:18 +0000)
committerJim Meyering <jim@meyering.net>
Mon, 19 Dec 2005 18:18:03 +0000 (18:18 +0000)
open, fchown, and close rather than just chown.  To do that reliably
(even with an overly restrictive umask), ensure that each
mknod call uses a mode including at least owner-read access.

(main): When `-m MODE' is specified, exit nonzero if
the subsequent chown (or equivalent open,fchown,close) fails.

src/mknod.c

index a444c34da1490569b98f50f0e72fac9dd9345ea3..e451f15c04a25e2d0fe6e9d09668b77036854c81 100644 (file)
 
 #include <config.h>
 #include <stdio.h>
+#include <assert.h>
 #include <getopt.h>
 #include <sys/types.h>
 
 #include "system.h"
+#include "chmod-safer.h"
 #include "error.h"
 #include "modechange.h"
 #include "quote.h"
@@ -88,10 +90,12 @@ int
 main (int argc, char **argv)
 {
   mode_t newmode;
+  mode_t tmp_mode;
   const char *specified_mode;
   int optc;
   int expected_operands;
-  mode_t node_type;
+  mode_t node_type IF_LINT (= 0);
+  dev_t device = 0;
 
   initialize_main (&argc, &argv);
   program_name = argv[0];
@@ -127,6 +131,11 @@ main (int argc, char **argv)
       free (change);
     }
 
+  /* This is the mode we'll use in the mknod or mkfifo call.
+     If it doesn't include S_IRUSR, use S_IRUSR so the final
+     open-for-fchmod will succeed.  */
+  tmp_mode = (newmode & S_IRUSR) ? newmode : S_IRUSR;
+
   /* If the number of arguments is 0 or 1,
      or (if it's 2 or more and the second one starts with `p'), then there
      must be exactly two operands.  Otherwise, there must be four.  */
@@ -183,7 +192,6 @@ main (int argc, char **argv)
        char const *s_major = argv[optind + 2];
        char const *s_minor = argv[optind + 3];
        uintmax_t i_major, i_minor;
-       dev_t device;
 
        if (xstrtoumax (s_major, NULL, 0, &i_major, NULL) != LONGINT_OK
            || i_major != (major_t) i_major)
@@ -201,7 +209,7 @@ main (int argc, char **argv)
          error (EXIT_FAILURE, 0, _("invalid device %s %s"), s_major, s_minor);
 #endif
 
-       if (mknod (argv[optind], newmode | node_type, device) != 0)
+       if (mknod (argv[optind], tmp_mode | node_type, device) != 0)
          error (EXIT_FAILURE, errno, "%s", quote (argv[optind]));
       }
       break;
@@ -210,7 +218,8 @@ main (int argc, char **argv)
 #ifndef S_ISFIFO
       error (EXIT_FAILURE, 0, _("fifo files not supported"));
 #else
-      if (mkfifo (argv[optind], newmode))
+      node_type = S_IFIFO;
+      if (mkfifo (argv[optind], tmp_mode))
        error (EXIT_FAILURE, errno, "%s", quote (argv[optind]));
 #endif
       break;
@@ -226,9 +235,9 @@ main (int argc, char **argv)
 
   if (specified_mode)
     {
-      if (chmod (argv[optind], newmode))
-        error (0, errno, _("cannot set permissions of %s"),
-               quote (argv[optind]));
+      if (chmod_safer (argv[optind], newmode, device, node_type) != 0)
+       error (EXIT_FAILURE, errno, _("cannot set permissions of %s"),
+              quote (argv[optind]));
     }
 
   exit (EXIT_SUCCESS);