Skip to content

Commit

Permalink
Don't dereference argv[0] when launching a script through a symlink.
Browse files Browse the repository at this point in the history
Reported-by: Joakim Tjernlund <Joakim.Tjernlund@transmode.se>
Ref: https://bugs.gentoo.org/show_bug.cgi?id=517496

Also, don't complain about non-regular or non-executable files that
are not explicitely candidates.
  • Loading branch information
cedric-vincent committed Aug 7, 2014
1 parent 205c4fa commit 520fa36
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 5 deletions.
16 changes: 12 additions & 4 deletions src/path/path.c
Expand Up @@ -219,17 +219,21 @@ int which(Tracee *tracee, const char *paths, char host_path[PATH_MAX], char *con
/* Is the command available without any $PATH look-up? */
status = realpath2(tracee, host_path, command, true);
if (status == 0 && stat(host_path, &statr) == 0) {
if (!S_ISREG(statr.st_mode)) {
if (is_explicit && !S_ISREG(statr.st_mode)) {
notice(tracee, ERROR, USER, "'%s' is not a regular file", command);
return -EACCES;
}

if ((statr.st_mode & S_IXUSR) == 0) {
if (is_explicit && (statr.st_mode & S_IXUSR) == 0) {
notice(tracee, ERROR, USER, "'%s' is not executable", command);
return -EACCES;
}

found = true;

/* Don't dereference the final component to preserve
* argv0 in case it is a symlink to script. */
(void) realpath2(tracee, host_path, command, false);
}
else
found = false;
Expand Down Expand Up @@ -274,8 +278,12 @@ int which(Tracee *tracee, const char *paths, char host_path[PATH_MAX], char *con
if (status == 0
&& stat(host_path, &statr) == 0
&& S_ISREG(statr.st_mode)
&& (statr.st_mode & S_IXUSR) != 0)
return 0;
&& (statr.st_mode & S_IXUSR) != 0) {
/* Don't dereference the final component to preserve
* argv0 in case it is a symlink to script. */
(void) realpath2(tracee, host_path, path, false);
return 0;
}
} while (*(cursor - 1) != '\0');

not_found:
Expand Down
2 changes: 1 addition & 1 deletion src/tracee/event.c
Expand Up @@ -92,7 +92,7 @@ int launch_process(Tracee *tracee)
* guest rootfs. Note: Valgrind can't handle execve(2) on
* "foreign" binaries (ENOEXEC) but can handle execvp(3) on such
* binaries. */
execvp(tracee->exe, tracee->cmdline);
execv(tracee->exe, tracee->cmdline);
return -errno;

default: /* parent */
Expand Down
51 changes: 51 additions & 0 deletions tests/test-713b6910.sh
@@ -0,0 +1,51 @@
if [ -z `which mcookie` ] || [ -z `which rm` ] || [ -z `which cat` ] || [ -z `which chmod` ] || [ -z `which ln` ] || [ -z `which grep` ] || [ -z `which mkdir` ] || [ ! -x ${ROOTFS}/bin/readlink ]; then
exit 125;
fi

######################################################################

TMP1=/tmp/$(mcookie)
TMP2=/tmp/$(mcookie)
TMP3=/tmp/$(mcookie)
TMP4=/tmp/$(mcookie)

rm -fr ${TMP1} ${TMP2} ${TMP3} ${TMP4}

######################################################################

cat > ${TMP1} <<'EOF'
#!/bin/sh
echo $0
EOF

chmod +x ${TMP1}
ln -s ${TMP1} ${TMP2}

${PROOT} ${TMP2} | grep -v ${TMP1}
${PROOT} ${TMP2} | grep ${TMP2}

######################################################################

mkdir -p ${TMP3}
cd ${TMP3}

ln -s $(which true) false
! ${PROOT} false

echo "#!$(which false)" > true
chmod a-x true
${PROOT} true

######################################################################

ln -s ${ROOTFS}/bin/readlink ${TMP4}

TEST1=$(${PROOT} ${ROOTFS}/bin/readlink /proc/self/exe)
TEST2=$(${PROOT} ${TMP4} /proc/self/exe)

test "${TEST1}" = "${TEST2}"

######################################################################

cd /
rm -fr ${TMP1} ${TMP2} ${TMP3} ${TMP4}

0 comments on commit 520fa36

Please sign in to comment.