lkml.org 
[lkml]   [2020]   [Jun]   [8]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH AUTOSEL 5.6 199/606] x86/unwind/orc: Fix unwind_get_return_address_ptr() for inactive tasks
    Date
    From: Josh Poimboeuf <jpoimboe@redhat.com>

    commit 187b96db5ca79423618dfa29a05c438c34f9e1f0 upstream.

    Normally, show_trace_log_lvl() scans the stack, looking for text
    addresses to print. In parallel, it unwinds the stack with
    unwind_next_frame(). If the stack address matches the pointer returned
    by unwind_get_return_address_ptr() for the current frame, the text
    address is printed normally without a question mark. Otherwise it's
    considered a breadcrumb (potentially from a previous call path) and it's
    printed with a question mark to indicate that the address is unreliable
    and typically can be ignored.

    Since the following commit:

    f1d9a2abff66 ("x86/unwind/orc: Don't skip the first frame for inactive tasks")

    ... for inactive tasks, show_trace_log_lvl() prints *only* unreliable
    addresses (prepended with '?').

    That happens because, for the first frame of an inactive task,
    unwind_get_return_address_ptr() returns the wrong return address
    pointer: one word *below* the task stack pointer. show_trace_log_lvl()
    starts scanning at the stack pointer itself, so it never finds the first
    'reliable' address, causing only guesses to being printed.

    The first frame of an inactive task isn't a normal stack frame. It's
    actually just an instance of 'struct inactive_task_frame' which is left
    behind by __switch_to_asm(). Now that this inactive frame is actually
    exposed to callers, fix unwind_get_return_address_ptr() to interpret it
    properly.

    Fixes: f1d9a2abff66 ("x86/unwind/orc: Don't skip the first frame for inactive tasks")
    Reported-by: Tetsuo Handa <penguin-kernel@i-love.sakura.ne.jp>
    Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
    Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
    Link: https://lkml.kernel.org/r/20200522135435.vbxs7umku5pyrdbk@treble
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    arch/x86/kernel/unwind_orc.c | 7 +++++++
    1 file changed, 7 insertions(+)

    diff --git a/arch/x86/kernel/unwind_orc.c b/arch/x86/kernel/unwind_orc.c
    index 9414f02a55ea..1a90abeca5f3 100644
    --- a/arch/x86/kernel/unwind_orc.c
    +++ b/arch/x86/kernel/unwind_orc.c
    @@ -314,12 +314,19 @@ EXPORT_SYMBOL_GPL(unwind_get_return_address);

    unsigned long *unwind_get_return_address_ptr(struct unwind_state *state)
    {
    + struct task_struct *task = state->task;
    +
    if (unwind_done(state))
    return NULL;

    if (state->regs)
    return &state->regs->ip;

    + if (task != current && state->sp == task->thread.sp) {
    + struct inactive_task_frame *frame = (void *)task->thread.sp;
    + return &frame->ret_addr;
    + }
    +
    if (state->sp)
    return (unsigned long *)state->sp - 1;

    --
    2.25.1
    \
     
     \ /
      Last update: 2020-06-09 02:30    [W:3.099 / U:0.052 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site