qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] linux-user: mremap fails with EFAULT if address range overlaps w


From: Tobias Koch
Subject: [PATCH] linux-user: mremap fails with EFAULT if address range overlaps with stack guard
Date: Thu, 5 Mar 2020 22:05:34 +0100

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 <address@hidden>
---
 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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]