[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 4/7] linux-user: Use guest_start_len_valid in mremap
From: |
Richard Henderson |
Subject: |
[Qemu-devel] [PATCH 4/7] linux-user: Use guest_start_len_valid in mremap. |
Date: |
Tue, 30 Mar 2010 11:52:11 -0700 |
Also properly signal error for non-page aligned inputs
and zero sized outputs.
Signed-off-by: Richard Henderson <address@hidden>
---
linux-user/mmap.c | 44 ++++++++++++++++++++++++--------------------
1 files changed, 24 insertions(+), 20 deletions(-)
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index f4d44a8..463679d 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -657,37 +657,40 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong
old_size,
abi_ulong new_addr)
{
int prot;
- void *host_addr;
+ void *host_addr = MAP_FAILED;
- mmap_lock();
+ if (new_size == 0 || (old_addr & ~TARGET_PAGE_MASK)) {
+ errno = EINVAL;
+ return -1;
+ }
- if (flags & MREMAP_FIXED)
- host_addr = (void *) syscall(__NR_mremap, g2h(old_addr),
- old_size, new_size,
- flags,
- new_addr);
- else if (flags & MREMAP_MAYMOVE) {
- abi_ulong mmap_start;
+ mmap_lock();
- mmap_start = mmap_find_vma(0, new_size);
+ /* ??? If host page size > target page size, we can fail here
+ when we shouldn't. */
+ if (flags & MREMAP_FIXED) {
+ if (new_addr & ~TARGET_PAGE_MASK) {
+ errno = EINVAL;
+ } else {
+ host_addr = (void *) syscall(__NR_mremap, g2h(old_addr),
+ old_size, new_size, flags, new_addr);
+ }
+ } else if (flags & MREMAP_MAYMOVE) {
+ abi_ulong mmap_start = mmap_find_vma(0, new_size);
if (mmap_start == -1) {
errno = ENOMEM;
- host_addr = MAP_FAILED;
- } else
+ } else {
host_addr = (void *) syscall(__NR_mremap, g2h(old_addr),
old_size, new_size,
flags | MREMAP_FIXED,
g2h(mmap_start));
- } else {
- host_addr = mremap(g2h(old_addr), old_size, new_size, flags);
- /* Check if address fits target address space */
- if ((unsigned long)host_addr + new_size > (abi_ulong)-1) {
- /* Revert mremap() changes */
- host_addr = mremap(g2h(old_addr), new_size, old_size, flags);
- errno = ENOMEM;
- host_addr = MAP_FAILED;
}
+ } else if (guest_start_len_valid(old_addr, new_size)) {
+ host_addr = mremap(g2h(old_addr), old_size, new_size, flags);
+ assert(host_addr == g2h(old_addr) || host_addr == MAP_FAILED);
+ } else {
+ errno = ENOMEM;
}
if (host_addr == MAP_FAILED) {
@@ -698,6 +701,7 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong
old_size,
page_set_flags(old_addr, old_addr + old_size, 0);
page_set_flags(new_addr, new_addr + new_size, prot | PAGE_VALID);
}
+
mmap_unlock();
return new_addr;
}
--
1.6.6.1
- [Qemu-devel] [PATCH 0/7] Fix tests for start+len address valid for guest, Richard Henderson, 2010/04/05
- [Qemu-devel] [PATCH 1/7] target-sparc: Fix TARGET_{PHYS, VIRT}_ADDR_SPACE_BITS., Richard Henderson, 2010/04/05
- [Qemu-devel] [PATCH 7/7] Use guest_start_len_valid in page_check_range., Richard Henderson, 2010/04/05
- [Qemu-devel] [PATCH 3/7] linux-user: Use guest_start_len_valid in msync., Richard Henderson, 2010/04/05
- [Qemu-devel] [PATCH 6/7] Fix zero-length write(2)., Richard Henderson, 2010/04/05
- [Qemu-devel] [PATCH 2/7] Add guest_start_len_valid function., Richard Henderson, 2010/04/05
- [Qemu-devel] [PATCH 5/7] linux-user: Use guest_start_len_valid in mmap., Richard Henderson, 2010/04/05
- [Qemu-devel] [PATCH 4/7] linux-user: Use guest_start_len_valid in mremap.,
Richard Henderson <=