diff options
author | Max Filippov <jcmvbkbc@gmail.com> | 2018-09-17 11:13:14 -0700 |
---|---|---|
committer | Laurent Vivier <laurent@vivier.eu> | 2018-09-25 22:36:49 +0200 |
commit | 5dfa88f7162f390463b227940e84a23af5407744 (patch) | |
tree | 4cac8b67ae543ad0723c94dd48c9d8c088bf98f7 | |
parent | 58cfa6c2e6eb51b23cc98f81d16136b3ca929b31 (diff) | |
download | qemu-5dfa88f7162f390463b227940e84a23af5407744.zip qemu-5dfa88f7162f390463b227940e84a23af5407744.tar.gz qemu-5dfa88f7162f390463b227940e84a23af5407744.tar.bz2 |
linux-user: do setrlimit selectively
setrlimit guest calls that affect memory resources
(RLIMIT_{AS,DATA,STACK}) may interfere with QEMU internal memory
management. They may result in QEMU lockup because mprotect call in
page_unprotect would fail with ENOMEM error code, causing infinite loop
of SIGSEGV. E.g. it happens when running libstdc++ testsuite for xtensa
target on x86_64 host.
Don't call host setrlimit for memory-related resources.
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Message-Id: <20180917181314.22551-1-jcmvbkbc@gmail.com>
[lv: rebase on master]
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
-rw-r--r-- | linux-user/syscall.c | 16 |
1 files changed, 15 insertions, 1 deletions
diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 019af63..ae3c0df 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -7879,7 +7879,21 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, rlim.rlim_cur = target_to_host_rlim(target_rlim->rlim_cur); rlim.rlim_max = target_to_host_rlim(target_rlim->rlim_max); unlock_user_struct(target_rlim, arg2, 0); - return get_errno(setrlimit(resource, &rlim)); + /* + * If we just passed through resource limit settings for memory then + * they would also apply to QEMU's own allocations, and QEMU will + * crash or hang or die if its allocations fail. Ideally we would + * track the guest allocations in QEMU and apply the limits ourselves. + * For now, just tell the guest the call succeeded but don't actually + * limit anything. + */ + if (resource != RLIMIT_AS && + resource != RLIMIT_DATA && + resource != RLIMIT_STACK) { + return get_errno(setrlimit(resource, &rlim)); + } else { + return 0; + } } #endif #ifdef TARGET_NR_getrlimit |