If the address range starting at old_address overlaps with the stack guard it is invalid and mremap must fail with EFAULT. The musl c library relies on this behavior to detect the stack size, which it does by doing consecutive mremaps until it hits the stack guard. Without this patch, software (such as the Ruby interpreter) that calls pthread_getattr_np under musl will crash on 32 bit targets emulated on a 64 bit host.
Signed-off-by: Tobias Koch <tobias.k...@nonterra.com> --- linux-user/mmap.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/linux-user/mmap.c b/linux-user/mmap.c index 8685f02e7e..62cddbd072 100644 --- a/linux-user/mmap.c +++ b/linux-user/mmap.c @@ -651,6 +651,12 @@ int target_munmap(abi_ulong start, abi_ulong len) return ret; } +#ifdef TARGET_HPPA +#define STACK_GROWS_DOWN 0 +#else +#define STACK_GROWS_DOWN 1 +#endif + abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size, abi_ulong new_size, unsigned long flags, abi_ulong new_addr) @@ -665,6 +671,26 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size, return -1; } + /* Check that we're not overlapping with the stack guard. */ + if (reserved_va) { + abi_ulong guard_size, guard_start; + + guard_size = TARGET_PAGE_SIZE < qemu_real_host_page_size ? + qemu_real_host_page_size : TARGET_PAGE_SIZE; + + if (STACK_GROWS_DOWN) { + guard_start = reserved_va - guest_stack_size - guard_size; + } else { + guard_start = reserved_va - guard_size; + } + + if (guard_start < old_addr + old_size && + old_addr < guard_start + guard_size) { + errno = EFAULT; + return -1; + } + } + mmap_lock(); if (flags & MREMAP_FIXED) { -- 2.20.1