From patchwork Wed Feb 28 21:06:10 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Max Filippov X-Patchwork-Id: 10249755 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 5529860212 for ; Wed, 28 Feb 2018 21:10:57 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 43FE228DAD for ; Wed, 28 Feb 2018 21:10:57 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 38A3A28DB5; Wed, 28 Feb 2018 21:10:57 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.3 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, FROM_LOCAL_NOVOWEL, HK_RANDOM_FROM, RCVD_IN_DNSWL_HI, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 7B5ED28DAD for ; Wed, 28 Feb 2018 21:10:56 +0000 (UTC) Received: from localhost ([::1]:46938 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1er903-00014B-Nk for patchwork-qemu-devel@patchwork.kernel.org; Wed, 28 Feb 2018 16:10:55 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46264) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1er8vs-0005h5-8N for qemu-devel@nongnu.org; Wed, 28 Feb 2018 16:06:39 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1er8vq-0000Wh-Tc for qemu-devel@nongnu.org; Wed, 28 Feb 2018 16:06:36 -0500 Received: from mail-lf0-x243.google.com ([2a00:1450:4010:c07::243]:36948) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1er8vq-0000Va-I1; Wed, 28 Feb 2018 16:06:34 -0500 Received: by mail-lf0-x243.google.com with SMTP id y19so5627488lfd.4; Wed, 28 Feb 2018 13:06:34 -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=hQA/t/Y6LW0ZKM1PaDvH4Bux3F0lsNl13AFnd2Cha0YyVrHjy69dlwPQ1/eyHe4K4m 2Z921IYmczoJgrDShXcJKg55lJhP9PFElhhElXpQDMk11BQ7s9U3EmIky5gBsyPENoE4 GdRFMC2P4iFcbQfIz1hiB9iG5clxfiDw2lyDkfBkxu2JmMI2f5DGOrbzI+7K4w6LjpB4 MuQd00IDzv8PQDOqhhYZbedjTy2lsrdsLBuU8J51IYIUeoNXsMlDxJVQW1uzjCTeTVhV m7WFPx7T1CAUcKM9ytI2h+bh9s9aVS58s9IxmyEcawA9KMCJbZHW7H1jRs+yx31W1AAD vX3A== 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=MiFMe3Q3QGXPYIbWlYXsBEGH5WWv7GiKrZoh/zSUvkw0SM/dkcEEws0tjnnxqd2E6k ZjfQLJkY67NkxEs6usEUe4KdUYv2jAoD61dy+DQOXmyHgedx6EmYwvoyFbYghhV905uk I0NSw55VvAPgOhZjTq5aRbst79eBkTA7fn4RuYlppCGYX/FpJVVbxL4I/1km0uOutIED OY6AdDyVcqbr7gZ1kyLp4knOfCORrFN/F2tlNgRtle/WBVK97DaV0EDQUn4jZKHV8lon MrsOarDrWomyfciatYtYI646guujXyCzAuNMtoIgskNAMW5skfaRxVJwa36MQcdGGBQ/ SZVA== X-Gm-Message-State: APf1xPAZmCr67W45hcwsgkBhRuw7vWH77vmHlFHd3mfXe8qWDYkwXc/F mnfNXgTRseEainQZ40CmfbUCEg== X-Google-Smtp-Source: AG47ELvOVK4MQWk51cfJ5MuL53XS3CLFAroGtm5J/dPROkGvg1aWBmyaTArYuE9TxrIgfjKMLb+6fQ== X-Received: by 10.46.122.15 with SMTP id v15mr14962452ljc.141.1519851993077; Wed, 28 Feb 2018 13:06:33 -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 l8sm547134lfb.19.2018.02.28.13.06.30 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 28 Feb 2018 13:06:32 -0800 (PST) From: Max Filippov To: qemu-devel@nongnu.org Date: Wed, 28 Feb 2018 13:06:10 -0800 Message-Id: <20180228210616.2756-6-jcmvbkbc@gmail.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20180228210616.2756-1-jcmvbkbc@gmail.com> References: <20180228210616.2756-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::243 Subject: [Qemu-devel] [PATCH 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+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP 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();