From patchwork Mon Nov 6 08:57:13 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ram Pai X-Patchwork-Id: 834578 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [103.22.144.68]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3yVpJz04YDz9s4s for ; Mon, 6 Nov 2017 21:12:35 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="RvBx1HYz"; dkim-atps=neutral Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 3yVpJy60G1zDrK1 for ; Mon, 6 Nov 2017 21:12:34 +1100 (AEDT) Authentication-Results: lists.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="RvBx1HYz"; dkim-atps=neutral X-Original-To: linuxppc-dev@lists.ozlabs.org Delivered-To: linuxppc-dev@lists.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gmail.com (client-ip=2607:f8b0:400d:c0d::242; helo=mail-qt0-x242.google.com; envelope-from=ram.n.pai@gmail.com; receiver=) Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="RvBx1HYz"; dkim-atps=neutral Received: from mail-qt0-x242.google.com (mail-qt0-x242.google.com [IPv6:2607:f8b0:400d:c0d::242]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 3yVmhT1hKjzDrJx for ; Mon, 6 Nov 2017 19:59:21 +1100 (AEDT) Received: by mail-qt0-x242.google.com with SMTP id h4so9978505qtk.8 for ; Mon, 06 Nov 2017 00:59:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=23595Mb75LDgee3M8YfkN9D4MUXeLpV8VmKLmm3LgwU=; b=RvBx1HYz44e4J+06PMW0oGbTARwdMl9uyDQuGnh17iC2wX/nM6Ylx/eTxtl/FtUJp5 4tVvWJ9hCUvNZ91xebl3Ph15NKmxUdKtZCTO2Y+8XJK7ZlzOIcwkZ3Ve2tImT6wRf8h0 HIshwDK0dkosd9v5i32h/lj3yNeZdkoBLS28PLv2zAaEocvdZTIZCcqoBDaXWu5RNdg8 W9corWW7tLw+KeG0JSasCgQeL8AukyzXqPcsiJfcqxGdugXnA5FAfojMP9I/KQslPAdg JXhBiwaE9/xXQKJnyNfH13WbRZ8oAwVN2103ld7qu+rnmKI6Dybhq5c22mT9F3xUBcJ1 Cuog== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=23595Mb75LDgee3M8YfkN9D4MUXeLpV8VmKLmm3LgwU=; b=ddnXCky2HLtziHESPN1E/vlgbGYBLaB/mGZq1Q/W9U3jOJ93zK4FKUHDc+6uPFE3NQ QPjA07v3phjwbG1nklQuBhQgflWNdMfh2/3N9e7wLgCdwJL1qazNhtALNQWrVz+kdaeM xfLqSb3otHb1Yp4oHIbdIlw97S7XQLVpSzuzr+q68OBDwFqx2KPF8q0nnka8sKBP8pM0 x4tLd97VTL6N+FX7dymgVqxCkLesoWumZkYE+FZFuaMz7lYabN1B+wx+jAxiYytjty9R 7Z7aGOq8A6kRgryL7r5Asq8OVR1zhdirrO2wU1vkn5IAGzLoC3A22ys7TCWyjk2GDsvG q7+w== X-Gm-Message-State: AMCzsaV9KKVl1ax5vH2mBy5u+N2R5+vZrz/BweR41YkZY8jw7a8xyxrv SDybDlRvHFDKhX2CrwsXTjE= X-Google-Smtp-Source: ABhQp+Qer5heRtwWyQb1mdBC7/tox+AVvGNEzqg/HDOaBmemokD4UAS+dxcHUVGGWFSt6DOf84o9Vg== X-Received: by 10.237.55.102 with SMTP id i93mr22959567qtb.333.1509958759304; Mon, 06 Nov 2017 00:59:19 -0800 (PST) Received: from localhost.localdomain (50-39-103-96.bvtn.or.frontiernet.net. [50.39.103.96]) by smtp.gmail.com with ESMTPSA id r26sm8001094qki.42.2017.11.06.00.59.16 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 06 Nov 2017 00:59:18 -0800 (PST) From: Ram Pai To: mpe@ellerman.id.au, mingo@redhat.com, akpm@linux-foundation.org, corbet@lwn.net, arnd@arndb.de Subject: [PATCH v9 21/51] powerpc: Deliver SEGV signal on pkey violation Date: Mon, 6 Nov 2017 00:57:13 -0800 Message-Id: <1509958663-18737-22-git-send-email-linuxram@us.ibm.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1509958663-18737-1-git-send-email-linuxram@us.ibm.com> References: <1509958663-18737-1-git-send-email-linuxram@us.ibm.com> X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.24 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-arch@vger.kernel.org, ebiederm@xmission.com, linux-doc@vger.kernel.org, x86@kernel.org, dave.hansen@intel.com, linux-kernel@vger.kernel.org, linuxram@us.ibm.com, mhocko@kernel.org, linux-mm@kvack.org, paulus@samba.org, aneesh.kumar@linux.vnet.ibm.com, linux-kselftest@vger.kernel.org, bauerman@linux.vnet.ibm.com, linuxppc-dev@lists.ozlabs.org, khandual@linux.vnet.ibm.com Errors-To: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org Sender: "Linuxppc-dev" The value of the pkey, whose protection got violated, is made available in si_pkey field of the siginfo structure. Signed-off-by: Ram Pai --- arch/powerpc/include/asm/bug.h | 1 + arch/powerpc/kernel/traps.c | 12 ++++++++- arch/powerpc/mm/fault.c | 55 ++++++++++++++++++++++----------------- 3 files changed, 43 insertions(+), 25 deletions(-) diff --git a/arch/powerpc/include/asm/bug.h b/arch/powerpc/include/asm/bug.h index 3c04249..97c3847 100644 --- a/arch/powerpc/include/asm/bug.h +++ b/arch/powerpc/include/asm/bug.h @@ -133,6 +133,7 @@ extern int do_page_fault(struct pt_regs *, unsigned long, unsigned long); extern void bad_page_fault(struct pt_regs *, unsigned long, int); extern void _exception(int, struct pt_regs *, int, unsigned long); +extern void _exception_pkey(int, struct pt_regs *, int, unsigned long, int); extern void die(const char *, struct pt_regs *, long); extern bool die_will_crash(void); diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 13c9dcd..ed1c39b 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -265,7 +266,9 @@ void user_single_step_siginfo(struct task_struct *tsk, info->si_addr = (void __user *)regs->nip; } -void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr) + +void _exception_pkey(int signr, struct pt_regs *regs, int code, unsigned long addr, + int key) { siginfo_t info; const char fmt32[] = KERN_INFO "%s[%d]: unhandled signal %d " \ @@ -292,9 +295,16 @@ void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr) info.si_signo = signr; info.si_code = code; info.si_addr = (void __user *) addr; + info.si_pkey = key; + force_sig_info(signr, &info, current); } +void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr) +{ + _exception_pkey(signr, regs, code, addr, 0); +} + void system_reset_exception(struct pt_regs *regs) { /* diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index dfcd0e4..84523ed 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c @@ -107,7 +107,8 @@ static bool store_updates_sp(struct pt_regs *regs) */ static int -__bad_area_nosemaphore(struct pt_regs *regs, unsigned long address, int si_code) +__bad_area_nosemaphore(struct pt_regs *regs, unsigned long address, int si_code, + int pkey) { /* * If we are in kernel mode, bail out with a SEGV, this will @@ -117,17 +118,18 @@ static bool store_updates_sp(struct pt_regs *regs) if (!user_mode(regs)) return SIGSEGV; - _exception(SIGSEGV, regs, si_code, address); + _exception_pkey(SIGSEGV, regs, si_code, address, pkey); return 0; } static noinline int bad_area_nosemaphore(struct pt_regs *regs, unsigned long address) { - return __bad_area_nosemaphore(regs, address, SEGV_MAPERR); + return __bad_area_nosemaphore(regs, address, SEGV_MAPERR, 0); } -static int __bad_area(struct pt_regs *regs, unsigned long address, int si_code) +static int __bad_area(struct pt_regs *regs, unsigned long address, int si_code, + int pkey) { struct mm_struct *mm = current->mm; @@ -137,30 +139,18 @@ static int __bad_area(struct pt_regs *regs, unsigned long address, int si_code) */ up_read(&mm->mmap_sem); - return __bad_area_nosemaphore(regs, address, si_code); + return __bad_area_nosemaphore(regs, address, si_code, pkey); } static noinline int bad_area(struct pt_regs *regs, unsigned long address) { - return __bad_area(regs, address, SEGV_MAPERR); + return __bad_area(regs, address, SEGV_MAPERR, 0); } -static int bad_page_fault_exception(struct pt_regs *regs, unsigned long address, - int si_code) +static int bad_key_fault_exception(struct pt_regs *regs, unsigned long address, + int pkey) { - int sig = SIGBUS; - int code = BUS_OBJERR; - -#ifdef CONFIG_PPC_MEM_KEYS - if (si_code & DSISR_KEYFAULT) { - perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address); - sig = SIGSEGV; - code = SEGV_PKUERR; - } -#endif /* CONFIG_PPC_MEM_KEYS */ - - _exception(sig, regs, code, address); - return 0; + return __bad_area_nosemaphore(regs, address, SEGV_PKUERR, pkey); } static int do_sigbus(struct pt_regs *regs, unsigned long address, @@ -411,7 +401,16 @@ static int __do_page_fault(struct pt_regs *regs, unsigned long address, if (unlikely(page_fault_is_bad(error_code))) { if (!is_user) return SIGBUS; - return bad_page_fault_exception(regs, address, error_code); + + if (error_code & DSISR_KEYFAULT) { + perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, + address); + return bad_key_fault_exception(regs, address, + get_mm_addr_key(current->mm, address)); + } + + _exception_pkey(SIGBUS, regs, BUS_OBJERR, address, 0); + return 0; } /* Additional sanity check(s) */ @@ -516,8 +515,16 @@ static int __do_page_fault(struct pt_regs *regs, unsigned long address, fault = handle_mm_fault(vma, address, flags); #ifdef CONFIG_PPC_MEM_KEYS - if (unlikely(fault & VM_FAULT_SIGSEGV)) - return __bad_area(regs, address, SEGV_PKUERR); + if (unlikely(fault & VM_FAULT_SIGSEGV)) { + /* + * The PGD-PDT...PMD-PTE tree may not have been fully setup. + * Hence we cannot walk the tree to locate the PTE, to locate + * the key. Hence lets use vma_pkey() to get the key; instead + * of get_mm_addr_key(). + */ + up_read(¤t->mm->mmap_sem); + return bad_key_fault_exception(regs, address, vma_pkey(vma)); + } #endif /* CONFIG_PPC_MEM_KEYS */ major |= fault & VM_FAULT_MAJOR;