From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.5 required=3.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED,DKIM_INVALID,DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS, URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4F81AC4363C for ; Wed, 7 Oct 2020 07:39:47 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id 79BC7212CC for ; Wed, 7 Oct 2020 07:39:46 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=google.com header.i=@google.com header.b="ruoXB4q0" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 79BC7212CC Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id B349B900003; Wed, 7 Oct 2020 03:39:45 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id ABD75900002; Wed, 7 Oct 2020 03:39:45 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 95CB6900003; Wed, 7 Oct 2020 03:39:45 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0021.hostedemail.com [216.40.44.21]) by kanga.kvack.org (Postfix) with ESMTP id 605B5900002 for ; Wed, 7 Oct 2020 03:39:45 -0400 (EDT) Received: from smtpin28.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay02.hostedemail.com (Postfix) with ESMTP id E7CF13628 for ; Wed, 7 Oct 2020 07:39:44 +0000 (UTC) X-FDA: 77344329888.28.skirt68_22161a2271cd Received: from filter.hostedemail.com (10.5.16.251.rfc1918.com [10.5.16.251]) by smtpin28.hostedemail.com (Postfix) with ESMTP id C10BF6C05 for ; Wed, 7 Oct 2020 07:39:44 +0000 (UTC) X-HE-Tag: skirt68_22161a2271cd X-Filterd-Recvd-Size: 9031 Received: from mail-wr1-f65.google.com (mail-wr1-f65.google.com [209.85.221.65]) by imf45.hostedemail.com (Postfix) with ESMTP for ; Wed, 7 Oct 2020 07:39:44 +0000 (UTC) Received: by mail-wr1-f65.google.com with SMTP id m6so979931wrn.0 for ; Wed, 07 Oct 2020 00:39:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=RYwEGS7gOxFlwuQRTr7QM+pg66rzdyTCfIUfekhpUBo=; b=ruoXB4q0W4dOYr0HkGK3Qg2MUNaxXi9Tfm5XoN+wJuao1gaRUueT0KcnNUVdAc6i7R ad7CYmcCeYVK++bMrK+3TtUU+XRMTKATzz4A0NJN3o7RmWQUbCtCU/k7VX8UmjxZCcLx 90FV/U6rqDEoHznYihJVKIjTp59Cgm6dxLKO0y4kB8P9aqgDO09c+9jYYxfNjQeQwLeT 0iJgvI4hvfuLW4QF6oH+DgdLqWEER3NlD8sgZ8ZestVegmAZlB3/yPVxiKvaoeSu1NTg gTBMILXz/Q4NZ/g/+Fxx+UK5QvpWKKFVUDzwBk6TTlfiUYgu85IgWeCGYmrwbyzcKAGT TBSw== 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:mime-version :content-transfer-encoding; bh=RYwEGS7gOxFlwuQRTr7QM+pg66rzdyTCfIUfekhpUBo=; b=rmoRR3NiNd5kTHIABrsVk1uVFUkXvGVREcE6LGS/2A8cDKsuEnRcUKLPeS5oXIHhU/ lyVErB9Dcjttrh3a1q8a8qglJfiH/jL+NH3qUInECOEiX8HB+Oy+kgDk7D0e602xUQZe QljjYhmwnYG5sl0knRsiEvalXFgn+olZ4NTSy79zL+MsfNAhchjbFmaxj/+VwcO1g3br 4CA4EMqeldx8VTaP9AvlwtAc3RJho4R0504baleFNWmQ+YldqhHGkcSE8v3Z972DsJZH xgVS8dO/n2sm861PU5xZpi8ex1NF0b/GpPjgfcWxrnky349neyLOOBYMauB0cEnLjZx3 DW2w== X-Gm-Message-State: AOAM533sJYPolSizBkj2gu9r7SCyLU4i1mxmb+5nCpPXBwozP7QALsi0 pGCqqRv0sLUSa3Nig3AXCyrO5w== X-Google-Smtp-Source: ABdhPJx+7ke9fEecAqH/fAr9lPYggeTnVTs2kZ4YZOSai+UmsGlcT1A4NpyX9005g+lQnoEoGseTpw== X-Received: by 2002:adf:e88a:: with SMTP id d10mr2072440wrm.247.1602056382670; Wed, 07 Oct 2020 00:39:42 -0700 (PDT) Received: from localhost ([2a02:168:96c5:1:55ed:514f:6ad7:5bcc]) by smtp.gmail.com with ESMTPSA id r3sm1639024wrm.51.2020.10.07.00.39.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 07 Oct 2020 00:39:41 -0700 (PDT) From: Jann Horn To: "David S. Miller" , sparclinux@vger.kernel.org, Andrew Morton , linux-mm@kvack.org Cc: linux-kernel@vger.kernel.org, Khalid Aziz , Christoph Hellwig , Anthony Yznaga , Catalin Marinas , Will Deacon , linux-arm-kernel@lists.infradead.org, Michael Ellerman , Benjamin Herrenschmidt , Paul Mackerras , linuxppc-dev@lists.ozlabs.org Subject: [PATCH 1/2] mm/mprotect: Call arch_validate_prot under mmap_lock and with length Date: Wed, 7 Oct 2020 09:39:31 +0200 Message-Id: <20201007073932.865218-1-jannh@google.com> X-Mailer: git-send-email 2.28.0.806.g8561365e88-goog MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: arch_validate_prot() is a hook that can validate whether a given set of protection flags is valid in an mprotect() operation. It is given the set of protection flags and the address being modified. However, the address being modified can currently not actually be used in a meaningful way because: 1. Only the address is given, but not the length, and the operation can span multiple VMAs. Therefore, the callee can't actually tell which virtual address range, or which VMAs, are being targeted. 2. The mmap_lock is not held, meaning that if the callee were to check the VMA at @addr, that VMA would be unrelated to the one the operation is performed on. Currently, custom arch_validate_prot() handlers are defined by arm64, powerpc and sparc. arm64 and powerpc don't care about the address range, they just check the flags against CPU support masks. sparc's arch_validate_prot() attempts to look at the VMA, but doesn't tak= e the mmap_lock. Change the function signature to also take a length, and move the arch_validate_prot() call in mm/mprotect.c down into the locked region. Cc: stable@vger.kernel.org Fixes: 9035cf9a97e4 ("mm: Add address parameter to arch_validate_prot()") Suggested-by: Khalid Aziz Suggested-by: Christoph Hellwig Signed-off-by: Jann Horn --- arch/arm64/include/asm/mman.h | 4 ++-- arch/powerpc/include/asm/mman.h | 3 ++- arch/powerpc/kernel/syscalls.c | 2 +- arch/sparc/include/asm/mman.h | 6 ++++-- include/linux/mman.h | 3 ++- mm/mprotect.c | 6 ++++-- 6 files changed, 15 insertions(+), 9 deletions(-) diff --git a/arch/arm64/include/asm/mman.h b/arch/arm64/include/asm/mman.= h index 081ec8de9ea6..0876a87986dc 100644 --- a/arch/arm64/include/asm/mman.h +++ b/arch/arm64/include/asm/mman.h @@ -23,7 +23,7 @@ static inline pgprot_t arch_vm_get_page_prot(unsigned l= ong vm_flags) #define arch_vm_get_page_prot(vm_flags) arch_vm_get_page_prot(vm_flags) =20 static inline bool arch_validate_prot(unsigned long prot, - unsigned long addr __always_unused) + unsigned long addr __always_unused, unsigned long len __always_unused) { unsigned long supported =3D PROT_READ | PROT_WRITE | PROT_EXEC | PROT_S= EM; =20 @@ -32,6 +32,6 @@ static inline bool arch_validate_prot(unsigned long pro= t, =20 return (prot & ~supported) =3D=3D 0; } -#define arch_validate_prot(prot, addr) arch_validate_prot(prot, addr) +#define arch_validate_prot(prot, addr, len) arch_validate_prot(prot, add= r, len) =20 #endif /* ! __ASM_MMAN_H__ */ diff --git a/arch/powerpc/include/asm/mman.h b/arch/powerpc/include/asm/m= man.h index 7cb6d18f5cd6..65dd9b594985 100644 --- a/arch/powerpc/include/asm/mman.h +++ b/arch/powerpc/include/asm/mman.h @@ -36,7 +36,8 @@ static inline pgprot_t arch_vm_get_page_prot(unsigned l= ong vm_flags) } #define arch_vm_get_page_prot(vm_flags) arch_vm_get_page_prot(vm_flags) =20 -static inline bool arch_validate_prot(unsigned long prot, unsigned long = addr) +static inline bool arch_validate_prot(unsigned long prot, unsigned long = addr, + unsigned long len) { if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC | PROT_SEM | PROT_SAO)) return false; diff --git a/arch/powerpc/kernel/syscalls.c b/arch/powerpc/kernel/syscall= s.c index 078608ec2e92..b1fabb97d138 100644 --- a/arch/powerpc/kernel/syscalls.c +++ b/arch/powerpc/kernel/syscalls.c @@ -43,7 +43,7 @@ static inline long do_mmap2(unsigned long addr, size_t = len, { long ret =3D -EINVAL; =20 - if (!arch_validate_prot(prot, addr)) + if (!arch_validate_prot(prot, addr, len)) goto out; =20 if (shift) { diff --git a/arch/sparc/include/asm/mman.h b/arch/sparc/include/asm/mman.= h index f94532f25db1..e85222c76585 100644 --- a/arch/sparc/include/asm/mman.h +++ b/arch/sparc/include/asm/mman.h @@ -52,9 +52,11 @@ static inline pgprot_t sparc_vm_get_page_prot(unsigned= long vm_flags) return (vm_flags & VM_SPARC_ADI) ? __pgprot(_PAGE_MCD_4V) : __pgprot(0)= ; } =20 -#define arch_validate_prot(prot, addr) sparc_validate_prot(prot, addr) -static inline int sparc_validate_prot(unsigned long prot, unsigned long = addr) +#define arch_validate_prot(prot, addr, len) sparc_validate_prot(prot, ad= dr, len) +static inline int sparc_validate_prot(unsigned long prot, unsigned long = addr, + unsigned long len) { + mmap_assert_write_locked(current->mm); if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC | PROT_SEM | PROT_ADI)) return 0; if (prot & PROT_ADI) { diff --git a/include/linux/mman.h b/include/linux/mman.h index 6f34c33075f9..5b4d554d3189 100644 --- a/include/linux/mman.h +++ b/include/linux/mman.h @@ -96,7 +96,8 @@ static inline void vm_unacct_memory(long pages) * * Returns true if the prot flags are valid */ -static inline bool arch_validate_prot(unsigned long prot, unsigned long = addr) +static inline bool arch_validate_prot(unsigned long prot, unsigned long = addr, + unsigned long len) { return (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC | PROT_SEM)) =3D=3D= 0; } diff --git a/mm/mprotect.c b/mm/mprotect.c index ce8b8a5eacbb..e2d6b51acbf8 100644 --- a/mm/mprotect.c +++ b/mm/mprotect.c @@ -533,14 +533,16 @@ static int do_mprotect_pkey(unsigned long start, si= ze_t len, end =3D start + len; if (end <=3D start) return -ENOMEM; - if (!arch_validate_prot(prot, start)) - return -EINVAL; =20 reqprot =3D prot; =20 if (mmap_write_lock_killable(current->mm)) return -EINTR; =20 + error =3D -EINVAL; + if (!arch_validate_prot(prot, start, len)) + goto out; + /* * If userspace did not allocate the pkey, do not let * them use it here. base-commit: c85fb28b6f999db9928b841f63f1beeb3074eeca --=20 2.28.0.806.g8561365e88-goog