summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>2005-12-19 18:18:03 +0000
committerJim Meyering <jim@meyering.net>2005-12-19 18:18:03 +0000
commitfa6cfcb9ce13b810d8dc88a7b562927636ecaa30 (patch)
tree1fecf2f5fe85bd7faa7806d3a64a7901a849fcc5 /src
parent52893ffd2a3ff896e0b51f3f35bca191b71a47d4 (diff)
downloadcoreutils-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.c23
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);