From: Max Filippov <jcmvbkbc@gmail.com>
To: qemu-devel@nongnu.org
Cc: Max Filippov <jcmvbkbc@gmail.com>,
qemu-stable@nongnu.org, Riku Voipio <riku.voipio@iki.fi>,
Laurent Vivier <laurent@vivier.eu>
Subject: [Qemu-devel] [PATCH 05/11] linux-user: fix mmap/munmap/mprotect/mremap/shmat
Date: Wed, 28 Feb 2018 13:06:10 -0800 [thread overview]
Message-ID: <20180228210616.2756-6-jcmvbkbc@gmail.com> (raw)
In-Reply-To: <20180228210616.2756-1-jcmvbkbc@gmail.com>
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.
Introduce macro 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>
---
include/exec/cpu-all.h | 2 +-
include/exec/cpu_ldst.h | 12 +++++++-----
linux-user/mmap.c | 20 +++++++++++++++-----
linux-user/syscall.c | 3 +++
4 files changed, 26 insertions(+), 11 deletions(-)
diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
index 0b141683f095..12bd049997ac 100644
--- a/include/exec/cpu-all.h
+++ b/include/exec/cpu-all.h
@@ -160,7 +160,7 @@ extern int have_guest_base;
extern unsigned long reserved_va;
#define GUEST_ADDR_MAX (reserved_va ? reserved_va : \
- (1ul << TARGET_VIRT_ADDR_SPACE_BITS) - 1)
+ (2ul << (TARGET_VIRT_ADDR_SPACE_BITS - 1)) - 1)
#else
#include "exec/hwaddr.h"
diff --git a/include/exec/cpu_ldst.h b/include/exec/cpu_ldst.h
index 191f2e962a3c..bbf6988bc725 100644
--- a/include/exec/cpu_ldst.h
+++ b/include/exec/cpu_ldst.h
@@ -53,14 +53,16 @@
#if HOST_LONG_BITS <= TARGET_VIRT_ADDR_SPACE_BITS
#define h2g_valid(x) 1
+#define guest_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)); \
-})
+#define h2g_valid(x) guest_valid((unsigned long)(x) - guest_base)
+#define guest_valid(x) ((x) <= GUEST_ADDR_MAX)
#endif
+#define guest_range_valid(start, len) \
+ ({unsigned long l = (len); \
+ guest_valid(l) && (start) <= GUEST_ADDR_MAX - l; })
+
#define h2g_nocheck(x) ({ \
unsigned long __ret = (unsigned long)(x) - guest_base; \
(abi_ulong)__ret; \
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 0fbfd6dff20d..df81f9b803b6 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -80,8 +80,9 @@ int target_mprotect(abi_ulong start, abi_ulong len, int prot)
return -EINVAL;
len = TARGET_PAGE_ALIGN(len);
end = start + len;
- if (end < start)
- return -EINVAL;
+ if (!guest_range_valid(start, len)) {
+ return -ENOMEM;
+ }
prot &= PROT_READ | PROT_WRITE | PROT_EXEC;
if (len == 0)
return 0;
@@ -481,8 +482,8 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
* It can fail only on 64-bit host with 32-bit target.
* On any other target/host host mmap() handles this error correctly.
*/
- if ((unsigned long)start + len - 1 > (abi_ulong) -1) {
- errno = EINVAL;
+ if (!guest_range_valid(start, len)) {
+ errno = ENOMEM;
goto fail;
}
@@ -622,8 +623,10 @@ int target_munmap(abi_ulong start, abi_ulong len)
if (start & ~TARGET_PAGE_MASK)
return -EINVAL;
len = TARGET_PAGE_ALIGN(len);
- if (len == 0)
+ if (len == 0 || !guest_range_valid(start, len)) {
return -EINVAL;
+ }
+
mmap_lock();
end = start + len;
real_start = start & qemu_host_page_mask;
@@ -678,6 +681,13 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
int prot;
void *host_addr;
+ if (!guest_range_valid(old_addr, old_size) ||
+ ((flags & MREMAP_FIXED) &&
+ !guest_range_valid(new_addr, new_size))) {
+ errno = ENOMEM;
+ return -1;
+ }
+
mmap_lock();
if (flags & MREMAP_FIXED) {
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index e24f43c4a259..79245e73784f 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -4900,6 +4900,9 @@ static inline abi_ulong do_shmat(CPUArchState *cpu_env,
return -TARGET_EINVAL;
}
}
+ if (!guest_range_valid(shmaddr, shm_info.shm_segsz)) {
+ return -TARGET_EINVAL;
+ }
mmap_lock();
--
2.11.0
next prev parent reply other threads:[~2018-02-28 21:06 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-02-28 21:06 [Qemu-devel] [PATCH 00/11] linux-user support for target/xtensa Max Filippov
2018-02-28 21:06 ` [Qemu-devel] [PATCH 01/11] target/xtensa: dump correct physical registers Max Filippov
2018-02-28 21:06 ` [Qemu-devel] [PATCH 02/11] target/xtensa: mark register windows in the dump Max Filippov
2018-02-28 21:06 ` [Qemu-devel] [PATCH 03/11] target/xtensa: use correct number of registers in gdbstub Max Filippov
2018-02-28 21:06 ` [Qemu-devel] [PATCH 04/11] target/xtensa: support MTTCG Max Filippov
2018-02-28 21:06 ` Max Filippov [this message]
2018-02-28 21:06 ` [Qemu-devel] [PATCH 06/11] linux-user: fix assertion in shmdt Max Filippov
2018-02-28 21:06 ` [Qemu-devel] [PATCH 07/11] linux-user: fix target_mprotect/target_munmap error return values Max Filippov
2018-02-28 21:06 ` [Qemu-devel] [PATCH 08/11] linux-user: drop unused target_msync function Max Filippov
2018-02-28 21:06 ` [Qemu-devel] [PATCH 09/11] target/xtensa: add linux-user support Max Filippov
2018-02-28 21:06 ` [Qemu-devel] [PATCH 10/11] qemu-binfmt-conf.sh: add qemu-xtensa Max Filippov
2018-02-28 21:06 ` [Qemu-devel] [PATCH 11/11] MAINTAINERS: fix W: address for xtensa Max Filippov
2018-02-28 21:27 ` [Qemu-devel] [PATCH 00/11] linux-user support for target/xtensa no-reply
2018-02-28 21:51 ` no-reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180228210616.2756-6-jcmvbkbc@gmail.com \
--to=jcmvbkbc@gmail.com \
--cc=laurent@vivier.eu \
--cc=qemu-devel@nongnu.org \
--cc=qemu-stable@nongnu.org \
--cc=riku.voipio@iki.fi \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).