bug-coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: chmod set-gid/set-uid behavior change issues


From: Paul Eggert
Subject: Re: chmod set-gid/set-uid behavior change issues
Date: Fri, 28 Jul 2006 03:35:50 -0400
User-agent: Gnus/5.1008 (Gnus v5.10.8) Emacs/21.4 (gnu/linux)

Jim Meyering <address@hidden> writes:

> As you've guessed, #2 is the one I prefer.

OK, I implemented that by installing the following.  This should also
fix the test case problems that Bob reported.

2006-07-28  Paul Eggert  <address@hidden>

        * NEWS: chmod now preserves setuid and setgid bits on directories
        if you use a numeric mode with them clear, e.g., "chmod 755 DIR".

        * doc/coreutils.texi (install invocation, mkdir invocation):
        Add cross-references to Directory Setuid and Setgid.
        (install-invocation): The default mode is no longer equivalent to 755.
        * doc/perm.texi (Changing Special Mode Bits): Clarify u+s versus
        a+s versus +s, and likewise for g+s.
        (Numeric Modes): Bring back example of 0055 == 55.  4755 no
        longer clears setgid bit on directories.
        (Directory Setuid and Setgid): Numeric modes now affect setuid
        and setgid on directories only if they set these bits.  This
        is so that leading 0 has no effect on numeric modes.

        * lib/modechange.c (mode_compile): Numeric modes now affect setuid and
        setgid on directories only if they set these bits.

        Fix test case problems if working directory is setgid,
        reported by Bob Proulx.
        * tests/cp/fail-perm: Use symbolic mode so that we clear
        setgid bit more reliably on directories.
        * tests/mkdir/special-1 (set_mode_string): Likewise.

Index: NEWS
===================================================================
RCS file: /fetish/cu/NEWS,v
retrieving revision 1.395
diff -p -u -r1.395 NEWS
--- NEWS        25 Jul 2006 18:38:58 -0000      1.395
+++ NEWS        28 Jul 2006 07:23:43 -0000
@@ -31,8 +31,10 @@ GNU coreutils NEWS                      
   `chmod 755 DIR' and `chmod u=rwx,go=rx DIR' now preserve DIR's
   set-user-ID and set-group-ID bits instead of clearing them, and
   similarly for `mkdir -m 755 DIR' and `mkdir -m u=rwx,go=rx DIR'.  To
-  clear the bits, mention them explicitly, e.g., `chmod 0755 DIR' or
-  `mkdir -m a-s,u=rwx,go=rx DIR'.  This change is for convenience on
+  clear the bits, mention them explicitly in a symbolic mode, e.g.,
+  `mkdir -m u=rwx,go=rx,-s DIR'.  To set them, mention them explicitly
+  in either a symbolic or a numeric mode, e.g., `mkdir -m 2755 DIR',
+  `mkdir -m u=rwx,go=rx,g+s' DIR.  This change is for convenience on
   systems where these bits inherit from parents.  Unfortunately other
   operating systems are not consistent here, and portable scripts
   cannot assume the bits are set, cleared, or preserved, even when the
Index: doc/coreutils.texi
===================================================================
RCS file: /fetish/cu/doc/coreutils.texi,v
retrieving revision 1.342
diff -p -u -r1.342 coreutils.texi
--- doc/coreutils.texi  26 Jul 2006 14:06:58 -0000      1.342
+++ doc/coreutils.texi  28 Jul 2006 07:18:28 -0000
@@ -7260,7 +7260,8 @@ If the @option{--directory} (@option{-d}
 @command{install} creates each @var{directory} and any missing parent
 directories.  Parent directories are created with mode
 @samp{u=rwx,go=rx} (755), regardless of the @option{-m} option or the
-current umask.
+current umask.  @xref{Directory Setuid and Setgid}, for how the
+set-user-ID and set-group-ID bits of parent directories are inherited.
 @end itemize
 
 @cindex Makefiles, installing programs in
@@ -7308,9 +7309,12 @@ Set the file mode bits for the installed
 which can be either an octal number, or a symbolic mode as in
 @command{chmod}, with @samp{a=} (no access allowed to anyone) as the
 point of departure (@pxref{File permissions}).
-The default mode is @samp{u=rwx,go=rx,a-s} (0755)---read, write, and
+The default mode is @samp{u=rwx,go=rx,a-s}---read, write, and
 execute for the owner, read and execute for group and other, and with
 set-user-ID and set-group-ID disabled.
+This default is not quite the same as @samp{755}, since it disables
+instead of preserving set-user-ID and set-group-ID on directories.
address@hidden Setuid and Setgid}.
 
 @item -o @var{owner}
 @itemx address@hidden
@@ -8102,7 +8106,9 @@ Normally the directory has the desired f
 is created.  As a @acronym{GNU} extension, @var{mode} may also mention
 special mode bits, but in this case there may be a temporary window
 during which the directory exists but its special mode bits are
-incorrect.
+incorrect.  @xref{Directory Setuid and Setgid}, for how the
+set-user-ID and set-group-ID bits of directories are inherited unless
+overridden in this way.
 
 @item -p
 @itemx --parents
@@ -8111,6 +8117,8 @@ incorrect.
 @cindex parent directories, creating
 Make any missing parent directories for each argument.  The file permission
 bits of parent directories are set to the umask modified by @samp{u+wx}.
address@hidden Setuid and Setgid}, for how the set-user-ID and
+set-group-ID bits of parent directories are inherited.
 Ignore arguments corresponding to existing directories, and do not
 change their file mode bits.
 
Index: doc/perm.texi
===================================================================
RCS file: /fetish/cu/doc/perm.texi,v
retrieving revision 1.19
diff -p -u -r1.19 perm.texi
--- doc/perm.texi       25 Jul 2006 18:37:55 -0000      1.19
+++ doc/perm.texi       28 Jul 2006 07:18:28 -0000
@@ -297,13 +297,17 @@ you can change its special mode bits.  @
 summary of these special mode bits.
 
 To change the file mode bits to set the user ID on execution, use
address@hidden or @samp{a} in the @var{users} part of the symbolic mode and
address@hidden in the @var{users} part of the symbolic mode and
 @samp{s} in the @var{permissions} part.
 
 To change the file mode bits to set the group ID on execution, use
address@hidden or @samp{a} in the @var{users} part of the symbolic mode and
address@hidden in the @var{users} part of the symbolic mode and
 @samp{s} in the @var{permissions} part.
 
+To set both user and group ID on execution, omit the @var{users} part
+of the symbolic mode (or use @samp{a}) and use @samp{s} in the
address@hidden part.
+
 To change the file mode bits to set the restricted deletion flag or sticky bit,
 omit the @var{users} part of the symbolic mode (or use @samp{a}) and use
 @samp{t} in the @var{permissions} part.
@@ -479,7 +483,8 @@ As an
 alternative to giving a symbolic mode, you can give an octal (base 8)
 number that represents the mode.
 This number is always interpreted in octal; you do not have to add a
-leading @samp{0}, as you do in C.
+leading @samp{0}, as you do in C.  Mode @samp{0055} is the same as
+mode @samp{55}.
 
 A numeric mode is usually shorter than the corresponding symbolic
 mode, but it is limited in that normally it cannot take into account the
@@ -520,9 +525,9 @@ Mode      Mode Bit
 4000      Set user ID on execution
 @end example
 
-For example, numeric mode 4755 corresponds to symbolic mode
address@hidden,go=rx,g-s}, and numeric mode 664 corresponds to symbolic mode
address@hidden,o=r}.  Numeric mode 0 corresponds to symbolic mode
+For example, numeric mode @samp{4755} corresponds to symbolic mode
address@hidden,go=rx}, and numeric mode @samp{664} corresponds to symbolic mode
address@hidden,o=r}.  Numeric mode @samp{0} corresponds to symbolic mode
 @samp{a=}.
 
 @node Directory Setuid and Setgid
@@ -543,31 +548,43 @@ bits of directories.  If commands like @
 mechanisms would be less convenient and it would be harder to share
 files.  Therefore, a command like @command{chmod} does not affect the
 set-user-ID or set-group-ID bits of a directory unless the user
-specifically mentions them.  For example, on systems that support
+specifically mentions them in a symbolic mode, or sets them in
+a numeric mode.  For example, on systems that support
 set-group-ID inheritance:
 
 @example
 # These commands leave the set-user-ID and
 # set-group-ID bits of the subdirectories alone,
 # so that they retain their default values.
-mkdir a b
-chmod 755 a
-chmod u=rwx,go=rx b
-mkdir -m 755 c
-mkdir -m u=rwx,go=rx d
+mkdir A B C
+chmod 755 A
+chmod 0755 B
+chmod u=rwx,go=rx C
+mkdir -m 755 D
+mkdir -m 0755 E
+mkdir -m u=rwx,go=rx F
 @end example
 
-If you want to try to clear these bits, you must mention them
+If you want to try to set these bits, you must mention them
 explicitly in the symbolic or numeric modes, e.g.:
 
 @example
-# These commands try to clear the set-user-ID
+# These commands try to set the set-user-ID
 # and set-group-ID bits of the subdirectories.
-mkdir a b
-chmod 0755 a
-chmod a-s,u=rwx,go=rx b
-mkdir -m 0755 c
-mkdir -m a-s,u=rwx,go=rx d
+mkdir G H
+chmod 6755 G
+chmod u=rwx,go=rx,a+s H
+mkdir -m 6755 I
+mkdir -m u=rwx,go=rx,a+s J
address@hidden example
+
+If you want to try to clear these bits, you must mention them
+explicitly in a symbolic mode, e.g.:
+
address@hidden
+# This command tries to clear the set-user-ID
+# and set-group-ID bits of the directory D.
+chmod a-s D
 @end example
 
 This behavior is a @acronym{GNU} extension.  Portable scripts should
Index: lib/modechange.c
===================================================================
RCS file: /fetish/cu/lib/modechange.c,v
retrieving revision 1.35
diff -p -u -r1.35 modechange.c
--- lib/modechange.c    17 Jul 2006 05:56:28 -0000      1.35
+++ lib/modechange.c    28 Jul 2006 07:18:28 -0000
@@ -143,12 +143,12 @@ mode_compile (char const *mode_string)
   if ('0' <= *mode_string && *mode_string < '8')
     {
       unsigned int octal_mode = 0;
-      unsigned int octal_mentioned = 0;
+      mode_t mode;
+      mode_t mentioned;
 
       do
        {
          octal_mode = 8 * octal_mode + *mode_string++ - '0';
-         octal_mentioned = 8 * octal_mentioned + 7;
          if (ALLM < octal_mode)
            return NULL;
        }
@@ -157,8 +157,9 @@ mode_compile (char const *mode_string)
       if (*mode_string)
        return NULL;
 
-      return make_node_op_equals (octal_to_mode (octal_mode),
-                                 octal_to_mode (octal_mentioned & ALLM));
+      mode = octal_to_mode (octal_mode);
+      mentioned = (mode & (S_ISUID | S_ISGID)) | S_ISVTX | S_IRWXUGO;
+      return make_node_op_equals (mode, mentioned);
     }
 
   /* Allocate enough space to hold the result.  */
@@ -299,7 +300,8 @@ mode_create_from_ref (const char *ref_fi
    directory if DIR), assuming the umask is UMASK_VALUE, adjusted as
    indicated by the list of change operations CHANGES.  If DIR, the
    type 'X' change affects the returned value even if no execute bits
-   were set in OLDMODE.  If PMODE_BITS is not null, store into
+   were set in OLDMODE, and set user and group ID bits are preserved
+   unless CHANGES mentioned them.  If PMODE_BITS is not null, store into
    *PMODE_BITS a mask denoting file mode bits that are affected by
    CHANGES.
 
Index: tests/cp/fail-perm
===================================================================
RCS file: /fetish/cu/tests/cp/fail-perm,v
retrieving revision 1.11
diff -p -u -r1.11 fail-perm
--- tests/cp/fail-perm  25 Jul 2006 18:38:25 -0000      1.11
+++ tests/cp/fail-perm  28 Jul 2006 07:18:28 -0000
@@ -20,7 +20,7 @@ cd $tmp || framework_failure=1
 mkdir D D/D || framework_failure=1
 touch D/a || framework_failure=1
 chmod 0 D/a || framework_failure=1
-chmod 0500 D || framework_failure=1
+chmod u=rx,go=,-st D || framework_failure=1
 
 if test $framework_failure = 1; then
   echo 'failure in testing framework'
Index: tests/mkdir/special-1
===================================================================
RCS file: /fetish/cu/tests/mkdir/special-1,v
retrieving revision 1.5
diff -p -u -r1.5 special-1
--- tests/mkdir/special-1       29 Apr 2000 09:37:44 -0000      1.5
+++ tests/mkdir/special-1       28 Jul 2006 07:18:28 -0000
@@ -10,7 +10,7 @@ tmp=mkdir-sp-$$
 trap 'status=$?; rm -rf $tmp && exit $status' 0
 trap 'exit $?' 1 2 13 15
 
-set_mode_string=u=rwx,g=rx,o=w,go+t
+set_mode_string=u=rwx,g=rx,o=w,-s,+t
 output_mode_string=drwxr-x-wT
 
 mkdir -m$set_mode_string $tmp || fail=1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]