@@ -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;
}
Also properly signal error for non-page aligned inputs and zero sized outputs. Signed-off-by: Richard Henderson <rth@twiddle.net> --- linux-user/mmap.c | 44 ++++++++++++++++++++++++-------------------- 1 files changed, 24 insertions(+), 20 deletions(-)