0001
0002 #ifndef _ASM_X86_TEXT_PATCHING_H
0003 #define _ASM_X86_TEXT_PATCHING_H
0004
0005 #include <linux/types.h>
0006 #include <linux/stddef.h>
0007 #include <asm/ptrace.h>
0008
0009 struct paravirt_patch_site;
0010 #ifdef CONFIG_PARAVIRT
0011 void apply_paravirt(struct paravirt_patch_site *start,
0012 struct paravirt_patch_site *end);
0013 #else
0014 static inline void apply_paravirt(struct paravirt_patch_site *start,
0015 struct paravirt_patch_site *end)
0016 {}
0017 #define __parainstructions NULL
0018 #define __parainstructions_end NULL
0019 #endif
0020
0021
0022
0023
0024
0025
0026 #define POKE_MAX_OPCODE_SIZE 5
0027
0028 extern void text_poke_early(void *addr, const void *opcode, size_t len);
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044 extern void *text_poke(void *addr, const void *opcode, size_t len);
0045 extern void text_poke_sync(void);
0046 extern void *text_poke_kgdb(void *addr, const void *opcode, size_t len);
0047 extern void *text_poke_copy(void *addr, const void *opcode, size_t len);
0048 extern void *text_poke_set(void *addr, int c, size_t len);
0049 extern int poke_int3_handler(struct pt_regs *regs);
0050 extern void text_poke_bp(void *addr, const void *opcode, size_t len, const void *emulate);
0051
0052 extern void text_poke_queue(void *addr, const void *opcode, size_t len, const void *emulate);
0053 extern void text_poke_finish(void);
0054
0055 #define INT3_INSN_SIZE 1
0056 #define INT3_INSN_OPCODE 0xCC
0057
0058 #define RET_INSN_SIZE 1
0059 #define RET_INSN_OPCODE 0xC3
0060
0061 #define CALL_INSN_SIZE 5
0062 #define CALL_INSN_OPCODE 0xE8
0063
0064 #define JMP32_INSN_SIZE 5
0065 #define JMP32_INSN_OPCODE 0xE9
0066
0067 #define JMP8_INSN_SIZE 2
0068 #define JMP8_INSN_OPCODE 0xEB
0069
0070 #define DISP32_SIZE 4
0071
0072 static __always_inline int text_opcode_size(u8 opcode)
0073 {
0074 int size = 0;
0075
0076 #define __CASE(insn) \
0077 case insn##_INSN_OPCODE: size = insn##_INSN_SIZE; break
0078
0079 switch(opcode) {
0080 __CASE(INT3);
0081 __CASE(RET);
0082 __CASE(CALL);
0083 __CASE(JMP32);
0084 __CASE(JMP8);
0085 }
0086
0087 #undef __CASE
0088
0089 return size;
0090 }
0091
0092 union text_poke_insn {
0093 u8 text[POKE_MAX_OPCODE_SIZE];
0094 struct {
0095 u8 opcode;
0096 s32 disp;
0097 } __attribute__((packed));
0098 };
0099
0100 static __always_inline
0101 void __text_gen_insn(void *buf, u8 opcode, const void *addr, const void *dest, int size)
0102 {
0103 union text_poke_insn *insn = buf;
0104
0105 BUG_ON(size < text_opcode_size(opcode));
0106
0107
0108
0109
0110
0111
0112 OPTIMIZER_HIDE_VAR(insn);
0113 OPTIMIZER_HIDE_VAR(addr);
0114 OPTIMIZER_HIDE_VAR(dest);
0115
0116 insn->opcode = opcode;
0117
0118 if (size > 1) {
0119 insn->disp = (long)dest - (long)(addr + size);
0120 if (size == 2) {
0121
0122
0123
0124
0125 BUG_ON((insn->disp >> 31) != (insn->disp >> 7));
0126 }
0127 }
0128 }
0129
0130 static __always_inline
0131 void *text_gen_insn(u8 opcode, const void *addr, const void *dest)
0132 {
0133 static union text_poke_insn insn;
0134 __text_gen_insn(&insn, opcode, addr, dest, text_opcode_size(opcode));
0135 return &insn.text;
0136 }
0137
0138 extern int after_bootmem;
0139 extern __ro_after_init struct mm_struct *poking_mm;
0140 extern __ro_after_init unsigned long poking_addr;
0141
0142 #ifndef CONFIG_UML_X86
0143 static __always_inline
0144 void int3_emulate_jmp(struct pt_regs *regs, unsigned long ip)
0145 {
0146 regs->ip = ip;
0147 }
0148
0149 static __always_inline
0150 void int3_emulate_push(struct pt_regs *regs, unsigned long val)
0151 {
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161 regs->sp -= sizeof(unsigned long);
0162 *(unsigned long *)regs->sp = val;
0163 }
0164
0165 static __always_inline
0166 unsigned long int3_emulate_pop(struct pt_regs *regs)
0167 {
0168 unsigned long val = *(unsigned long *)regs->sp;
0169 regs->sp += sizeof(unsigned long);
0170 return val;
0171 }
0172
0173 static __always_inline
0174 void int3_emulate_call(struct pt_regs *regs, unsigned long func)
0175 {
0176 int3_emulate_push(regs, regs->ip - INT3_INSN_SIZE + CALL_INSN_SIZE);
0177 int3_emulate_jmp(regs, func);
0178 }
0179
0180 static __always_inline
0181 void int3_emulate_ret(struct pt_regs *regs)
0182 {
0183 unsigned long ip = int3_emulate_pop(regs);
0184 int3_emulate_jmp(regs, ip);
0185 }
0186 #endif
0187
0188 #endif