aboutsummaryrefslogtreecommitdiff
path: root/include/exec
diff options
context:
space:
mode:
authorMax Filippov <jcmvbkbc@gmail.com>2018-03-07 13:50:10 -0800
committerLaurent Vivier <laurent@vivier.eu>2018-03-09 19:21:34 +0100
commitebf9a3630c911d0cfc9c20f7cafe9ba4f88cf583 (patch)
tree7ab5dec45952e20b3eca851c56504bbbcc3df102 /include/exec
parentd4247ec2d79ef2477cb886fa688706b068119736 (diff)
downloadqemu-ebf9a3630c911d0cfc9c20f7cafe9ba4f88cf583.zip
qemu-ebf9a3630c911d0cfc9c20f7cafe9ba4f88cf583.tar.gz
qemu-ebf9a3630c911d0cfc9c20f7cafe9ba4f88cf583.tar.bz2
linux-user: fix mmap/munmap/mprotect/mremap/shmat
In linux-user QEMU that runs for a target with TARGET_ABI_BITS bigger than L1_MAP_ADDR_SPACE_BITS an assertion in page_set_flags fires when mmap, munmap, mprotect, mremap or shmat is called for an address outside the guest address space. mmap and mprotect should return ENOMEM in such case. Change definition of GUEST_ADDR_MAX to always be the last valid guest address. Account for this change in open_self_maps. Add macro guest_addr_valid that verifies if the guest address is valid. Add function guest_range_valid that verifies if address range is within guest address space and does not wrap around. Use that macro in mmap/munmap/mprotect/mremap/shmat for error checking. Cc: qemu-stable@nongnu.org Cc: Riku Voipio <riku.voipio@iki.fi> Cc: Laurent Vivier <laurent@vivier.eu> Signed-off-by: Max Filippov <jcmvbkbc@gmail.com> Reviewed-by: Laurent Vivier <laurent@vivier.eu> Message-Id: <20180307215010.30706-1-jcmvbkbc@gmail.com> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Diffstat (limited to 'include/exec')
-rw-r--r--include/exec/cpu-all.h6
-rw-r--r--include/exec/cpu_ldst.h16
2 files changed, 12 insertions, 10 deletions
diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
index 0b14168..f4fa94e 100644
--- a/include/exec/cpu-all.h
+++ b/include/exec/cpu-all.h
@@ -159,8 +159,12 @@ extern unsigned long guest_base;
extern int have_guest_base;
extern unsigned long reserved_va;
-#define GUEST_ADDR_MAX (reserved_va ? reserved_va : \
+#if HOST_LONG_BITS <= TARGET_VIRT_ADDR_SPACE_BITS
+#define GUEST_ADDR_MAX (~0ul)
+#else
+#define GUEST_ADDR_MAX (reserved_va ? reserved_va - 1 : \
(1ul << TARGET_VIRT_ADDR_SPACE_BITS) - 1)
+#endif
#else
#include "exec/hwaddr.h"
diff --git a/include/exec/cpu_ldst.h b/include/exec/cpu_ldst.h
index 191f2e9..5de8c8a 100644
--- a/include/exec/cpu_ldst.h
+++ b/include/exec/cpu_ldst.h
@@ -51,15 +51,13 @@
/* All direct uses of g2h and h2g need to go away for usermode softmmu. */
#define g2h(x) ((void *)((unsigned long)(target_ulong)(x) + guest_base))
-#if HOST_LONG_BITS <= TARGET_VIRT_ADDR_SPACE_BITS
-#define h2g_valid(x) 1
-#else
-#define h2g_valid(x) ({ \
- unsigned long __guest = (unsigned long)(x) - guest_base; \
- (__guest < (1ul << TARGET_VIRT_ADDR_SPACE_BITS)) && \
- (!reserved_va || (__guest < reserved_va)); \
-})
-#endif
+#define guest_addr_valid(x) ((x) <= GUEST_ADDR_MAX)
+#define h2g_valid(x) guest_addr_valid((unsigned long)(x) - guest_base)
+
+static inline int guest_range_valid(unsigned long start, unsigned long len)
+{
+ return len - 1 <= GUEST_ADDR_MAX && start <= GUEST_ADDR_MAX - len + 1;
+}
#define h2g_nocheck(x) ({ \
unsigned long __ret = (unsigned long)(x) - guest_base; \