Message ID | 20190507174400.064350937@goodmis.org (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | x86_64/ftrace: Emulate calls from int3 when patching functions | expand |
On Tue, May 07, 2019 at 01:42:28PM -0400, Steven Rostedt wrote: > From: Josh Poimboeuf <jpoimboe@redhat.com> > > To allow an int3 handler to emulate a call instruction, it must be able to > push a return address onto the stack. Add a gap to the stack to allow the > int3 handler to push the return address and change the return from int3 to > jump straight to the emulated called function target. > > Link: http://lkml.kernel.org/r/20181130183917.hxmti5josgq4clti@treble > Link: http://lkml.kernel.org/r/20190502162133.GX2623@hirez.programming.kicks-ass.net > > [ > Note, this is needed to allow Live Kernel Patching to not miss calling a > patched function when tracing is enabled. -- Steven Rostedt > ] > > Cc: stable@vger.kernel.org > Fixes: b700e7f03df5 ("livepatch: kernel: add support for live patching") > Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com> > Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org> > --- > arch/x86/entry/entry_64.S | 18 ++++++++++++++++-- > 1 file changed, 16 insertions(+), 2 deletions(-) > > diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S > index 1f0efdb7b629..00df6b135ab1 100644 > --- a/arch/x86/entry/entry_64.S > +++ b/arch/x86/entry/entry_64.S > @@ -879,7 +879,7 @@ apicinterrupt IRQ_WORK_VECTOR irq_work_interrupt smp_irq_work_interrupt > * @paranoid == 2 is special: the stub will never switch stacks. This is for > * #DF: if the thread stack is somehow unusable, we'll still get a useful OOPS. > */ > -.macro idtentry sym do_sym has_error_code:req paranoid=0 shift_ist=-1 > +.macro idtentry sym do_sym has_error_code:req paranoid=0 shift_ist=-1 create_gap=0 > ENTRY(\sym) > UNWIND_HINT_IRET_REGS offset=\has_error_code*8 > > @@ -899,6 +899,20 @@ ENTRY(\sym) > jnz .Lfrom_usermode_switch_stack_\@ > .endif > > + .if \create_gap == 1 > + /* > + * If coming from kernel space, create a 6-word gap to allow the static > + * call #BP handler to emulate a call instruction. Might as well refer to it as the int3 handler, since that's what the rest of the code calls it. Also, no static calls yet :-) So: s/static call #BP handler/int3 handler/
On Tue, 7 May 2019 12:56:55 -0500 Josh Poimboeuf <jpoimboe@redhat.com> wrote: > > + .if \create_gap == 1 > > + /* > > + * If coming from kernel space, create a 6-word gap to allow the static > > + * call #BP handler to emulate a call instruction. > > Might as well refer to it as the int3 handler, since that's what the > rest of the code calls it. Also, no static calls yet :-) So: > > s/static call #BP handler/int3 handler/ > Done. -- Steve
diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S index 1f0efdb7b629..00df6b135ab1 100644 --- a/arch/x86/entry/entry_64.S +++ b/arch/x86/entry/entry_64.S @@ -879,7 +879,7 @@ apicinterrupt IRQ_WORK_VECTOR irq_work_interrupt smp_irq_work_interrupt * @paranoid == 2 is special: the stub will never switch stacks. This is for * #DF: if the thread stack is somehow unusable, we'll still get a useful OOPS. */ -.macro idtentry sym do_sym has_error_code:req paranoid=0 shift_ist=-1 +.macro idtentry sym do_sym has_error_code:req paranoid=0 shift_ist=-1 create_gap=0 ENTRY(\sym) UNWIND_HINT_IRET_REGS offset=\has_error_code*8 @@ -899,6 +899,20 @@ ENTRY(\sym) jnz .Lfrom_usermode_switch_stack_\@ .endif + .if \create_gap == 1 + /* + * If coming from kernel space, create a 6-word gap to allow the static + * call #BP handler to emulate a call instruction. + */ + testb $3, CS-ORIG_RAX(%rsp) + jnz .Lfrom_usermode_no_gap_\@ + .rept 6 + pushq 5*8(%rsp) + .endr + UNWIND_HINT_IRET_REGS offset=8 +.Lfrom_usermode_no_gap_\@: + .endif + .if \paranoid call paranoid_entry .else @@ -1130,7 +1144,7 @@ apicinterrupt3 HYPERV_STIMER0_VECTOR \ #endif /* CONFIG_HYPERV */ idtentry debug do_debug has_error_code=0 paranoid=1 shift_ist=DEBUG_STACK -idtentry int3 do_int3 has_error_code=0 +idtentry int3 do_int3 has_error_code=0 create_gap=1 idtentry stack_segment do_stack_segment has_error_code=1 #ifdef CONFIG_XEN_PV