From patchwork Fri May 3 13:01:33 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joey Gouly X-Patchwork-Id: 13652794 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 172DBC4345F for ; Fri, 3 May 2024 13:02:50 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 7AD9F6B00A9; Fri, 3 May 2024 09:02:48 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 711366B00AB; Fri, 3 May 2024 09:02:48 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 429E76B00AC; Fri, 3 May 2024 09:02:48 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0017.hostedemail.com [216.40.44.17]) by kanga.kvack.org (Postfix) with ESMTP id 1415E6B00A9 for ; Fri, 3 May 2024 09:02:48 -0400 (EDT) Received: from smtpin24.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay01.hostedemail.com (Postfix) with ESMTP id CA3B01C16B8 for ; Fri, 3 May 2024 13:02:47 +0000 (UTC) X-FDA: 82077099174.24.C8AF5B6 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by imf15.hostedemail.com (Postfix) with ESMTP id F2940A001D for ; Fri, 3 May 2024 13:02:45 +0000 (UTC) Authentication-Results: imf15.hostedemail.com; dkim=none; spf=pass (imf15.hostedemail.com: domain of joey.gouly@arm.com designates 217.140.110.172 as permitted sender) smtp.mailfrom=joey.gouly@arm.com; dmarc=pass (policy=none) header.from=arm.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1714741366; a=rsa-sha256; cv=none; b=WlRS1cVwXjYtHLYGx3Ixu2pEBj9cAC+0J7pQ6aaL6cY+G51uGz0l9wvXRbOqHzBl5pnkYG Lwk+SdiwPUEQQRoFVkOXD+QkboGolIS7/k6lAzM4o1l8hU+fLWj60h+a050Gj9lOKKdKoY IVVsIBl+QybtZ2//eP/epHY5xKHSF/w= ARC-Authentication-Results: i=1; imf15.hostedemail.com; dkim=none; spf=pass (imf15.hostedemail.com: domain of joey.gouly@arm.com designates 217.140.110.172 as permitted sender) smtp.mailfrom=joey.gouly@arm.com; dmarc=pass (policy=none) header.from=arm.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1714741366; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=KBI5PC2Sjgr5q/lRbWwQKGtcG+FQFgqzDWWR8xEOTc4=; b=PM6GFQHGAMRRWcylrUKIOfJlp3MhKORv1UyX8NuoQPQX7SErl119mbayogwycknTapqd2k qcsCwHNe1Nhyyzn1kzX3Rj5Y4XFVC23nTqXLewobarUu2SW5MPUW1witU6p0w+1+3z2bnl qIt3+FY4cebNj1i5e8xE4UgnCoQX+YI= Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 6F8C416F2; Fri, 3 May 2024 06:03:10 -0700 (PDT) Received: from e124191.cambridge.arm.com (e124191.cambridge.arm.com [10.1.197.45]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 1ECA63F73F; Fri, 3 May 2024 06:02:42 -0700 (PDT) From: Joey Gouly To: linux-arm-kernel@lists.infradead.org Cc: akpm@linux-foundation.org, aneesh.kumar@kernel.org, aneesh.kumar@linux.ibm.com, bp@alien8.de, broonie@kernel.org, catalin.marinas@arm.com, christophe.leroy@csgroup.eu, dave.hansen@linux.intel.com, hpa@zytor.com, joey.gouly@arm.com, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, linuxppc-dev@lists.ozlabs.org, maz@kernel.org, mingo@redhat.com, mpe@ellerman.id.au, naveen.n.rao@linux.ibm.com, npiggin@gmail.com, oliver.upton@linux.dev, shuah@kernel.org, szabolcs.nagy@arm.com, tglx@linutronix.de, will@kernel.org, x86@kernel.org, kvmarm@lists.linux.dev Subject: [PATCH v4 15/29] arm64: handle PKEY/POE faults Date: Fri, 3 May 2024 14:01:33 +0100 Message-Id: <20240503130147.1154804-16-joey.gouly@arm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240503130147.1154804-1-joey.gouly@arm.com> References: <20240503130147.1154804-1-joey.gouly@arm.com> MIME-Version: 1.0 X-Stat-Signature: cujicfb16zxb3xtcmjo9tduxqrsokycp X-Rspam-User: X-Rspamd-Server: rspam02 X-Rspamd-Queue-Id: F2940A001D X-HE-Tag: 1714741365-419627 X-HE-Meta: U2FsdGVkX1+3zDy34cT3ycjYispE6tKIcMuczbqQwNV5WYH8vRMSqZJxPsg1zkYazgXBAU/TNhBwYb+QAbOq1e2uyo6jhjTu1K1p32hWAnjewtlUt/QoZnRC8AmIK4Gir5i4tRdGvDW4d+qYNXNd0YkwJWYmCqdNrOIQW9nbRbwCQ57UOTkGX6Nn2oNfbHbHE7pLmS3fq00I3KNc1OyGIYWkauVVwV99TLEBk07/z/a59VSj27NdQG5xazc6F6PHk9UHJINF5kqJTnsLdFcku+Xia8o6kjvVGidqILCqSqwprG3BB1G9ys/mgHUJ5tebpql0XNm13CVbwbm2OfiHk9McBFrSvFsaKZjGVB3wOUbvA0uRhczyWbI/CIV+h8MxmVQQyHnIWjI2sT4HZhyiPvzRZGqv9xnCXIIImurYXOzju9E0QNQa0lnb/mIgoQnI5nROYbAiyn48j0Upyzlci25XJF0YIy2ES8w6OhACPWMVWzJhBPHpOhbCit99nDSvEx8atzLLjIB2oMdG5HNOO1dR8jWJ+hM8ZZwhNll4UoXafaXRs44GZ5314vYLsfPrmumiYbYlJgjryvzu8FQnOZrNyXGAcWai8EQxdZ3tsyzR5kjYk++WwQhrQqeQxUeJFIT12C0eiIgFe7vzAovLh0mejYKesM6s+uUbjcW3qVYvb1l0JOcNeQDOAot2LHdfgxlm7DLDFyNFcvtkxFaCn3m+4WfYeKsxuB2XoGSMTIJWYhrgHR+0gvPbzS5196slkzm/gv7Btg7bzTmds6j4niJ+Ib0RxJI5a3S7GdJ8gWglAEAYsEUlM2qqC1S7A1lJYJKLNMySpObXbqXovM6qEbcEZBQ55msHG6yVbTOGj8OPfD4s45Jq3hIihBeD3fH4i26ro8KPM6SLcRtRNUsBxvwq5FQjp0qF+Y4MtgIChv7suocQI7xKKb5/hTaE+LQyDjYsu+86bwFSDgZ37k7 YliwIZnC 5DZLu5cs7dc1D24SIdoJJtPJQ9xC4OU1/EmVUneIt+96kjF+Pv848U6r9D08X55OivyWdsKhcLivdxuzC7xVvDwjP/qBjjpvsuq6U5PH1t32woqkZ4k7fG/S+VLHay9hprA0z5vG13l+k7xGN12dWO/cmYTbxu2hOZvIAKRutiW+iUO8hCKXTc2gV5jkW1YoDtgpitjiQJQXG9eP+y9NGQ86nXth3A1RhVYr7 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: List-Subscribe: List-Unsubscribe: If a memory fault occurs that is due to an overlay/pkey fault, report that to userspace with a SEGV_PKUERR. Signed-off-by: Joey Gouly Cc: Catalin Marinas Cc: Will Deacon --- arch/arm64/include/asm/traps.h | 1 + arch/arm64/kernel/traps.c | 12 ++++++-- arch/arm64/mm/fault.c | 56 ++++++++++++++++++++++++++++++++-- 3 files changed, 64 insertions(+), 5 deletions(-) diff --git a/arch/arm64/include/asm/traps.h b/arch/arm64/include/asm/traps.h index eefe766d6161..f6f6f2cb7f10 100644 --- a/arch/arm64/include/asm/traps.h +++ b/arch/arm64/include/asm/traps.h @@ -25,6 +25,7 @@ try_emulate_armv8_deprecated(struct pt_regs *regs, u32 insn) void force_signal_inject(int signal, int code, unsigned long address, unsigned long err); void arm64_notify_segfault(unsigned long addr); void arm64_force_sig_fault(int signo, int code, unsigned long far, const char *str); +void arm64_force_sig_fault_pkey(int signo, int code, unsigned long far, const char *str, int pkey); void arm64_force_sig_mceerr(int code, unsigned long far, short lsb, const char *str); void arm64_force_sig_ptrace_errno_trap(int errno, unsigned long far, const char *str); diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index 215e6d7f2df8..1bac6c84d3f5 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c @@ -263,16 +263,24 @@ static void arm64_show_signal(int signo, const char *str) __show_regs(regs); } -void arm64_force_sig_fault(int signo, int code, unsigned long far, - const char *str) +void arm64_force_sig_fault_pkey(int signo, int code, unsigned long far, + const char *str, int pkey) { arm64_show_signal(signo, str); if (signo == SIGKILL) force_sig(SIGKILL); + else if (code == SEGV_PKUERR) + force_sig_pkuerr((void __user *)far, pkey); else force_sig_fault(signo, code, (void __user *)far); } +void arm64_force_sig_fault(int signo, int code, unsigned long far, + const char *str) +{ + arm64_force_sig_fault_pkey(signo, code, far, str, 0); +} + void arm64_force_sig_mceerr(int code, unsigned long far, short lsb, const char *str) { diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index 8251e2fea9c7..585295168918 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -489,6 +490,23 @@ static void do_bad_area(unsigned long far, unsigned long esr, #define VM_FAULT_BADMAP ((__force vm_fault_t)0x010000) #define VM_FAULT_BADACCESS ((__force vm_fault_t)0x020000) +static bool fault_from_pkey(unsigned long esr, struct vm_area_struct *vma, + unsigned int mm_flags) +{ + unsigned long iss2 = ESR_ELx_ISS2(esr); + + if (!arch_pkeys_enabled()) + return false; + + if (iss2 & ESR_ELx_Overlay) + return true; + + return !arch_vma_access_permitted(vma, + mm_flags & FAULT_FLAG_WRITE, + mm_flags & FAULT_FLAG_INSTRUCTION, + mm_flags & FAULT_FLAG_REMOTE); +} + static vm_fault_t __do_page_fault(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long addr, unsigned int mm_flags, unsigned long vm_flags, @@ -529,6 +547,8 @@ static int __kprobes do_page_fault(unsigned long far, unsigned long esr, unsigned int mm_flags = FAULT_FLAG_DEFAULT; unsigned long addr = untagged_addr(far); struct vm_area_struct *vma; + bool pkey_fault = false; + int pkey = -1; if (kprobe_page_fault(regs, esr)) return 0; @@ -590,6 +610,12 @@ static int __kprobes do_page_fault(unsigned long far, unsigned long esr, vma_end_read(vma); goto lock_mmap; } + + if (fault_from_pkey(esr, vma, mm_flags)) { + vma_end_read(vma); + goto lock_mmap; + } + fault = handle_mm_fault(vma, addr, mm_flags | FAULT_FLAG_VMA_LOCK, regs); if (!(fault & (VM_FAULT_RETRY | VM_FAULT_COMPLETED))) vma_end_read(vma); @@ -617,6 +643,11 @@ static int __kprobes do_page_fault(unsigned long far, unsigned long esr, goto done; } + if (fault_from_pkey(esr, vma, mm_flags)) { + pkey_fault = true; + pkey = vma_pkey(vma); + } + fault = __do_page_fault(mm, vma, addr, mm_flags, vm_flags, regs); /* Quick path to respond to signals */ @@ -682,9 +713,28 @@ static int __kprobes do_page_fault(unsigned long far, unsigned long esr, * Something tried to access memory that isn't in our memory * map. */ - arm64_force_sig_fault(SIGSEGV, - fault == VM_FAULT_BADACCESS ? SEGV_ACCERR : SEGV_MAPERR, - far, inf->name); + int fault_kind; + /* + * The pkey value that we return to userspace can be different + * from the pkey that caused the fault. + * + * 1. T1 : mprotect_key(foo, PAGE_SIZE, pkey=4); + * 2. T1 : set POR_EL0 to deny access to pkey=4, touches, page + * 3. T1 : faults... + * 4. T2: mprotect_key(foo, PAGE_SIZE, pkey=5); + * 5. T1 : enters fault handler, takes mmap_lock, etc... + * 6. T1 : reaches here, sees vma_pkey(vma)=5, when we really + * faulted on a pte with its pkey=4. + */ + + if (pkey_fault) + fault_kind = SEGV_PKUERR; + else + fault_kind = fault == VM_FAULT_BADACCESS ? SEGV_ACCERR : SEGV_MAPERR; + + arm64_force_sig_fault_pkey(SIGSEGV, + fault_kind, + far, inf->name, pkey); } return 0;