aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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));