Received: by 2002:ac0:a582:0:0:0:0:0 with SMTP id m2-v6csp100295imm; Mon, 1 Oct 2018 07:17:28 -0700 (PDT) X-Google-Smtp-Source: ACcGV61mu6Yun+EBozgmhIPYAxt3K4ezbXg55HfzVU4UzfgpPuPjTjPACuYXcARcd8riTE9goi7l X-Received: by 2002:a17:902:c85:: with SMTP id 5-v6mr12089574plt.141.1538403448784; Mon, 01 Oct 2018 07:17:28 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1538403448; cv=none; d=google.com; s=arc-20160816; b=tobZM2bx92AEwlUgTMtHQ1R8Oyd/ukth+WHkUB37GnONIT46r4Kp9LhNyOSt+n3vWk oW6+HAVrldz6LCXq3u2N8ivFdxQEfghxGUImSnG6lSa7Esn9ameA3B2tM3W3I5M2ncRb qrs+FPnJg+L567uN7RjTVTzT3/Kv5/7Lm7rC5eBBSaVkoXBeiT9Iz4FbcRYmlIdnkDkC FPubMOUOzXa8BiISkxjAKUus1hiYSeCALmejSe/as6/0BdqHj3NZtykdaH4/tJ3Rr9UD DAMWeuzrotIp6CUVq1bCwJTQyYOBGjXSXM7KTQZI2okPkCxuM+wi61A/vxR7UB3NV+oS XJBQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:from:date:message-id:references :in-reply-to:subject:cc:to; bh=FbXGPB7jFkMLuQ2gifkWmni08AdrCWwRJG2BX8Hm+xI=; b=q1PIeWlbX8oBqkSGs/l5oIpF0cW3OVRB+c19LiNnRw6ybl6NfVc1Dhb0FoZBrxcxuP xz1Vx7+A+9XizVhvwEWSixz3/Y+7jpun/RF0xq2KyzFn/OV6HghNVXihuDEF9vcwCew1 Pow6hEv5eowDQj9OYvY5HMYRaENDdcEwDf5/RGPL9k5d14RwA2g0Z1pvrudC46wIT8yn 2K/79JN+PKjs8Tb7WdJSc+Ey2dLkCdj0WscRXue/BAY12Dxd/6R3IOkZHVbDE+iRojsU I3GuatkgfyBceTIwDYh95icOV45+Vv3O+UDsUAHsi4mt+i3I5XN5Fn3atZ4mYBvAyfDB Jt1A== ARC-Authentication-Results: i=1; mx.google.com; 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 Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id l15-v6si12479921pgj.528.2018.10.01.07.17.14; Mon, 01 Oct 2018 07:17:28 -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; 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 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729557AbeJAUzB (ORCPT + 99 others); Mon, 1 Oct 2018 16:55:01 -0400 Received: from verein.lst.de ([213.95.11.211]:37917 "EHLO newverein.lst.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729428AbeJAUzA (ORCPT ); Mon, 1 Oct 2018 16:55:00 -0400 Received: by newverein.lst.de (Postfix, from userid 2005) id A856D68BC7; Mon, 1 Oct 2018 16:16:58 +0200 (CEST) To: Will Deacon , Catalin Marinas , Julien Thierry , Steven Rostedt , Josh Poimboeuf , Ingo Molnar , Ard Biesheuvel , Arnd Bergmann , AKASHI Takahiro Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, live-patching@vger.kernel.org Subject: [PATCH v3 4/4] arm64: reliable stacktraces In-Reply-To: <20181001140910.086E768BC7@newverein.lst.de> References: <20181001140910.086E768BC7@newverein.lst.de> Message-Id: <20181001141658.A856D68BC7@newverein.lst.de> Date: Mon, 1 Oct 2018 16:16:58 +0200 (CEST) From: duwe@lst.de (Torsten Duwe) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Make unwind_frame() report whether it had to stop normally or due to an error condition; walk_stackframe() will pass that info. __save_stack_trace() is used to check the validity of a frame; save_stack_trace_tsk_reliable() can now trivially be implemented. Modify arch/arm64/kernel/time.c for the new semantics. Signed-off-by: Torsten Duwe --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -127,8 +127,9 @@ config ARM64 select HAVE_PERF_EVENTS select HAVE_PERF_REGS select HAVE_PERF_USER_STACK_DUMP - select HAVE_REGS_AND_STACK_ACCESS_API select HAVE_RCU_TABLE_FREE + select HAVE_REGS_AND_STACK_ACCESS_API + select HAVE_RELIABLE_STACKTRACE select HAVE_STACKPROTECTOR select HAVE_SYSCALL_TRACEPOINTS select HAVE_KPROBES --- a/arch/arm64/include/asm/stacktrace.h +++ b/arch/arm64/include/asm/stacktrace.h @@ -33,7 +33,7 @@ struct stackframe { }; extern int unwind_frame(struct task_struct *tsk, struct stackframe *frame); -extern void walk_stackframe(struct task_struct *tsk, struct stackframe *frame, +extern int walk_stackframe(struct task_struct *tsk, struct stackframe *frame, int (*fn)(struct stackframe *, void *), void *data); extern void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk); --- a/arch/arm64/kernel/stacktrace.c +++ b/arch/arm64/kernel/stacktrace.c @@ -40,6 +40,13 @@ * ldp x29, x30, [sp] * add sp, sp, #0x10 */ + +/* + * unwind_frame -- unwind a single stack frame. + * Returns 0 when there are more frames to go. + * 1 means reached end of stack; negative (error) + * means stopped because information is not reliable. + */ int notrace unwind_frame(struct task_struct *tsk, struct stackframe *frame) { unsigned long fp = frame->fp; @@ -81,23 +88,27 @@ int notrace unwind_frame(struct task_str * both are NULL. */ if (!frame->fp && !frame->pc) - return -EINVAL; + return 1; return 0; } -void notrace walk_stackframe(struct task_struct *tsk, struct stackframe *frame, +int notrace walk_stackframe(struct task_struct *tsk, struct stackframe *frame, int (*fn)(struct stackframe *, void *), void *data) { while (1) { int ret; - if (fn(frame, data)) - break; + ret = fn(frame, data); + if (ret) + return ret; ret = unwind_frame(tsk, frame); if (ret < 0) + return ret; + if (ret > 0) break; } + return 0; } #ifdef CONFIG_STACKTRACE @@ -145,14 +156,15 @@ void save_stack_trace_regs(struct pt_reg trace->entries[trace->nr_entries++] = ULONG_MAX; } -static noinline void __save_stack_trace(struct task_struct *tsk, +static noinline int __save_stack_trace(struct task_struct *tsk, struct stack_trace *trace, unsigned int nosched) { struct stack_trace_data data; struct stackframe frame; + int ret; if (!try_get_task_stack(tsk)) - return; + return -EBUSY; data.trace = trace; data.skip = trace->skip; @@ -171,11 +183,12 @@ static noinline void __save_stack_trace( frame.graph = tsk->curr_ret_stack; #endif - walk_stackframe(tsk, &frame, save_trace, &data); + ret = walk_stackframe(tsk, &frame, save_trace, &data); if (trace->nr_entries < trace->max_entries) trace->entries[trace->nr_entries++] = ULONG_MAX; put_task_stack(tsk); + return ret; } EXPORT_SYMBOL_GPL(save_stack_trace_tsk); @@ -190,4 +203,12 @@ void save_stack_trace(struct stack_trace } EXPORT_SYMBOL_GPL(save_stack_trace); + +int save_stack_trace_tsk_reliable(struct task_struct *tsk, + struct stack_trace *trace) +{ + return __save_stack_trace(tsk, trace, 1); +} +EXPORT_SYMBOL_GPL(save_stack_trace_tsk_reliable); + #endif --- a/arch/arm64/kernel/time.c +++ b/arch/arm64/kernel/time.c @@ -56,7 +56,7 @@ unsigned long profile_pc(struct pt_regs #endif do { int ret = unwind_frame(NULL, &frame); - if (ret < 0) + if (ret) return 0; } while (in_lock_functions(frame.pc));