mirror of https://github.com/proot-me/proot.git
Fix the expansion of argv[] for scripts.
This commit is contained in:
parent
ce2d1c4bbd
commit
fc1ca713b8
|
@ -190,23 +190,37 @@ end:
|
||||||
int expand_shebang(Tracee *tracee, char host_path[PATH_MAX], char user_path[PATH_MAX])
|
int expand_shebang(Tracee *tracee, char host_path[PATH_MAX], char user_path[PATH_MAX])
|
||||||
{
|
{
|
||||||
ArrayOfXPointers *argv = NULL;
|
ArrayOfXPointers *argv = NULL;
|
||||||
bool argv_has_changed = false;
|
|
||||||
char argument[ARG_MAX];
|
char argument[ARG_MAX];
|
||||||
int status;
|
int status;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
/* "The interpreter must be a valid pathname for an executable
|
/* "The interpreter must be a valid pathname for an executable
|
||||||
* which is not itself a script." -- man 2 execve
|
* which is not itself a script [1]. If the filename
|
||||||
|
* argument of execve() specifies an interpreter script, then
|
||||||
|
* interpreter will be invoked with the following arguments:
|
||||||
*
|
*
|
||||||
* As of this writing (3.10.17) this true only for the ELF
|
* interpreter [optional-arg] filename arg...
|
||||||
* interpreter; ie. a script can use a script as
|
*
|
||||||
* interpreter. */
|
* where arg... is the series of words pointed to by the argv
|
||||||
|
* argument of execve()." -- man 2 execve
|
||||||
|
*
|
||||||
|
* [1]: as of this writing (3.10.17) this true only for the
|
||||||
|
* ELF interpreter; ie. a script can use a script as
|
||||||
|
* interpreter.
|
||||||
|
*/
|
||||||
for (i = 0; i < MAXSYMLINKS; i++) {
|
for (i = 0; i < MAXSYMLINKS; i++) {
|
||||||
|
char *old_user_path;
|
||||||
|
|
||||||
/* Translate this path (user -> host), then check it is executable. */
|
/* Translate this path (user -> host), then check it is executable. */
|
||||||
status = translate_and_check_exec(tracee, host_path, user_path);
|
status = translate_and_check_exec(tracee, host_path, user_path);
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
|
/* Remember the initial user path. */
|
||||||
|
old_user_path = talloc_strdup(tracee->ctx, user_path);
|
||||||
|
if (old_user_path == NULL)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
/* Extract into user_path and argument the shebang from host_path. */
|
/* Extract into user_path and argument the shebang from host_path. */
|
||||||
status = extract_shebang(tracee, host_path, user_path, argument);
|
status = extract_shebang(tracee, host_path, user_path, argument);
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
|
@ -216,6 +230,11 @@ int expand_shebang(Tracee *tracee, char host_path[PATH_MAX], char user_path[PATH
|
||||||
if (status == 0)
|
if (status == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
/* Translate new path (user -> host), then check it is executable. */
|
||||||
|
status = translate_and_check_exec(tracee, host_path, user_path);
|
||||||
|
if (status < 0)
|
||||||
|
return status;
|
||||||
|
|
||||||
/* Fetch argv[] only on demand. */
|
/* Fetch argv[] only on demand. */
|
||||||
if (argv == NULL) {
|
if (argv == NULL) {
|
||||||
status = fetch_array_of_xpointers(tracee, &argv, SYSARG_2, 0);
|
status = fetch_array_of_xpointers(tracee, &argv, SYSARG_2, 0);
|
||||||
|
@ -223,19 +242,14 @@ int expand_shebang(Tracee *tracee, char host_path[PATH_MAX], char user_path[PATH
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Translate new path (user -> host), then check it is executable. */
|
/* Assuming the shebang of "script" is "#!/bin/sh -x",
|
||||||
status = translate_and_check_exec(tracee, host_path, user_path);
|
* a call to:
|
||||||
if (status < 0)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
/* "If the filename argument of execve() specifies an
|
|
||||||
* interpreter script, then interpreter will be
|
|
||||||
* invoked with the following arguments:
|
|
||||||
*
|
*
|
||||||
* interpreter [optional-arg] filename arg...
|
* execve("./script", { "script.sh", NULL }, ...)
|
||||||
*
|
*
|
||||||
* where arg... is the series of words pointed to by
|
* becomes:
|
||||||
* the argv argument of execve()." -- man 2 execve
|
*
|
||||||
|
* execve("/bin/sh", { "/bin/sh", "-x", "./script", NULL }, ...)
|
||||||
*
|
*
|
||||||
* See commit 8c8fbe85 about "argv->length == 1". */
|
* See commit 8c8fbe85 about "argv->length == 1". */
|
||||||
if (argument[0] != '\0') {
|
if (argument[0] != '\0') {
|
||||||
|
@ -243,7 +257,7 @@ int expand_shebang(Tracee *tracee, char host_path[PATH_MAX], char user_path[PATH
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
status = write_xpointees(argv, 0, 2, user_path, argument);
|
status = write_xpointees(argv, 0, 3, user_path, argument, old_user_path);
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -252,16 +266,14 @@ int expand_shebang(Tracee *tracee, char host_path[PATH_MAX], char user_path[PATH
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
status = write_xpointees(argv, 0, 1, user_path);
|
status = write_xpointees(argv, 0, 2, user_path, old_user_path);
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
argv_has_changed = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Push argv[] only on demand. */
|
/* Push argv[] only on demand. */
|
||||||
if (argv_has_changed) {
|
if (argv != NULL) {
|
||||||
status = push_array_of_xpointers(argv, SYSARG_2);
|
status = push_array_of_xpointers(argv, SYSARG_2);
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
return status;
|
return status;
|
||||||
|
|
|
@ -99,7 +99,7 @@ setup: $(ROOTFS)/bin/true $(ROOTFS)/bin/false \
|
||||||
$(ROOTFS)/bin/pwd $(ROOTFS)/bin/readlink $(ROOTFS)/bin/symlink \
|
$(ROOTFS)/bin/pwd $(ROOTFS)/bin/readlink $(ROOTFS)/bin/symlink \
|
||||||
$(ROOTFS)/bin/abs-true $(ROOTFS)/bin/rel-true $(ROOTFS)/bin/echo \
|
$(ROOTFS)/bin/abs-true $(ROOTFS)/bin/rel-true $(ROOTFS)/bin/echo \
|
||||||
$(ROOTFS)/bin/argv0 $(ROOTFS)/bin/readdir $(ROOTFS)/bin/cat $(ROOTFS)/tmp \
|
$(ROOTFS)/bin/argv0 $(ROOTFS)/bin/readdir $(ROOTFS)/bin/cat $(ROOTFS)/tmp \
|
||||||
$(ROOTFS)/bin/chdir_getcwd $(ROOTFS)/bin/fchdir_getcwd \
|
$(ROOTFS)/bin/chdir_getcwd $(ROOTFS)/bin/fchdir_getcwd $(ROOTFS)/bin/argv \
|
||||||
$(ROOTFS)/bin/fork-wait $(ROOTFS)/bin/ptrace $(ROOTFS)/bin/ptrace-2
|
$(ROOTFS)/bin/fork-wait $(ROOTFS)/bin/ptrace $(ROOTFS)/bin/ptrace-2
|
||||||
|
|
||||||
$(ROOTFS)/tmp:
|
$(ROOTFS)/tmp:
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < argc; i++)
|
||||||
|
printf("%s ", argv[i]);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
if [ ! -x ${ROOTFS}/bin/argv ] || [ -z `which mcookie` ] || [ -z `which mkdir` ] || [ -z `which chmod` ] || [ -z `which env` ] || [ -z `which rm` ] || [ -z `which grep` ] || [ -z `which env` ] || [ -z `which ln` ]; then
|
||||||
|
exit 125;
|
||||||
|
fi
|
||||||
|
|
||||||
|
BIN_DIR=/tmp/$(mcookie)
|
||||||
|
TMP=$(mcookie)
|
||||||
|
TMP2=$(mcookie)
|
||||||
|
|
||||||
|
mkdir ${BIN_DIR}
|
||||||
|
echo "#! ${ROOTFS}/bin/argv -x" > ${BIN_DIR}/${TMP}
|
||||||
|
chmod +x ${BIN_DIR}/${TMP}
|
||||||
|
ln -s ${BIN_DIR}/${TMP} ${BIN_DIR}/${TMP2}
|
||||||
|
|
||||||
|
${PROOT} env ${BIN_DIR}/${TMP} | grep "${ROOTFS}/bin/argv -x ${BIN_DIR}/${TMP}"
|
||||||
|
|
||||||
|
${PROOT} env PATH=${BIN_DIR} ${TMP} | grep "${ROOTFS}/bin/argv -x ${BIN_DIR}/${TMP}"
|
||||||
|
|
||||||
|
(cd ${BIN_DIR}; ${PROOT} env ./${TMP}) | grep "${ROOTFS}/bin/argv -x ./${TMP}"
|
||||||
|
|
||||||
|
${PROOT} env ${BIN_DIR}/${TMP2} | grep "${ROOTFS}/bin/argv -x ${BIN_DIR}/${TMP2}"
|
||||||
|
|
||||||
|
${PROOT} env PATH=${BIN_DIR} ${TMP2} | grep "${ROOTFS}/bin/argv -x ${BIN_DIR}/${TMP2}"
|
||||||
|
|
||||||
|
(cd ${BIN_DIR}; ${PROOT} env ./${TMP2}) | grep "${ROOTFS}/bin/argv -x ./${TMP2}"
|
||||||
|
|
||||||
|
${PROOT} ${BIN_DIR}/${TMP} | grep "${ROOTFS}/bin/argv -x ${BIN_DIR}/${TMP}"
|
||||||
|
|
||||||
|
env PATH=${BIN_DIR} ${PROOT} ${TMP} | grep "${ROOTFS}/bin/argv -x ${BIN_DIR}/${TMP}"
|
||||||
|
|
||||||
|
# TODO: (cd ${BIN_DIR}; ${PROOT} ./${TMP}) | grep "${ROOTFS}/bin/argv -x ./${TMP}"
|
||||||
|
|
||||||
|
rm -fr ${BIN_DIR}
|
Loading…
Reference in New Issue