kernel_optimize_test/arch/x86/entry
Josh Poimboeuf 81b67439d1 x86/unwind/orc: Fix premature unwind stoppage due to IRET frames
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: ee9f8fce99 ("x86/unwind: Add the ORC unwinder")
Reviewed-by: Miroslav Benes <mbenes@suse.cz>
Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
Signed-off-by: Ingo 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
2020-04-25 12:22:29 +02:00
..
syscalls x86/entry/32: Use IA32-specific wrappers for syscalls taking 64-bit arguments 2020-03-21 16:03:24 +01:00
vdso sparc,x86: vdso: remove meaningless undefining CONFIG_OPTIMIZE_INLINING 2020-04-07 10:43:42 -07:00
vsyscall y2038: syscall implementation cleanups 2019-12-01 14:00:59 -08:00
calling.h x86/entry/64: Fix unwind hints in register clearing code 2020-04-25 12:22:27 +02:00
common.c Merge branch 'x86-cleanups-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2020-03-31 11:04:05 -07:00
entry_32.S x86/entry/64: Trace irqflags unconditionally as ON when returning to user space 2020-03-10 13:56:32 +01:00
entry_64_compat.S x86/asm: Change all ENTRY+ENDPROC to SYM_FUNC_* 2019-10-18 11:58:33 +02:00
entry_64.S x86/unwind/orc: Fix premature unwind stoppage due to IRET frames 2020-04-25 12:22:29 +02:00
Makefile x86/entry/64: Split X32 syscall table into its own file 2020-03-21 16:03:21 +01:00
syscall_32.c x86/entry: Drop asmlinkage from syscalls 2020-03-21 16:03:25 +01:00
syscall_64.c x86/entry: Drop asmlinkage from syscalls 2020-03-21 16:03:25 +01:00
syscall_x32.c x86/entry: Drop asmlinkage from syscalls 2020-03-21 16:03:25 +01:00
thunk_32.S x86/entry: Rename ___preempt_schedule 2020-03-21 16:03:53 +01:00
thunk_64.S x86/entry: Rename ___preempt_schedule 2020-03-21 16:03:53 +01:00