From patchwork Tue Mar 30 18:52:11 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 49417 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 43F8AB7D0E for ; Tue, 6 Apr 2010 04:08:07 +1000 (EST) Received: from localhost ([127.0.0.1]:41591 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NyqiR-0007RG-8w for incoming@patchwork.ozlabs.org; Mon, 05 Apr 2010 14:08:03 -0400 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1NyqEs-0003Ga-GR for qemu-devel@nongnu.org; Mon, 05 Apr 2010 13:37:30 -0400 Received: from [140.186.70.92] (port=47494 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NyqEn-0003Dn-0J for qemu-devel@nongnu.org; Mon, 05 Apr 2010 13:37:29 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1NyqEk-0001Bs-Or for qemu-devel@nongnu.org; Mon, 05 Apr 2010 13:37:24 -0400 Received: from are.twiddle.net ([75.149.56.221]:60857) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1NyqEk-0001BV-FD for qemu-devel@nongnu.org; Mon, 05 Apr 2010 13:37:22 -0400 Received: by are.twiddle.net (Postfix, from userid 5000) id 83211CE6; Mon, 5 Apr 2010 10:37:21 -0700 (PDT) Message-Id: <3a524a7b48fad38a52c6df21a332374983f86a68.1270488612.git.rth@twiddle.net> In-Reply-To: References: From: Richard Henderson Date: Tue, 30 Mar 2010 11:52:11 -0700 To: qemu-devel@nongnu.org X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 2) Cc: blauwirbel@gmail.com Subject: [Qemu-devel] [PATCH 4/7] linux-user: Use guest_start_len_valid in mremap. X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Also properly signal error for non-page aligned inputs and zero sized outputs. Signed-off-by: Richard Henderson --- 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; }