]> git.eshelyaron.com Git - emacs.git/commitdiff
* fileio.c (Fcopy_file): Adjust mode if fchown fails. (Bug#9002)
authorPaul Eggert <eggert@cs.ucla.edu>
Mon, 18 Jul 2011 17:21:18 +0000 (10:21 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Mon, 18 Jul 2011 17:21:18 +0000 (10:21 -0700)
If fchown fails to set both uid and gid, try to set just gid,
as that is sometimes allowed.  Adjust the file's mode to eliminate
setuid or setgid bits that are inappropriate if fchown fails.

src/ChangeLog
src/fileio.c

index a2891fa9c911bfafc283bfa42f1d24a2a47a1a55..5de5fefd6aaa1f2ae9137ea0702a34cd89533e54 100644 (file)
@@ -1,3 +1,10 @@
+2011-07-18  Paul Eggert  <eggert@cs.ucla.edu>
+
+       * fileio.c (Fcopy_file): Adjust mode if fchown fails.  (Bug#9002)
+       If fchown fails to set both uid and gid, try to set just gid,
+       as that is sometimes allowed.  Adjust the file's mode to eliminate
+       setuid or setgid bits that are inappropriate if fchown fails.
+
 2011-07-18  Stefan Monnier  <monnier@iro.umontreal.ca>
 
        * xdisp.c (next_element_from_string, next_element_from_buffer): Use EQ
index a52e834c2b270758b6b59afe661da24c5b04c73a..fb2c081ae5c4af065e6f4a34160c47c22e4916cf 100644 (file)
@@ -38,8 +38,6 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <selinux/context.h>
 #endif
 
-#include <ignore-value.h>
-
 #include "lisp.h"
 #include "intervals.h"
 #include "buffer.h"
@@ -1961,9 +1959,21 @@ on the system, we copy the SELinux context of FILE to NEWNAME.  */)
      owner and group.  */
   if (input_file_statable_p)
     {
+      int mode_mask = 07777;
       if (!NILP (preserve_uid_gid))
-       ignore_value (fchown (ofd, st.st_uid, st.st_gid));
-      if (fchmod (ofd, st.st_mode & 07777) != 0)
+       {
+         /* Attempt to change owner and group.  If that doesn't work
+            attempt to change just the group, as that is sometimes allowed.
+            Adjust the mode mask to eliminate setuid or setgid bits
+            that are inappropriate if the owner and group are wrong.  */
+         if (fchown (ofd, st.st_uid, st.st_gid) != 0)
+           {
+             mode_mask &= ~06000;
+             if (fchown (ofd, -1, st.st_gid) == 0)
+               mode_mask |= 02000;
+           }
+       }
+      if (fchmod (ofd, st.st_mode & mode_mask) != 0)
        report_file_error ("Doing chmod", Fcons (newname, Qnil));
     }
 #endif /* not MSDOS */