• Josh Poimboeuf's avatar
    x86/unwind/orc: Fix unwind_get_return_address_ptr() for inactive tasks · 187b96db
    Josh Poimboeuf authored
    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:
    
      f1d9a2ab ("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: f1d9a2ab ("x86/unwind/orc: Don't skip the first frame for inactive tasks")
    Reported-by: default avatarTetsuo Handa <penguin-kernel@i-love.sakura.ne.jp>
    Signed-off-by: default avatarJosh Poimboeuf <jpoimboe@redhat.com>
    Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
    Link: https://lkml.kernel.org/r/20200522135435.vbxs7umku5pyrdbk@treble
    187b96db
unwind_orc.c 17.6 KB