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
