• Josh Poimboeuf's avatar
    x86/unwind/orc: Fix premature unwind stoppage due to IRET frames · 81b67439
    Josh Poimboeuf authored
    The following execution path is possible:
    
      fsnotify()
        [ realign the stack and store previous SP in R10 ]
        <IRQ>
          [ only IRET regs saved ]
          common_interrupt()
            interrupt_entry()
    	  <NMI>
    	    [ full pt_regs saved ]
    	    ...
    	    [ unwind stack ]
    
    When the unwinder goes through the NMI and the IRQ on the stack, and
    then sees fsnotify(), it doesn't have access to the value of R10,
    because it only has the five IRET registers.  So the unwind stops
    prematurely.
    
    However, because the interrupt_entry() code is careful not to clobber
    R10 before saving the full regs, the unwinder should be able to read R10
    from the previously saved full pt_regs associated with the NMI.
    
    Handle this case properly.  When encountering an IRET regs frame
    immediately after a full pt_regs frame, use the pt_regs as a backup
    which can be used to get the C register values.
    
    Also, note that a call frame resets the 'prev_regs' value, because a
    function is free to clobber the registers.  For this fix to work, the
    IRET and full regs frames must be adjacent, with no FUNC frames in
    between.  So replace the FUNC hint in interrupt_entry() with an
    IRET_REGS hint.
    
    Fixes: ee9f8fce ("x86/unwind: Add the ORC unwinder")
    Reviewed-by: default avatarMiroslav Benes <mbenes@suse.cz>
    Signed-off-by: default avatarJosh Poimboeuf <jpoimboe@redhat.com>
    Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
    Cc: Andy Lutomirski <luto@kernel.org>
    Cc: Dave Jones <dsj@fb.com>
    Cc: Jann Horn <jannh@google.com>
    Cc: Peter Zijlstra <peterz@infradead.org>
    Cc: Thomas Gleixner <tglx@linutronix.de>
    Cc: Vince Weaver <vincent.weaver@maine.edu>
    Link: https://lore.kernel.org/r/97a408167cc09f1cfa0de31a7b70dd88868d743f.1587808742.git.jpoimboe@redhat.com
    81b67439
unwind.h 3.14 KB