diff options
author | Jim Meyering <jim@meyering.net> | 2005-12-19 18:18:03 +0000 |
---|---|---|
committer | Jim Meyering <jim@meyering.net> | 2005-12-19 18:18:03 +0000 |
commit | fa6cfcb9ce13b810d8dc88a7b562927636ecaa30 (patch) | |
tree | 1fecf2f5fe85bd7faa7806d3a64a7901a849fcc5 /src | |
parent | 52893ffd2a3ff896e0b51f3f35bca191b71a47d4 (diff) | |
download | coreutils-fa6cfcb9ce13b810d8dc88a7b562927636ecaa30.tar.xz |
(main) Avoid a minor race condition when `-m MODE' is specified, by using
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.
Diffstat (limited to 'src')
-rw-r--r-- | src/mknod.c | 23 |
1 files changed, 16 insertions, 7 deletions
diff --git a/src/mknod.c b/src/mknod.c index a444c34da..e451f15c0 100644 --- a/src/mknod.c +++ b/src/mknod.c @@ -19,10 +19,12 @@ #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); |