From patchwork Wed Feb 4 00:30:38 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Miller X-Patchwork-Id: 21819 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by ozlabs.org (Postfix) with ESMTP id 0DCB3DDDFB for ; Wed, 4 Feb 2009 11:30:44 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752055AbZBDAam (ORCPT ); Tue, 3 Feb 2009 19:30:42 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1752096AbZBDAam (ORCPT ); Tue, 3 Feb 2009 19:30:42 -0500 Received: from 74-93-104-97-Washington.hfc.comcastbusiness.net ([74.93.104.97]:49835 "EHLO sunset.davemloft.net" rhost-flags-OK-FAIL-OK-OK) by vger.kernel.org with ESMTP id S1752055AbZBDAal (ORCPT ); Tue, 3 Feb 2009 19:30:41 -0500 Received: from localhost (localhost [127.0.0.1]) by sunset.davemloft.net (Postfix) with ESMTP id B02A0C8C1BA for ; Tue, 3 Feb 2009 16:30:38 -0800 (PST) Date: Tue, 03 Feb 2009 16:30:38 -0800 (PST) Message-Id: <20090203.163038.141261513.davem@davemloft.net> To: sparclinux@vger.kernel.org Subject: [PATCH]: sparc64: Kill bogus TPC/address truncation during 32-bit faults. From: David Miller X-Mailer: Mew version 6.1 on Emacs 22.1 / Mule 5.0 (SAKAKI) Mime-Version: 1.0 Sender: sparclinux-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: sparclinux@vger.kernel.org After some more auditing and data mining, I checked in the following patch which simplifies bug checks and removes bogus address truncation done by the fault handler. sparc64: Kill bogus TPC/address truncation during 32-bit faults. This builds upon eeabac7386ca13bfe1a58afeb04326a9e1a3a20e ("sparc64: Validate kernel generated fault addresses on sparc64.") Upon further consideration, we actually should never see any fault addresses for 32-bit tasks with the upper 32-bits set. If it does every happen, by definition it's a bug. Whatever context created that fault would only have that fault satisfied if we used the full 64-bit address. If we truncate it, we'll always fault the wrong address and we'll always loop faulting forever. So catch such conditions and mark them as errors always. Log the error and fail the fault. Signed-off-by: David S. Miller --- arch/sparc/mm/fault_64.c | 49 ++++++++++++++++++++++++++++++++------------- 1 files changed, 35 insertions(+), 14 deletions(-) diff --git a/arch/sparc/mm/fault_64.c b/arch/sparc/mm/fault_64.c index 1a786ab..4ab8993 100644 --- a/arch/sparc/mm/fault_64.c +++ b/arch/sparc/mm/fault_64.c @@ -225,6 +225,30 @@ cannot_handle: unhandled_fault (address, current, regs); } +static void noinline bogus_32bit_fault_tpc(struct pt_regs *regs) +{ + static int times; + + if (times++ < 10) + printk(KERN_ERR "FAULT[%s:%d]: 32-bit process reports " + "64-bit TPC [%lx]\n", + current->comm, current->pid, + regs->tpc); + show_regs(regs); +} + +static void noinline bogus_32bit_fault_address(struct pt_regs *regs, + unsigned long addr) +{ + static int times; + + if (times++ < 10) + printk(KERN_ERR "FAULT[%s:%d]: 32-bit process " + "reports 64-bit fault address [%lx]\n", + current->comm, current->pid, addr); + show_regs(regs); +} + asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) { struct mm_struct *mm = current->mm; @@ -246,13 +270,20 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) BUG(); if (test_thread_flag(TIF_32BIT)) { - if (!(regs->tstate & TSTATE_PRIV)) - regs->tpc &= 0xffffffff; - address &= 0xffffffff; + if (!(regs->tstate & TSTATE_PRIV)) { + if (unlikely((regs->tpc >> 32) != 0)) { + bogus_32bit_fault_tpc(regs); + goto intr_or_no_mm; + } + } + if (unlikely((address >> 32) != 0)) { + bogus_32bit_fault_address(regs, address); + goto intr_or_no_mm; + } } if (regs->tstate & TSTATE_PRIV) { - unsigned long eaddr, tpc = regs->tpc; + unsigned long tpc = regs->tpc; /* Sanity check the PC. */ if ((tpc >= KERNBASE && tpc < (unsigned long) __init_end) || @@ -262,16 +293,6 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) bad_kernel_pc(regs, address); return; } - - insn = get_fault_insn(regs, insn); - eaddr = compute_effective_address(regs, insn, 0); - if (WARN_ON_ONCE((eaddr & PAGE_MASK) != (address & PAGE_MASK))){ - printk(KERN_ERR "FAULT: Mismatch kernel fault " - "address: addr[%lx] eaddr[%lx] TPC[%lx]\n", - address, eaddr, tpc); - show_regs(regs); - goto handle_kernel_fault; - } } /*