Package: coreutils Version: 5.2.1-2 Tags: patch security fixed-upstream The mkdir, mkfifo, and mknod commands have a bug that can cause them to create a file with incorrect permissions. In principle this is a security problem, though I doubt whether the feature in question is widely used.
Here's an example of the bug: $ umask 077 $ mkdir -m =+rwx d $ ls -ld d drwxrwxrwx 2 eggert eggert 4096 Apr 23 18:51 d "d" should be accessible only to the user (i.e., the output of ls should start "drwx------"). However, because of the bug, it is accessible to the world. I have installed the following patch into CVS coreutils as described in <http://lists.gnu.org/archive/html/bug-coreutils/2005-04/msg00155.html>. 2005-04-22 Paul Eggert <[EMAIL PROTECTED]> * NEWS: Fix bug with "mkdir -m =+x dir"; the umask was being ignored when the "+x" was being evaluated. * mkdir.c (main): Compile mode with MODE_MASK_ALL and initial umask. * mkfifo.c (main): Likewise. * mknod.c (main): Likewise. * tests/mkdir/perm: Test for the above bug. Index: NEWS =================================================================== RCS file: /fetish/cu/NEWS,v retrieving revision 1.276 diff -p -u -r1.276 NEWS --- NEWS 9 Apr 2005 04:51:11 -0000 1.276 +++ NEWS 22 Apr 2005 23:50:46 -0000 @@ -44,6 +44,9 @@ GNU coreutils NEWS ls now refuses to generate time stamps containing more than 1000 bytes, to foil potential denial-of-service attacks on hosts with very large stacks. + "mkdir -m =+x dir" no longer ignores the umask when evaluating "+x", + and similarly for mkfifo and mknod. + "pr -D FORMAT" now accepts the same formats that "date +FORMAT" does. test now detects integer overflow when evaluating large integers, Index: src/mkdir.c =================================================================== RCS file: /fetish/cu/src/mkdir.c,v retrieving revision 1.91 diff -p -u -r1.91 mkdir.c --- src/mkdir.c 21 Sep 2004 22:26:42 -0000 1.91 +++ src/mkdir.c 22 Apr 2005 23:50:53 -0000 @@ -82,7 +82,7 @@ int main (int argc, char **argv) { mode_t newmode; - mode_t parent_mode; + mode_t parent_mode IF_LINT (= 0); const char *specified_mode = NULL; const char *verbose_fmt_string = NULL; int exit_status = EXIT_SUCCESS; @@ -125,16 +125,9 @@ main (int argc, char **argv) } newmode = S_IRWXUGO; - { - mode_t umask_value = umask (0); - umask (umask_value); /* Restore the old value. */ - parent_mode = (newmode & (~ umask_value)) | S_IWUSR | S_IXUSR; - } - if (specified_mode) { - struct mode_change *change = mode_compile (specified_mode, 0); - newmode &= ~ umask (0); + struct mode_change *change = mode_compile (specified_mode, MODE_MASK_ALL); if (change == MODE_INVALID) error (EXIT_FAILURE, 0, _("invalid mode %s"), quote (specified_mode)); else if (change == MODE_MEMORY_EXHAUSTED) @@ -142,6 +135,14 @@ main (int argc, char **argv) newmode = mode_adjust (newmode, change); } + if (specified_mode || create_parents) + { + mode_t umask_value = umask (0); + if (! specified_mode) + umask (umask_value); + parent_mode = (S_IRWXUGO & ~umask_value) | (S_IWUSR | S_IXUSR); + } + for (; optind < argc; ++optind) { bool ok; Index: src/mkfifo.c =================================================================== RCS file: /fetish/cu/src/mkfifo.c,v retrieving revision 1.73 diff -p -u -r1.73 mkfifo.c --- src/mkfifo.c 21 Sep 2004 22:26:42 -0000 1.73 +++ src/mkfifo.c 22 Apr 2005 23:50:53 -0000 @@ -116,13 +116,13 @@ main (int argc, char **argv) newmode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); if (specified_mode) { - newmode &= ~ umask (0); - change = mode_compile (specified_mode, 0); + change = mode_compile (specified_mode, MODE_MASK_ALL); if (change == MODE_INVALID) error (EXIT_FAILURE, 0, _("invalid mode")); else if (change == MODE_MEMORY_EXHAUSTED) xalloc_die (); newmode = mode_adjust (newmode, change); + umask (0); } for (; optind < argc; ++optind) Index: src/mknod.c =================================================================== RCS file: /fetish/cu/src/mknod.c,v retrieving revision 1.84 diff -p -u -r1.84 mknod.c --- src/mknod.c 21 Sep 2004 22:26:42 -0000 1.84 +++ src/mknod.c 22 Apr 2005 23:50:53 -0000 @@ -121,13 +121,13 @@ main (int argc, char **argv) newmode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); if (specified_mode) { - newmode &= ~ umask (0); - change = mode_compile (specified_mode, 0); + change = mode_compile (specified_mode, MODE_MASK_ALL); if (change == MODE_INVALID) error (EXIT_FAILURE, 0, _("invalid mode")); else if (change == MODE_MEMORY_EXHAUSTED) xalloc_die (); newmode = mode_adjust (newmode, change); + umask (0); } /* If the number of arguments is 0 or 1, Index: tests/mkdir/perm =================================================================== RCS file: /fetish/cu/tests/mkdir/perm,v retrieving revision 1.15 diff -p -u -r1.15 perm --- tests/mkdir/perm 23 Jun 2004 15:07:04 -0000 1.15 +++ tests/mkdir/perm 22 Apr 2005 23:50:55 -0000 @@ -41,6 +41,7 @@ tests=' 050 : -m 312 : drwx-w-rwx : d-wx--x-w- : 160 : empty : drwx--xrwx : drw---xrwx : 160 : -m 743 : drwx--xrwx : drwxr---wx : + 027 : -m =+x : drwxr-x--- : d--x--x--- : - : - : last : last : ' for p in empty -p; do -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]

