From patchwork Thu Aug 22 15:10:59 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joey Gouly X-Patchwork-Id: 13773686 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 14283C5321D for ; Thu, 22 Aug 2024 15:12:37 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 996FF6B01A4; Thu, 22 Aug 2024 11:12:36 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 946626B01A5; Thu, 22 Aug 2024 11:12:36 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 79D276B01A6; Thu, 22 Aug 2024 11:12:36 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0016.hostedemail.com [216.40.44.16]) by kanga.kvack.org (Postfix) with ESMTP id 2DB366B01A4 for ; Thu, 22 Aug 2024 11:12:36 -0400 (EDT) Received: from smtpin29.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay10.hostedemail.com (Postfix) with ESMTP id CBBECC0DF6 for ; Thu, 22 Aug 2024 15:12:35 +0000 (UTC) X-FDA: 82480223070.29.E6C3334 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by imf26.hostedemail.com (Postfix) with ESMTP id 2D32914002B for ; Thu, 22 Aug 2024 15:12:33 +0000 (UTC) Authentication-Results: imf26.hostedemail.com; dkim=none; dmarc=pass (policy=none) header.from=arm.com; spf=pass (imf26.hostedemail.com: domain of joey.gouly@arm.com designates 217.140.110.172 as permitted sender) smtp.mailfrom=joey.gouly@arm.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1724339537; a=rsa-sha256; cv=none; b=59ALeJIk6UKgVSO62exiusxs65oOkWUfjHe7bKb2LgvZqFXm2Kk2LXtpzAWC4UxVz3aSZT bWnM+YHlohWONU6Ouz3LD1+ZNVpJ3ZYQS5EV6E5OhM4QjaU1bgwubowMtkwPmybE19S7gU ixodCTOIzs8ckCTpfor7s1afHPHyru4= ARC-Authentication-Results: i=1; imf26.hostedemail.com; dkim=none; dmarc=pass (policy=none) header.from=arm.com; spf=pass (imf26.hostedemail.com: domain of joey.gouly@arm.com designates 217.140.110.172 as permitted sender) smtp.mailfrom=joey.gouly@arm.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1724339537; 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=PmUc9IZ3QQaMGDGB6yp3qr7QaJz6BkaXbPPESjB5bJ4=; b=q5NQXwizoyR05LPpfukbQZ1LzC/NNq8oXGhmoD//KEyvIgpBhqxYrf2LxRIhEyBwUwOwpU VbVefV4HMfSND8jt5sHMx9cPxDGjMxUjAs/7gA1U+dCdCmDja6O1f9Hnzc3mm5mZQ3z3jH sXBGxWbXuYThpFwc7i3r0PuJOYQUGUg= 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 8D58515A1; Thu, 22 Aug 2024 08:12:59 -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 5BB9A3F58B; Thu, 22 Aug 2024 08:12:29 -0700 (PDT) From: Joey Gouly To: linux-arm-kernel@lists.infradead.org Cc: nd@arm.com, akpm@linux-foundation.org, aneesh.kumar@kernel.org, aneesh.kumar@linux.ibm.com, anshuman.khandual@arm.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, skhan@linuxfoundation.org, szabolcs.nagy@arm.com, tglx@linutronix.de, will@kernel.org, x86@kernel.org, kvmarm@lists.linux.dev, linux-kselftest@vger.kernel.org Subject: [PATCH v5 16/30] arm64: handle PKEY/POE faults Date: Thu, 22 Aug 2024 16:10:59 +0100 Message-Id: <20240822151113.1479789-17-joey.gouly@arm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240822151113.1479789-1-joey.gouly@arm.com> References: <20240822151113.1479789-1-joey.gouly@arm.com> MIME-Version: 1.0 X-Rspam-User: X-Rspamd-Queue-Id: 2D32914002B X-Rspamd-Server: rspam01 X-Stat-Signature: fbcog1qio6d18jwbfsxcxgirt7k4gbj7 X-HE-Tag: 1724339553-910136 X-HE-Meta: U2FsdGVkX18BDcL/Duz0v8qbr2eohmvzrvP/1w76kEtjY9hMR8JQrZWCmFEam/XY/NqJ1jDyzqGQM52dBkvU5C6dp84OjNEDyzIPgVYC9G9ed82GhyXfyQm3CQ5HzIr+oHBhYcrHIZyqPo19ZBfeO54LBn/+fnNhm2wOFweJp71NaCkFKb64321zs3z9RUa7luxusG7CUpIDMNKAMDTnNFK9YlhT4MBE8EyJc5znUcJhgQQDxAieCZxtdkAOE49Oi1qjzC46UrgSOX7Vki/dsY4PpOujPChqwkIH68Pcy5a81WQSQcAJlewuUMF0IjifvBSvgs0K/hjlWtzMmwDA910gvAzDlp1gyeC6h8wdl+3WR2MVR35nowKBYD91VWCp2P5NHJg9pAeJifQDajxQ/Kw6yHZpJXxXWYrUWm5oUrAE3io8Pn9M+FyU5SnC8motOlCsan3ooXurm5svYH2xw4NOmeoJ+2pD998wZs9lD4xwTdl5iy1Lbh80kn9WkT+WqyG1I6+vAOvZXhl55TgfkRTFUNkdj0FJ06Yx1GqALoIU1jDtjn5R3BAtkdrJY0qeCdXRg0lYP1GNh+yq9dCsKTa5dwAkKYBSe8EdGvZFsD9PAR0A20+1LFoTnb7lmvQleht0dF6IocHaBvbLwABls9DWs/GTR0JNeZ/b7OLu9MFRlbfZ6Ts51KLmeZZYfv4KtyoIDfjqtJa3JC/N+Vog+aH2Zszbcu+j+lUXRONWZ3P84RWkf0fUiVMCJA8Q4XmR3aWQoEWVtdPXam+7z+/h01oWQIXMiPaj4qxMTPhnQUdt0Ma+cLqoVxrNb4Rf/1Y/dSn6cn9Hfnhk1GkVKKEBw2wD0P/FUyfHFrf9guQT6C4uD0Pv3n/Xv7g+gtKX6EPz/Qlz2yP0t9UNrvMjQV6ToMj3IQzi7sW6uVOrGmMkFruHvIIzB9sOGvX2ft62KXcIzbl2MyV0aUCiCGm5Cm0 1zMtErmR Y/F1ujm7jp+RQ1TRyNvZ4HpiqODs1jPbdf5IKzfm4rm5N/xZjzXS4f7dj7Mlr8Z5SuTvjLLZJ5+cjyPO1+htdw447mCoLY4NUzE0LPy0uvhf1wp2jBKT+eQqNZVRCFmGH+0XNuwhFYYGX/BKkcWhC0erJgfXCQqQZAL88N4//PYstuAKi5DKvLoj/HIvako2j2kmB/7lfl3wdFdWgCtA82YzZwA== 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 Reviewed-by: Catalin Marinas --- arch/arm64/include/asm/traps.h | 1 + arch/arm64/kernel/traps.c | 6 ++++ arch/arm64/mm/fault.c | 55 +++++++++++++++++++++++++++++++++- 3 files changed, 61 insertions(+), 1 deletion(-) diff --git arch/arm64/include/asm/traps.h arch/arm64/include/asm/traps.h index eefe766d6161..d780d1bd2eac 100644 --- arch/arm64/include/asm/traps.h +++ 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(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 arch/arm64/kernel/traps.c arch/arm64/kernel/traps.c index 9e22683aa921..9a11bb0db284 100644 --- arch/arm64/kernel/traps.c +++ arch/arm64/kernel/traps.c @@ -273,6 +273,12 @@ void arm64_force_sig_fault(int signo, int code, unsigned long far, force_sig_fault(signo, code, (void __user *)far); } +void arm64_force_sig_fault_pkey(unsigned long far, const char *str, int pkey) +{ + arm64_show_signal(SIGSEGV, str); + force_sig_pkuerr((void __user *)far, pkey); +} + void arm64_force_sig_mceerr(int code, unsigned long far, short lsb, const char *str) { diff --git arch/arm64/mm/fault.c arch/arm64/mm/fault.c index 451ba7cbd5ad..a68055150950 100644 --- arch/arm64/mm/fault.c +++ arch/arm64/mm/fault.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -486,6 +487,23 @@ static void do_bad_area(unsigned long far, unsigned long esr, } } +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 (!system_supports_poe()) + 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, + false); +} + static bool is_el0_instruction_abort(unsigned long esr) { return ESR_ELx_EC(esr) == ESR_ELx_EC_IABT_LOW; @@ -511,6 +529,7 @@ static int __kprobes do_page_fault(unsigned long far, unsigned long esr, unsigned long addr = untagged_addr(far); struct vm_area_struct *vma; int si_code; + int pkey = -1; if (kprobe_page_fault(regs, esr)) return 0; @@ -575,6 +594,16 @@ static int __kprobes do_page_fault(unsigned long far, unsigned long esr, count_vm_vma_lock_event(VMA_LOCK_SUCCESS); goto bad_area; } + + if (fault_from_pkey(esr, vma, mm_flags)) { + pkey = vma_pkey(vma); + vma_end_read(vma); + fault = 0; + si_code = SEGV_PKUERR; + count_vm_vma_lock_event(VMA_LOCK_SUCCESS); + goto bad_area; + } + 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); @@ -610,7 +639,16 @@ static int __kprobes do_page_fault(unsigned long far, unsigned long esr, goto bad_area; } + if (fault_from_pkey(esr, vma, mm_flags)) { + pkey = vma_pkey(vma); + mmap_read_unlock(mm); + fault = 0; + si_code = SEGV_PKUERR; + goto bad_area; + } + fault = handle_mm_fault(vma, addr, mm_flags, regs); + /* Quick path to respond to signals */ if (fault_signal_pending(fault, regs)) { if (!user_mode(regs)) @@ -669,8 +707,23 @@ static int __kprobes do_page_fault(unsigned long far, unsigned long esr, arm64_force_sig_mceerr(BUS_MCEERR_AR, far, lsb, inf->name); } else { + /* + * 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. + */ /* Something tried to access memory that out of memory map */ - arm64_force_sig_fault(SIGSEGV, si_code, far, inf->name); + if (si_code == SEGV_PKUERR) + arm64_force_sig_fault_pkey(far, inf->name, pkey); + else + arm64_force_sig_fault(SIGSEGV, si_code, far, inf->name); } return 0;