Add an indication for an outermost frame to the unwind user frame structure and stop unwinding when reaching an outermost frame.
This will be used by unwind user sframe, as SFrame may represent an undefined return address as indication for an outermost frame. Cc: Steven Rostedt <[email protected]> Cc: Josh Poimboeuf <[email protected]> Cc: Masami Hiramatsu <[email protected]> Cc: Mathieu Desnoyers <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: Jiri Olsa <[email protected]> Cc: Arnaldo Carvalho de Melo <[email protected]> Cc: Namhyung Kim <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: Andrii Nakryiko <[email protected]> Cc: Indu Bhagat <[email protected]> Cc: "Jose E. Marchesi" <[email protected]> Cc: Beau Belgrave <[email protected]> Cc: Jens Remus <[email protected]> Cc: Linus Torvalds <[email protected]> Cc: Andrew Morton <[email protected]> Cc: Florian Weimer <[email protected]> Cc: Sam James <[email protected]> Cc: Kees Cook <[email protected]> Cc: "Carlos O'Donell" <[email protected]> Signed-off-by: Jens Remus <[email protected]> --- Notes (jremus): Changes in v12: - Adjust to Peter's tip perf/core commit ae25884ad749 ("unwind_user/x86: Teach FP unwind about start of function"). Changes in v11: - New patch. arch/x86/include/asm/unwind_user.h | 6 ++++-- include/linux/unwind_user_types.h | 1 + kernel/unwind/user.c | 6 ++++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/unwind_user.h b/arch/x86/include/asm/unwind_user.h index 12064284bc4e..f9a1c460150d 100644 --- a/arch/x86/include/asm/unwind_user.h +++ b/arch/x86/include/asm/unwind_user.h @@ -11,13 +11,15 @@ .cfa_off = 2*(ws), \ .ra_off = -1*(ws), \ .fp_off = -2*(ws), \ - .use_fp = true, + .use_fp = true, \ + .outermost = false, #define ARCH_INIT_USER_FP_ENTRY_FRAME(ws) \ .cfa_off = 1*(ws), \ .ra_off = -1*(ws), \ .fp_off = 0, \ - .use_fp = false, + .use_fp = false, \ + .outermost = false, static inline int unwind_user_word_size(struct pt_regs *regs) { diff --git a/include/linux/unwind_user_types.h b/include/linux/unwind_user_types.h index 43e4b160883f..616cc5ee4586 100644 --- a/include/linux/unwind_user_types.h +++ b/include/linux/unwind_user_types.h @@ -32,6 +32,7 @@ struct unwind_user_frame { s32 ra_off; s32 fp_off; bool use_fp; + bool outermost; }; struct unwind_user_state { diff --git a/kernel/unwind/user.c b/kernel/unwind/user.c index 7644ab9f6a61..d053295b1f7e 100644 --- a/kernel/unwind/user.c +++ b/kernel/unwind/user.c @@ -32,6 +32,12 @@ static int unwind_user_next_common(struct unwind_user_state *state, { unsigned long cfa, fp, ra; + /* Stop unwinding when reaching an outermost frame. */ + if (frame->outermost) { + state->done = true; + return 0; + } + if (frame->use_fp) { if (state->fp < state->sp) return -EINVAL; -- 2.48.1
