From patchwork Wed Feb 28 22:16:03 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Max Filippov X-Patchwork-Id: 879460 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="i7FXNi88"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3zs9955N5Cz9s23 for ; Thu, 1 Mar 2018 09:24:41 +1100 (AEDT) Received: from localhost ([::1]:47357 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1erA9P-0001AJ-RB for incoming@patchwork.ozlabs.org; Wed, 28 Feb 2018 17:24:39 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54374) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1erA1d-0003JK-Tp for qemu-devel@nongnu.org; Wed, 28 Feb 2018 17:16:43 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1erA1Y-0003F2-Uv for qemu-devel@nongnu.org; Wed, 28 Feb 2018 17:16:37 -0500 Received: from mail-lf0-x244.google.com ([2a00:1450:4010:c07::244]:33988) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1erA1Y-0003Cs-Dg; Wed, 28 Feb 2018 17:16:32 -0500 Received: by mail-lf0-x244.google.com with SMTP id l191so5885602lfe.1; Wed, 28 Feb 2018 14:16:32 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=Jx1zurxifg0T4seD37fmT/vF/FOPjzXG0nJrQOskNXo=; b=i7FXNi88IGj3OqGio61tX7VLZJO1HZwD7wNmy6dgM5N0x+wVFy9C1LB24lPe1LXFiJ aptM4ejxv3VO2P5UKXMGB7CKpeMGMOgWSnsCYbl3NSf84CVD5ILHuNpqQT3Y33nPdRH4 xjjZLbkYSHYKdPECqwYvUjD+EDgBlqilBWQasH6MU42LKZ6NJQmsRMn7AZU7PTTAFYXq UWuFPeRIGzexzr2UbHr2zk5B04EiXNDY3GXuV9Za0RLz1XbBw2Gd8x/YZ8RGBu+RjB3I Z46OT3uePqVudjYpcrRCmYCLLbOTOd8e6tqIE2J4RlY6FLqKXvo2f8dIyQm2oYsArEG3 Lw3Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=Jx1zurxifg0T4seD37fmT/vF/FOPjzXG0nJrQOskNXo=; b=n1MBj3DtJNvyITaOg2WSF2QQhx6j+Nw58yYNzT9m5b2waBzWTRjkUxmRwmJmv/cRfl 47IRZnwHNDpYUr/pDOMe+ejLFp46drXy20o2E7aGTA3ft3uMhJVWuU0jP3PaN/73tNaf 1sDZ9UU06Nkoey06BFYcWs2Qrcu/DdhKwD9QPqCU36EedWPge4qWu/v0XjJzPU6O0e45 3a5DQyS+GZkmH7wRcroy2v8WQ6jitZMRQYowYJQZMtKn3MhYdTP5LPZJywbTbWf+cRPb QzNRvW6fjbBaoMWcSYSfwe8qsC1qx0yK+rFJHeeOwPVGduTjg6p965Kf6xReScNUU8ai 58rA== X-Gm-Message-State: AElRT7E36eu1R9kc4eOvioQ+RIfXtHeUHj3AkHxOvOemI418q/E991Vv hOvrnK0iRD9DTiW7/Xyh9md10Q== X-Google-Smtp-Source: AG47ELt5KLuYeVFilODHh4uwdaT9Cedirybxkujkxdb/jRgwXgTgJwSMmx6x/7XwEK7FiwrjY/1CFg== X-Received: by 10.25.105.18 with SMTP id e18mr652383lfc.52.1519856190988; Wed, 28 Feb 2018 14:16:30 -0800 (PST) Received: from octofox.cadence.com (jcmvbkbc-1-pt.tunnel.tserv24.sto1.ipv6.he.net. [2001:470:27:1fa::2]) by smtp.gmail.com with ESMTPSA id s82sm566984lja.7.2018.02.28.14.16.28 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 28 Feb 2018 14:16:30 -0800 (PST) From: Max Filippov To: qemu-devel@nongnu.org Date: Wed, 28 Feb 2018 14:16:03 -0800 Message-Id: <20180228221609.11265-6-jcmvbkbc@gmail.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20180228221609.11265-1-jcmvbkbc@gmail.com> References: <20180228221609.11265-1-jcmvbkbc@gmail.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:4010:c07::244 Subject: [Qemu-devel] [PATCH v2 05/11] linux-user: fix mmap/munmap/mprotect/mremap/shmat X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Max Filippov , Riku Voipio , qemu-stable@nongnu.org, Laurent Vivier Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" 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 Cc: Laurent Vivier Signed-off-by: Max Filippov --- 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();