diff options
| author | Josh Poimboeuf <jpoimboe@redhat.com> | 2018-11-30 13:39:17 -0500 |
|---|---|---|
| committer | Steven Rostedt (VMware) <rostedt@goodmis.org> | 2019-05-08 12:13:06 -0400 |
| commit | 2700fefdb2d9751c416ad56897e27d41e409324a (patch) | |
| tree | d61960991476d2696cef04b7a491d09813640e59 | |
| parent | 03197fc02b356606355d7ede343b18e3e3737771 (diff) | |
x86_64: Add gap to int3 to allow for call emulation
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>
| -rw-r--r-- | arch/x86/entry/entry_64.S | 18 |
1 files changed, 16 insertions, 2 deletions
diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S index 1f0efdb7b629..27fcc6fbdd52 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 | |||
| 879 | * @paranoid == 2 is special: the stub will never switch stacks. This is for | 879 | * @paranoid == 2 is special: the stub will never switch stacks. This is for |
| 880 | * #DF: if the thread stack is somehow unusable, we'll still get a useful OOPS. | 880 | * #DF: if the thread stack is somehow unusable, we'll still get a useful OOPS. |
| 881 | */ | 881 | */ |
| 882 | .macro idtentry sym do_sym has_error_code:req paranoid=0 shift_ist=-1 | 882 | .macro idtentry sym do_sym has_error_code:req paranoid=0 shift_ist=-1 create_gap=0 |
| 883 | ENTRY(\sym) | 883 | ENTRY(\sym) |
| 884 | UNWIND_HINT_IRET_REGS offset=\has_error_code*8 | 884 | UNWIND_HINT_IRET_REGS offset=\has_error_code*8 |
| 885 | 885 | ||
| @@ -899,6 +899,20 @@ ENTRY(\sym) | |||
| 899 | jnz .Lfrom_usermode_switch_stack_\@ | 899 | jnz .Lfrom_usermode_switch_stack_\@ |
| 900 | .endif | 900 | .endif |
| 901 | 901 | ||
| 902 | .if \create_gap == 1 | ||
| 903 | /* | ||
| 904 | * If coming from kernel space, create a 6-word gap to allow the | ||
| 905 | * int3 handler to emulate a call instruction. | ||
| 906 | */ | ||
| 907 | testb $3, CS-ORIG_RAX(%rsp) | ||
| 908 | jnz .Lfrom_usermode_no_gap_\@ | ||
| 909 | .rept 6 | ||
| 910 | pushq 5*8(%rsp) | ||
| 911 | .endr | ||
| 912 | UNWIND_HINT_IRET_REGS offset=8 | ||
| 913 | .Lfrom_usermode_no_gap_\@: | ||
| 914 | .endif | ||
| 915 | |||
| 902 | .if \paranoid | 916 | .if \paranoid |
| 903 | call paranoid_entry | 917 | call paranoid_entry |
| 904 | .else | 918 | .else |
| @@ -1130,7 +1144,7 @@ apicinterrupt3 HYPERV_STIMER0_VECTOR \ | |||
| 1130 | #endif /* CONFIG_HYPERV */ | 1144 | #endif /* CONFIG_HYPERV */ |
| 1131 | 1145 | ||
| 1132 | idtentry debug do_debug has_error_code=0 paranoid=1 shift_ist=DEBUG_STACK | 1146 | idtentry debug do_debug has_error_code=0 paranoid=1 shift_ist=DEBUG_STACK |
| 1133 | idtentry int3 do_int3 has_error_code=0 | 1147 | idtentry int3 do_int3 has_error_code=0 create_gap=1 |
| 1134 | idtentry stack_segment do_stack_segment has_error_code=1 | 1148 | idtentry stack_segment do_stack_segment has_error_code=1 |
| 1135 | 1149 | ||
| 1136 | #ifdef CONFIG_XEN_PV | 1150 | #ifdef CONFIG_XEN_PV |
