From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755130AbdDLSsE (ORCPT ); Wed, 12 Apr 2017 14:48:04 -0400 Received: from mx1.redhat.com ([209.132.183.28]:54004 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754817AbdDLSr1 (ORCPT ); Wed, 12 Apr 2017 14:47:27 -0400 DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com E8EB3C05683F Authentication-Results: ext-mx08.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx08.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=jpoimboe@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com E8EB3C05683F From: Josh Poimboeuf To: x86@kernel.org Cc: linux-kernel@vger.kernel.org, Daniel Borkmann , Dave Jones Subject: [PATCH 2/3] x86/unwind: read stack return address in update_stack_state() Date: Wed, 12 Apr 2017 13:47:11 -0500 Message-Id: In-Reply-To: References: X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Wed, 12 Apr 2017 18:47:27 +0000 (UTC) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Instead of reading the return address when unwind_get_return_address() is called, read it from update_stack_state() and store it in the unwind state. This enables the next patch to check the return address from unwind_next_frame() so it can detect an entry code frame. Signed-off-by: Josh Poimboeuf --- arch/x86/include/asm/unwind.h | 1 + arch/x86/kernel/unwind_frame.c | 25 +++++++++++++------------ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/arch/x86/include/asm/unwind.h b/arch/x86/include/asm/unwind.h index 6fa75b1..5663425 100644 --- a/arch/x86/include/asm/unwind.h +++ b/arch/x86/include/asm/unwind.h @@ -14,6 +14,7 @@ struct unwind_state { #ifdef CONFIG_FRAME_POINTER unsigned long *bp, *orig_sp; struct pt_regs *regs; + unsigned long ip; #else unsigned long *sp; #endif diff --git a/arch/x86/kernel/unwind_frame.c b/arch/x86/kernel/unwind_frame.c index 9098ef1..c67a059 100644 --- a/arch/x86/kernel/unwind_frame.c +++ b/arch/x86/kernel/unwind_frame.c @@ -56,20 +56,10 @@ static void unwind_dump(struct unwind_state *state, unsigned long *sp) unsigned long unwind_get_return_address(struct unwind_state *state) { - unsigned long addr; - unsigned long *addr_p = unwind_get_return_address_ptr(state); - if (unwind_done(state)) return 0; - if (state->regs && user_mode(state->regs)) - return 0; - - addr = READ_ONCE_TASK_STACK(state->task, *addr_p); - addr = ftrace_graph_ret_addr(state->task, &state->graph_idx, addr, - addr_p); - - return __kernel_text_address(addr) ? addr : 0; + return __kernel_text_address(state->ip) ? state->ip : 0; } EXPORT_SYMBOL_GPL(unwind_get_return_address); @@ -141,7 +131,7 @@ static bool update_stack_state(struct unwind_state *state, struct stack_info *info = &state->stack_info; enum stack_type prev_type = info->type; struct pt_regs *regs; - unsigned long *frame, *prev_frame_end; + unsigned long *frame, *prev_frame_end, *addr_p, addr; size_t len; if (state->regs) @@ -185,6 +175,16 @@ static bool update_stack_state(struct unwind_state *state, state->regs = NULL; } + /* Save the return address: */ + if (state->regs && user_mode(state->regs)) + state->ip = 0; + else { + addr_p = unwind_get_return_address_ptr(state); + addr = READ_ONCE_TASK_STACK(state->task, *addr_p); + state->ip = ftrace_graph_ret_addr(state->task, &state->graph_idx, + addr, addr_p); + } + /* Save the original stack pointer for unwind_dump(): */ if (!state->orig_sp || info->type != prev_type) state->orig_sp = frame; @@ -228,6 +228,7 @@ bool unwind_next_frame(struct unwind_state *state) */ state->regs = regs; state->bp = NULL; + state->ip = 0; return true; } -- 2.7.4