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]>
---
 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 6e469044e4de..2dfb5ef11e36 100644
--- a/arch/x86/include/asm/unwind_user.h
+++ b/arch/x86/include/asm/unwind_user.h
@@ -23,13 +23,15 @@ static inline int unwind_user_word_size(struct pt_regs 
*regs)
        .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 bool unwind_user_at_function_start(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 1fb272419733..fdb1001e3750 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;
+       }
+
        /* Get the Canonical Frame Address (CFA) */
        if (frame->use_fp) {
                if (state->fp < state->sp)
-- 
2.51.0


Reply via email to