You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
78 lines
2.9 KiB
78 lines
2.9 KiB
7 years ago
|
From: Pavel Raiskup <praiskup@redhat.com>
|
||
|
Date: Sat, 15 Aug 2015 04:40:57 -0400
|
||
|
Subject: install-sh: avoid (low risk) race in /tmp
|
||
|
|
||
|
Ensure that nobody can cross privilege boundaries by pre-creating
|
||
|
symlink on '$tmpdir' path.
|
||
|
|
||
|
Just testing 'mkdir -p' by creating '/tmp/ins$RANDOM-$$/d' is not
|
||
|
safe because '/tmp' directory is usually world-writeable and
|
||
|
'/tmp/ins$RANDOM-$$' content could be pretty easily guessed by
|
||
|
attacker (at least for shells where $RANDOM is not supported).
|
||
|
So, as the first step, create the '/tmp/ins$RANDOM-$$' without -p.
|
||
|
This step would fail early if somebody wanted catch us.
|
||
|
|
||
|
Note that systems that implement (and have enabled)
|
||
|
fs.protected_symlinks kernel feature are not affected even without
|
||
|
this commit.
|
||
|
|
||
|
References:
|
||
|
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=760455
|
||
|
https://bugzilla.redhat.com/show_bug.cgi?id=1140725
|
||
|
|
||
|
* lib/install-sh: Implement safer 'mkdir -p' test by running
|
||
|
'$mkdirprog $mkdir_mode "$tmpdir"' first.
|
||
|
(scriptversion): Bump.
|
||
|
|
||
|
--- a/lib/install-sh
|
||
|
+++ b/lib/install-sh
|
||
|
@@ -345,34 +345,41 @@ do
|
||
|
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
|
||
|
;;
|
||
|
*)
|
||
|
+ # $RANDOM is not portable (e.g. dash); use it when possible to
|
||
|
+ # lower collision chance
|
||
|
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
|
||
|
- trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
|
||
|
+ trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0
|
||
|
|
||
|
+ # As "mkdir -p" follows symlinks and we work in /tmp possibly; so
|
||
|
+ # create the $tmpdir first (and fail if unsuccessful) to make sure
|
||
|
+ # that nobody tries to guess the $tmpdir name.
|
||
|
if (umask $mkdir_umask &&
|
||
|
- exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
|
||
|
+ $mkdirprog $mkdir_mode "$tmpdir" &&
|
||
|
+ exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
|
||
|
then
|
||
|
if test -z "$dir_arg" || {
|
||
|
# Check for POSIX incompatibilities with -m.
|
||
|
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
|
||
|
# other-writable bit of parent directory when it shouldn't.
|
||
|
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
|
||
|
- ls_ld_tmpdir=`ls -ld "$tmpdir"`
|
||
|
+ test_tmpdir="$tmpdir/a"
|
||
|
+ ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
|
||
|
case $ls_ld_tmpdir in
|
||
|
d????-?r-*) different_mode=700;;
|
||
|
d????-?--*) different_mode=755;;
|
||
|
*) false;;
|
||
|
esac &&
|
||
|
- $mkdirprog -m$different_mode -p -- "$tmpdir" && {
|
||
|
- ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
|
||
|
+ $mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
|
||
|
+ ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
|
||
|
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
|
||
|
}
|
||
|
}
|
||
|
then posix_mkdir=:
|
||
|
fi
|
||
|
- rmdir "$tmpdir/d" "$tmpdir"
|
||
|
+ rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
|
||
|
else
|
||
|
# Remove any dirs left behind by ancient mkdir implementations.
|
||
|
- rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
|
||
|
+ rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
|
||
|
fi
|
||
|
trap '' 0;;
|
||
|
esac;;
|