Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

x86/alternatives: Teach text_poke_bp() to emulate RET

Future patches will need to poke a RET instruction, provide the
infrastructure required for this.

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Reviewed-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Link: https://lore.kernel.org/r/20200818135804.982214828@infradead.org

authored by

Peter Zijlstra and committed by
Ingo Molnar
c43a43e4 f03c4129

+24
+19
arch/x86/include/asm/text-patching.h
··· 53 53 #define INT3_INSN_SIZE 1 54 54 #define INT3_INSN_OPCODE 0xCC 55 55 56 + #define RET_INSN_SIZE 1 57 + #define RET_INSN_OPCODE 0xC3 58 + 56 59 #define CALL_INSN_SIZE 5 57 60 #define CALL_INSN_OPCODE 0xE8 58 61 ··· 76 73 77 74 switch(opcode) { 78 75 __CASE(INT3); 76 + __CASE(RET); 79 77 __CASE(CALL); 80 78 __CASE(JMP32); 81 79 __CASE(JMP8); ··· 145 141 } 146 142 147 143 static __always_inline 144 + unsigned long int3_emulate_pop(struct pt_regs *regs) 145 + { 146 + unsigned long val = *(unsigned long *)regs->sp; 147 + regs->sp += sizeof(unsigned long); 148 + return val; 149 + } 150 + 151 + static __always_inline 148 152 void int3_emulate_call(struct pt_regs *regs, unsigned long func) 149 153 { 150 154 int3_emulate_push(regs, regs->ip - INT3_INSN_SIZE + CALL_INSN_SIZE); 151 155 int3_emulate_jmp(regs, func); 156 + } 157 + 158 + static __always_inline 159 + void int3_emulate_ret(struct pt_regs *regs) 160 + { 161 + unsigned long ip = int3_emulate_pop(regs); 162 + int3_emulate_jmp(regs, ip); 152 163 } 153 164 #endif /* !CONFIG_UML_X86 */ 154 165
+5
arch/x86/kernel/alternative.c
··· 1103 1103 */ 1104 1104 goto out_put; 1105 1105 1106 + case RET_INSN_OPCODE: 1107 + int3_emulate_ret(regs); 1108 + break; 1109 + 1106 1110 case CALL_INSN_OPCODE: 1107 1111 int3_emulate_call(regs, (long)ip + tp->rel32); 1108 1112 break; ··· 1281 1277 1282 1278 switch (tp->opcode) { 1283 1279 case INT3_INSN_OPCODE: 1280 + case RET_INSN_OPCODE: 1284 1281 break; 1285 1282 1286 1283 case CALL_INSN_OPCODE: