From patchwork Tue Oct 1 19:54:46 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Helge Deller X-Patchwork-Id: 2971701 Return-Path: X-Original-To: patchwork-linux-parisc@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 61AB4BFF0B for ; Tue, 1 Oct 2013 19:55:18 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 832612041C for ; Tue, 1 Oct 2013 19:55:17 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 4D14820417 for ; Tue, 1 Oct 2013 19:55:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751251Ab3JATzP (ORCPT ); Tue, 1 Oct 2013 15:55:15 -0400 Received: from mout.gmx.net ([212.227.15.19]:55704 "EHLO mout.gmx.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750881Ab3JATzO (ORCPT ); Tue, 1 Oct 2013 15:55:14 -0400 Received: from p100.box ([84.173.31.92]) by mail.gmx.com (mrgmx102) with ESMTPSA (Nemesis) id 0M8pKi-1VYl0t3nhM-00CAG6 for ; Tue, 01 Oct 2013 21:55:12 +0200 Date: Tue, 1 Oct 2013 21:54:46 +0200 From: Helge Deller To: linux-parisc@vger.kernel.org, James Bottomley , John David Anglin Subject: [PATCH] parisc: fix interruption handler to respect pagefault_disable() Message-ID: <20131001195446.GA29580@p100.box> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) X-Provags-ID: V03:K0:qlHBJdyi/HP5/G9uRJR2UUXP81ug997X/etEXZu76IaoLYKVqFk HlYx9t+v+Ke6+xXjpn08qre3Dvxl8ERJzfVP8j1l2qwRYyQfXQ5Xr3a2quC6qlPRL5eDjSS 9JlutmKkp/tc5JB9xnAUpocxyYMqyhuLvXShUxPggB7bL4QEgnknNL9ODzbZOS1SH3kqgKa NBPsaUgAHXg6aIYMxUq0w== Sender: linux-parisc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-parisc@vger.kernel.org X-Spam-Status: No, score=-7.5 required=5.0 tests=BAYES_00,FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Running an "echo t > /proc/sysrq-trigger" crashes the parisc kernel. The problem is, that in print_worker_info() we try to read the workqueue info via the probe_kernel_read() functions which use pagefault_disable() to avoid crashes like this: probe_kernel_read(&pwq, &worker->current_pwq, sizeof(pwq)); probe_kernel_read(&wq, &pwq->wq, sizeof(wq)); probe_kernel_read(name, wq->name, sizeof(name) - 1); The problem here is, that the first probe_kernel_read(&pwq) might return zero in pwq and as such the following probe_kernel_reads() try to access contents of the page zero which is read protected and generate a kernel segfault. With this patch we fix the interruption handler to call parisc_terminate() directly only if pagefault_disable() was not called (in which case preempt_count()==0). Otherwise we hand over to the pagefault handler which will try to look up the faulting address in the fixup tables. Signed-off-by: Helge Deller Cc: # v3.0+ Signed-off-by: John David Anglin --- To unsubscribe from this list: send the line "unsubscribe linux-parisc" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/arch/parisc/include/asm/traps.h b/arch/parisc/include/asm/traps.h index 1945f99..4736020 100644 --- a/arch/parisc/include/asm/traps.h +++ b/arch/parisc/include/asm/traps.h @@ -6,7 +6,7 @@ struct pt_regs; /* traps.c */ void parisc_terminate(char *msg, struct pt_regs *regs, - int code, unsigned long offset); + int code, unsigned long offset) __noreturn __cold; /* mm/fault.c */ void do_page_fault(struct pt_regs *regs, unsigned long code, diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c index 04e47c6..b3f87a3 100644 --- a/arch/parisc/kernel/traps.c +++ b/arch/parisc/kernel/traps.c @@ -805,14 +805,14 @@ void notrace handle_interruption(int code, struct pt_regs *regs) else { /* - * The kernel should never fault on its own address space. + * The kernel should never fault on its own address space, + * unless pagefault_disable() was called before. */ - if (fault_space == 0) + if (fault_space == 0 && !in_atomic()) { pdc_chassis_send_status(PDC_CHASSIS_DIRECT_PANIC); parisc_terminate("Kernel Fault", regs, code, fault_address); - } }