From: Joel Holdsworth <joel.holdsworth@vcatechnology.com>
To: qemu-devel@nongnu.org
Cc: Vasileios.Kalintiris@imgtec.com, riku.voipio@iki.fi,
Joel Holdsworth <joel.holdsworth@vcatechnology.com>
Subject: [Qemu-devel] [PATCH v2 2/4] linux-user: pass environment arguments in execve
Date: Tue, 14 Jun 2016 20:26:20 +0100 [thread overview]
Message-ID: <1465932382-28645-3-git-send-email-joel.holdsworth@vcatechnology.com> (raw)
In-Reply-To: <1465932382-28645-1-git-send-email-joel.holdsworth@vcatechnology.com>
Previously, when emulating execve(2), qemu would execute a child
instance of the emulator with the environment variables provided by
the parent process. This caused problems with qemu if any of the
variables affected the child emulator's behaviour e.g.
LD_LIBRARY_PATH.
This patch solves this issue by passing the environment variables
with '-E' arguments to the child qemu instance. The call to
execve(2) is replaced by a call to execv(2) so that the parent
emulator's environment variable state is propagated into the child.
Any variables from the host environment that are not in the in the
execve() call are removed with a '-U' argument.
---
linux-user/syscall.c | 96 ++++++++++++++++++++++++++++++++++++++--------------
1 file changed, 70 insertions(+), 26 deletions(-)
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index a478f56..440986e 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -6665,9 +6665,13 @@ static abi_long qemu_execve(char *filename, char *argv[],
char *envp[])
{
char *i_arg = NULL, *i_name = NULL;
- char **new_argp;
- int argc, fd, ret, i, offset = 3;
+ char **qemu_argp, **argp;
+ int i, j;
+ size_t qemu_argc = 3, argc, host_envc, envpc;
+ int fd, ret;
char *cp;
+ size_t def_envc = 0, undef_envc = 0;
+ char **def_env, **undef_env;
char buf[BINPRM_BUF_SIZE];
/* normal execve case */
@@ -6675,10 +6679,12 @@ static abi_long qemu_execve(char *filename, char *argv[],
return get_errno(execve(filename, argv, envp));
}
- for (argc = 0; argv[argc] != NULL; argc++) {
- /* nothing */ ;
- }
+ /* count the number of arguments and environment variables */
+ for (argc = 0; argv[argc]; argc++);
+ for (host_envc = 0; environ[host_envc]; host_envc++);
+ for (envpc = 0; envp[envpc]; envpc++);
+ /* read the file header so we can check the shebang */
fd = open(filename, O_RDONLY);
if (fd == -1) {
return get_errno(fd);
@@ -6739,36 +6745,74 @@ static abi_long qemu_execve(char *filename, char *argv[],
i_arg = cp;
}
- if (i_arg) {
- offset = 5;
- } else {
- offset = 4;
- }
+ if (i_arg)
+ qemu_argc += 2;
+ else
+ qemu_argc += 1;
+ }
+
+ /* list environment variables to define */
+ def_env = alloca((envpc + 1) * sizeof(envp[0]));
+ for (i = 0; i != envpc; i++) {
+ for (j = 0; j != host_envc; j++)
+ if (!strcmp(envp[i], environ[j]))
+ break;
+ if (j == host_envc)
+ def_env[def_envc++] = envp[i];
}
- new_argp = alloca((argc + offset + 1) * sizeof(void *));
+ qemu_argc += def_envc * 2;
- /* Copy the original arguments with offset */
- for (i = 0; i < argc; i++) {
- new_argp[i + offset] = argv[i];
+ /* list environment variables to undefine */
+ undef_env = alloca((host_envc + 1) * sizeof(undef_env[0]));
+ for (i = 0; i != host_envc; i++) {
+ const char *const host_env = environ[i];
+ const size_t key_len = strchr(host_env, '=') - host_env;
+ for (j = 0; j != envpc; j++)
+ if (!strncmp(host_env, envp[j], key_len))
+ break;
+ if (j == envpc)
+ undef_env[undef_envc++] = strndup(environ[i], key_len);
}
- new_argp[0] = strdup(qemu_execve_path);
- new_argp[1] = strdup("-0");
- new_argp[offset] = filename;
- new_argp[argc + offset] = NULL;
+ qemu_argc += undef_envc * 2;
- if (i_name) {
- new_argp[2] = i_name;
- new_argp[3] = i_name;
+ /* allocate the argument list */
+ argp = qemu_argp = alloca((qemu_argc + 1) * sizeof(void *));
- if (i_arg) {
- new_argp[4] = i_arg;
- }
+ /* set up the qemu arguments */
+ *argp++ = strdup(qemu_execve_path);
+
+ /* add arguments for the enironment variables */
+ for (i = 0; i < def_envc; i++) {
+ *argp++ = strdup("-E");
+ *argp++ = def_env[i];
+ }
+
+ for (i = 0; i < undef_envc; i++) {
+ *argp++ = strdup("-U");
+ *argp++ = undef_env[i];
+ }
+
+ /* add the path to the executable */
+ *argp++ = strdup("-0");
+ if (i_name) {
+ *argp++ = i_name;
+ *argp++ = i_name;
+ if (i_arg)
+ *argp++ = i_arg;
} else {
- new_argp[2] = argv[0];
+ *argp++ = argv[0];
}
+ *argp++ = filename;
+
+ /* copy the original arguments with offset */
+ for (i = 1; i < argc; i++)
+ *argp++ = argv[i];
+
+ *argp++ = NULL;
+
/* Although execve() is not an interruptible syscall it is
* a special case where we must use the safe_syscall wrapper:
* if we allow a signal to happen before we make the host
@@ -6779,7 +6823,7 @@ static abi_long qemu_execve(char *filename, char *argv[],
* before the execve completes and makes it the other
* program's problem.
*/
- return get_errno(safe_execve(qemu_execve_path, new_argp, envp));
+ return get_errno(safe_execve(qemu_execve_path, qemu_argp, environ));
}
/* do_syscall() should always have a single exit point at the end so
--
1.9.1
next prev parent reply other threads:[~2016-06-14 19:26 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-06-14 19:26 [Qemu-devel] linux-user: add option to intercept execve() syscalls Joel Holdsworth
2016-06-14 19:26 ` [Qemu-devel] [PATCH v2 1/4] " Joel Holdsworth
2016-06-15 19:31 ` Laurent Vivier
2016-06-20 20:04 ` Joel Holdsworth
2016-06-14 19:26 ` Joel Holdsworth [this message]
2016-06-15 19:59 ` [Qemu-devel] [PATCH v2 2/4] linux-user: pass environment arguments in execve Laurent Vivier
2016-06-20 19:51 ` Joel Holdsworth
2016-06-20 20:29 ` Laurent Vivier
2016-06-20 21:27 ` Joel Holdsworth
2016-06-20 21:40 ` Peter Maydell
2016-06-20 22:15 ` Joel Holdsworth
2016-06-20 22:54 ` Peter Maydell
2016-06-14 19:26 ` [Qemu-devel] [PATCH v2 3/4] linux-user: pass elf interpreter prefix " Joel Holdsworth
2016-06-15 20:06 ` Laurent Vivier
2016-06-20 19:57 ` Joel Holdsworth
2016-06-14 19:26 ` [Qemu-devel] [PATCH v2 4/4] linux-user: pass strace argument " Joel Holdsworth
2016-06-15 20:37 ` Laurent Vivier
2016-06-20 20:02 ` Joel Holdsworth
-- strict thread matches above, loose matches on Subject: below --
2016-06-20 20:08 [Qemu-devel] [PATCH v2 2/4] linux-user: pass environment arguments " Riku Voipio
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1465932382-28645-3-git-send-email-joel.holdsworth@vcatechnology.com \
--to=joel.holdsworth@vcatechnology.com \
--cc=Vasileios.Kalintiris@imgtec.com \
--cc=qemu-devel@nongnu.org \
--cc=riku.voipio@iki.fi \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).