| From 2700fefdb2d9751c416ad56897e27d41e409324a Mon Sep 17 00:00:00 2001 |
| From: Josh Poimboeuf <jpoimboe@redhat.com> |
| Date: Fri, 30 Nov 2018 12:39:17 -0600 |
| Subject: x86_64: Add gap to int3 to allow for call emulation |
| |
| From: Josh Poimboeuf <jpoimboe@redhat.com> |
| |
| commit 2700fefdb2d9751c416ad56897e27d41e409324a upstream. |
| |
| 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") |
| Tested-by: Nicolai Stange <nstange@suse.de> |
| Reviewed-by: Nicolai Stange <nstange@suse.de> |
| Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org> |
| Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com> |
| Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| arch/x86/entry/entry_64.S | 18 ++++++++++++++++-- |
| 1 file changed, 16 insertions(+), 2 deletions(-) |
| |
| --- a/arch/x86/entry/entry_64.S |
| +++ b/arch/x86/entry/entry_64.S |
| @@ -905,7 +905,7 @@ apicinterrupt IRQ_WORK_VECTOR irq_work |
| */ |
| #define CPU_TSS_IST(x) PER_CPU_VAR(cpu_tss_rw) + (TSS_ist + ((x) - 1) * 8) |
| |
| -.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 |
| |
| @@ -925,6 +925,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 |
| + * int3 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 |
| @@ -1154,7 +1168,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 |