aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlrich Hecht <uli@suse.de>2012-01-31 12:43:16 +0100
committerStefan Hajnoczi <stefanha@linux.vnet.ibm.com>2012-02-10 10:44:51 +0000
commita6f79cc9a5efc34c5b751b2e866a4977259f3f63 (patch)
treeb1cc99e3aba35827a7af271120986719aac89eff
parent57c83dacfe179bf061b8fa79d9553ebabe4d2ff4 (diff)
linux-user: fail execve() if env/args too big
If the host's page size is equal to or smaller than the target's, native execve() will fail appropriately with E2BIG if called with too big an environment for the target to handle. It may falsely succeed, however, if the host's page size is bigger, and feed the executed target process an environment that is too big for it to handle, at which point QEMU barfs and exits, confusing procmail's autoconf script and causing the build to fail. This patch makes sure that execve() will return E2BIG if the environment is too large for the target. Signed-off-by: Ulrich Hecht <uli@suse.de> Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
-rw-r--r--linux-user/syscall.c9
1 files changed, 9 insertions, 0 deletions
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index ee8899ef3d..e868ec6aff 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -4949,6 +4949,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
abi_ulong guest_envp;
abi_ulong addr;
char **q;
+ int total_size = 0;
argc = 0;
guest_argp = arg2;
@@ -4980,6 +4981,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
break;
if (!(*q = lock_user_string(addr)))
goto execve_efault;
+ total_size += strlen(*q) + 1;
}
*q = NULL;
@@ -4991,9 +4993,16 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
break;
if (!(*q = lock_user_string(addr)))
goto execve_efault;
+ total_size += strlen(*q) + 1;
}
*q = NULL;
+ /* This case will not be caught by the host's execve() if its
+ page size is bigger than the target's. */
+ if (total_size > MAX_ARG_PAGES * TARGET_PAGE_SIZE) {
+ ret = -TARGET_E2BIG;
+ goto execve_end;
+ }
if (!(p = lock_user_string(arg1)))
goto execve_efault;
ret = get_errno(execve(p, argp, envp));