Received: by 2002:a25:4158:0:0:0:0:0 with SMTP id o85csp3335090yba; Mon, 6 May 2019 22:42:02 -0700 (PDT) X-Google-Smtp-Source: APXvYqyDiSo8k2+BD3JyYcY4zoD0rY+WUQXz+PaVTuCaQGN/QzaYZf5NIEoQ3H2XB+2cu9KE0/vK X-Received: by 2002:a17:902:868e:: with SMTP id g14mr38491835plo.183.1557207721982; Mon, 06 May 2019 22:42:01 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1557207721; cv=none; d=google.com; s=arc-20160816; b=ZNisbbSufad3xdPJj/22vr8Jqk3PEGWuxOay+wBAm6p+XFtGOean3RVUAU0lngjy+0 EWuIDZXU+Mkjmj11hiYTOE5PgsiV/XokXtLamvo/0zKclVRh+ZwremV+Ww5NG3+iiCvj N51SbEe9PxmJ0hxNdm14L49YJ4vBqIADVbV8PgapCTSLacOEXGGb7/pmSEQ/ohnEyYSy h6BoD1ELQDF73O6on8WLEsYyzRMUoowiALGCFFWk8u0mUzeLSnQnal3LA0Kwd1pBG5kM +L6JZ8QEbFI9YVjDuteo2IxvRIc5Jg5RLHJOE8ZCGWWLDe4I2okmwVWSpUoXlLHAK82A NCLw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=mBMhSUUo31gJh5V21l5bjYIoxVD60Fxd6OUwlynXjQ0=; b=TAQmdy/nPV4hsU6Ec5fkelp81J+W2IJa1y5XlCW+Yf3t89OUVFpLifZYyCMdFkjgxT O3820TxBTvaMagPQ/YO/LdjEgs52F3ngi3i62YEo40QuL4TkSudxYofi+5iyEhuGctZ3 T+lUTKVY4EZ+0OistaxU/zrMV9Ybp3Zzo2+dv55ePHB2Ym6ScjdQ3Tc3XFe9ELK+xBTR zCJ7gwHGD7bneIOb0B4C/NS+/SOo/mPnuy3zhA2IIFKwMsxmKdvLIe6Jwji3XXP/ar8B zDNYbVbLhkB5IWsEGyj5+gx46aKEqwrF9VwaalIn2dMoa+V0QS9rLW5RgGJB9IwLIyj3 v+7A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=xOxMLPJo; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 142si18844088pfu.129.2019.05.06.22.41.46; Mon, 06 May 2019 22:42:01 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=xOxMLPJo; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728933AbfEGFjs (ORCPT + 99 others); Tue, 7 May 2019 01:39:48 -0400 Received: from mail.kernel.org ([198.145.29.99]:59270 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728927AbfEGFjp (ORCPT ); Tue, 7 May 2019 01:39:45 -0400 Received: from sasha-vm.mshome.net (c-73-47-72-35.hsd1.nh.comcast.net [73.47.72.35]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 2917D205ED; Tue, 7 May 2019 05:39:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1557207583; bh=RYU87FegKosZuI3aI3uRsmgKtJDRDUMRDynnQJtc/Sc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=xOxMLPJoQsQnokJjCSPpa2cJ5cApct0GAbAl71k3o8bueybTZ1Pi9duX5i6jYgL73 daUTqvRiRKieKv1UmqbUGr13sbaG3TWZr/86rZ0Yufi6vEUctpw7TSVCmucynfzX8f rbN0OJGokpUvZlaShX/EgdYayLaOiS24FaWxG8bM= From: Sasha Levin To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: David Miller , "David S . Miller" , Sasha Levin , sparclinux@vger.kernel.org Subject: [PATCH AUTOSEL 4.14 36/95] sparc64: Make corrupted user stacks more debuggable. Date: Tue, 7 May 2019 01:37:25 -0400 Message-Id: <20190507053826.31622-36-sashal@kernel.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190507053826.31622-1-sashal@kernel.org> References: <20190507053826.31622-1-sashal@kernel.org> MIME-Version: 1.0 X-stable: review X-Patchwork-Hint: Ignore Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: David Miller [ Upstream commit 5b4fc3882a649c9411dd0dcad2ddb78e911d340e ] Right now if we get a corrupted user stack frame we do a do_exit(SIGILL) which is not helpful. If under a debugger, this behavior causes the inferior process to exit. So the register and other state cannot be examined at the time of the event. Instead, conditionally log a rate limited kernel log message and then force a SIGSEGV. With bits and ideas borrowed (as usual) from powerpc. Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- arch/sparc/include/asm/switch_to_64.h | 3 ++- arch/sparc/kernel/process_64.c | 25 +++++++++++++++++++------ arch/sparc/kernel/rtrap_64.S | 1 + arch/sparc/kernel/signal32.c | 12 ++++++++++-- arch/sparc/kernel/signal_64.c | 6 +++++- 5 files changed, 37 insertions(+), 10 deletions(-) diff --git a/arch/sparc/include/asm/switch_to_64.h b/arch/sparc/include/asm/switch_to_64.h index 4ff29b1406a9..b1d4e2e3210f 100644 --- a/arch/sparc/include/asm/switch_to_64.h +++ b/arch/sparc/include/asm/switch_to_64.h @@ -67,6 +67,7 @@ do { save_and_clear_fpu(); \ } while(0) void synchronize_user_stack(void); -void fault_in_user_windows(void); +struct pt_regs; +void fault_in_user_windows(struct pt_regs *); #endif /* __SPARC64_SWITCH_TO_64_H */ diff --git a/arch/sparc/kernel/process_64.c b/arch/sparc/kernel/process_64.c index 318efd784a0b..5640131e2abf 100644 --- a/arch/sparc/kernel/process_64.c +++ b/arch/sparc/kernel/process_64.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -528,7 +529,12 @@ static void stack_unaligned(unsigned long sp) force_sig_info(SIGBUS, &info, current); } -void fault_in_user_windows(void) +static const char uwfault32[] = KERN_INFO \ + "%s[%d]: bad register window fault: SP %08lx (orig_sp %08lx) TPC %08lx O7 %08lx\n"; +static const char uwfault64[] = KERN_INFO \ + "%s[%d]: bad register window fault: SP %016lx (orig_sp %016lx) TPC %08lx O7 %016lx\n"; + +void fault_in_user_windows(struct pt_regs *regs) { struct thread_info *t = current_thread_info(); unsigned long window; @@ -541,9 +547,9 @@ void fault_in_user_windows(void) do { struct reg_window *rwin = &t->reg_window[window]; int winsize = sizeof(struct reg_window); - unsigned long sp; + unsigned long sp, orig_sp; - sp = t->rwbuf_stkptrs[window]; + orig_sp = sp = t->rwbuf_stkptrs[window]; if (test_thread_64bit_stack(sp)) sp += STACK_BIAS; @@ -554,8 +560,16 @@ void fault_in_user_windows(void) stack_unaligned(sp); if (unlikely(copy_to_user((char __user *)sp, - rwin, winsize))) + rwin, winsize))) { + if (show_unhandled_signals) + printk_ratelimited(is_compat_task() ? + uwfault32 : uwfault64, + current->comm, current->pid, + sp, orig_sp, + regs->tpc, + regs->u_regs[UREG_I7]); goto barf; + } } while (window--); } set_thread_wsaved(0); @@ -563,8 +577,7 @@ void fault_in_user_windows(void) barf: set_thread_wsaved(window + 1); - user_exit(); - do_exit(SIGILL); + force_sig(SIGSEGV, current); } asmlinkage long sparc_do_fork(unsigned long clone_flags, diff --git a/arch/sparc/kernel/rtrap_64.S b/arch/sparc/kernel/rtrap_64.S index 0b21042ab181..ad88d60bb740 100644 --- a/arch/sparc/kernel/rtrap_64.S +++ b/arch/sparc/kernel/rtrap_64.S @@ -30,6 +30,7 @@ __handle_preemption: wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate __handle_user_windows: + add %sp, PTREGS_OFF, %o0 call fault_in_user_windows wrpr %g0, RTRAP_PSTATE, %pstate ba,pt %xcc, __handle_preemption_continue diff --git a/arch/sparc/kernel/signal32.c b/arch/sparc/kernel/signal32.c index 5c572de64c74..879f8d86bc21 100644 --- a/arch/sparc/kernel/signal32.c +++ b/arch/sparc/kernel/signal32.c @@ -442,7 +442,11 @@ static int setup_frame32(struct ksignal *ksig, struct pt_regs *regs, get_sigframe(ksig, regs, sigframe_size); if (invalid_frame_pointer(sf, sigframe_size)) { - do_exit(SIGILL); + if (show_unhandled_signals) + pr_info("%s[%d] bad frame in setup_frame32: %08lx TPC %08lx O7 %08lx\n", + current->comm, current->pid, (unsigned long)sf, + regs->tpc, regs->u_regs[UREG_I7]); + force_sigsegv(ksig->sig, current); return -EINVAL; } @@ -573,7 +577,11 @@ static int setup_rt_frame32(struct ksignal *ksig, struct pt_regs *regs, get_sigframe(ksig, regs, sigframe_size); if (invalid_frame_pointer(sf, sigframe_size)) { - do_exit(SIGILL); + if (show_unhandled_signals) + pr_info("%s[%d] bad frame in setup_rt_frame32: %08lx TPC %08lx O7 %08lx\n", + current->comm, current->pid, (unsigned long)sf, + regs->tpc, regs->u_regs[UREG_I7]); + force_sigsegv(ksig->sig, current); return -EINVAL; } diff --git a/arch/sparc/kernel/signal_64.c b/arch/sparc/kernel/signal_64.c index 20426a1c28f2..2d0a50bde3f9 100644 --- a/arch/sparc/kernel/signal_64.c +++ b/arch/sparc/kernel/signal_64.c @@ -373,7 +373,11 @@ setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs) get_sigframe(ksig, regs, sf_size); if (invalid_frame_pointer (sf)) { - do_exit(SIGILL); /* won't return, actually */ + if (show_unhandled_signals) + pr_info("%s[%d] bad frame in setup_rt_frame: %016lx TPC %016lx O7 %016lx\n", + current->comm, current->pid, (unsigned long)sf, + regs->tpc, regs->u_regs[UREG_I7]); + force_sigsegv(ksig->sig, current); return -EINVAL; } -- 2.20.1