summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2012-11-20 13:15:34 -0800
committerPaul Eggert <eggert@cs.ucla.edu>2012-11-20 13:17:16 -0800
commit505fb47dc1743ea5411479276d825e4714bef312 (patch)
tree777330f8b6a79df15a0f64278fee1ccba9012e39
parent8041e6b62cc829fe6442003fc5be636771a569a1 (diff)
downloadcoreutils-505fb47dc1743ea5411479276d825e4714bef312.tar.xz
install: fix security race
* src/copy.c (copy_internal): Use DST_MODE_BITS, not SRC_MODE. See Bernhard R. Link in <http://bugs.gnu.org/12947> and in <http://bugs.debian.org/598018>.
-rw-r--r--src/copy.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/src/copy.c b/src/copy.c
index 16aed036d..7a354140a 100644
--- a/src/copy.c
+++ b/src/copy.c
@@ -2394,8 +2394,13 @@ copy_internal (char const *src_name, char const *dst_name,
/* POSIX says the permission bits of the source file must be
used as the 3rd argument in the open call. Historical
practice passed all the source mode bits to 'open', but the extra
- bits were ignored, so it should be the same either way. */
- if (! copy_reg (src_name, dst_name, x, src_mode & S_IRWXUGO,
+ bits were ignored, so it should be the same either way.
+
+ This call uses DST_MODE_BITS, not SRC_MODE. These are
+ normally the same, and the exception (where x->set_mode) is
+ used only by 'install', which POSIX does not specify and
+ where DST_MODE_BITS is what's wanted. */
+ if (! copy_reg (src_name, dst_name, x, dst_mode_bits & S_IRWXUGO,
omitted_permissions, &new_dst, &src_sb))
goto un_backup;
}