diff options
Diffstat (limited to 'arch/x86/kernel/kprobes/opt.c')
-rw-r--r-- | arch/x86/kernel/kprobes/opt.c | 32 |
1 files changed, 17 insertions, 15 deletions
diff --git a/arch/x86/kernel/kprobes/opt.c b/arch/x86/kernel/kprobes/opt.c index 898160b42e43..f304773285ae 100644 --- a/arch/x86/kernel/kprobes/opt.c +++ b/arch/x86/kernel/kprobes/opt.c | |||
@@ -77,7 +77,7 @@ found: | |||
77 | } | 77 | } |
78 | 78 | ||
79 | /* Insert a move instruction which sets a pointer to eax/rdi (1st arg). */ | 79 | /* Insert a move instruction which sets a pointer to eax/rdi (1st arg). */ |
80 | static void __kprobes synthesize_set_arg1(kprobe_opcode_t *addr, unsigned long val) | 80 | static void synthesize_set_arg1(kprobe_opcode_t *addr, unsigned long val) |
81 | { | 81 | { |
82 | #ifdef CONFIG_X86_64 | 82 | #ifdef CONFIG_X86_64 |
83 | *addr++ = 0x48; | 83 | *addr++ = 0x48; |
@@ -138,7 +138,8 @@ asm ( | |||
138 | #define INT3_SIZE sizeof(kprobe_opcode_t) | 138 | #define INT3_SIZE sizeof(kprobe_opcode_t) |
139 | 139 | ||
140 | /* Optimized kprobe call back function: called from optinsn */ | 140 | /* Optimized kprobe call back function: called from optinsn */ |
141 | static void __kprobes optimized_callback(struct optimized_kprobe *op, struct pt_regs *regs) | 141 | static void |
142 | optimized_callback(struct optimized_kprobe *op, struct pt_regs *regs) | ||
142 | { | 143 | { |
143 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); | 144 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); |
144 | unsigned long flags; | 145 | unsigned long flags; |
@@ -168,8 +169,9 @@ static void __kprobes optimized_callback(struct optimized_kprobe *op, struct pt_ | |||
168 | } | 169 | } |
169 | local_irq_restore(flags); | 170 | local_irq_restore(flags); |
170 | } | 171 | } |
172 | NOKPROBE_SYMBOL(optimized_callback); | ||
171 | 173 | ||
172 | static int __kprobes copy_optimized_instructions(u8 *dest, u8 *src) | 174 | static int copy_optimized_instructions(u8 *dest, u8 *src) |
173 | { | 175 | { |
174 | int len = 0, ret; | 176 | int len = 0, ret; |
175 | 177 | ||
@@ -189,7 +191,7 @@ static int __kprobes copy_optimized_instructions(u8 *dest, u8 *src) | |||
189 | } | 191 | } |
190 | 192 | ||
191 | /* Check whether insn is indirect jump */ | 193 | /* Check whether insn is indirect jump */ |
192 | static int __kprobes insn_is_indirect_jump(struct insn *insn) | 194 | static int insn_is_indirect_jump(struct insn *insn) |
193 | { | 195 | { |
194 | return ((insn->opcode.bytes[0] == 0xff && | 196 | return ((insn->opcode.bytes[0] == 0xff && |
195 | (X86_MODRM_REG(insn->modrm.value) & 6) == 4) || /* Jump */ | 197 | (X86_MODRM_REG(insn->modrm.value) & 6) == 4) || /* Jump */ |
@@ -224,7 +226,7 @@ static int insn_jump_into_range(struct insn *insn, unsigned long start, int len) | |||
224 | } | 226 | } |
225 | 227 | ||
226 | /* Decode whole function to ensure any instructions don't jump into target */ | 228 | /* Decode whole function to ensure any instructions don't jump into target */ |
227 | static int __kprobes can_optimize(unsigned long paddr) | 229 | static int can_optimize(unsigned long paddr) |
228 | { | 230 | { |
229 | unsigned long addr, size = 0, offset = 0; | 231 | unsigned long addr, size = 0, offset = 0; |
230 | struct insn insn; | 232 | struct insn insn; |
@@ -275,7 +277,7 @@ static int __kprobes can_optimize(unsigned long paddr) | |||
275 | } | 277 | } |
276 | 278 | ||
277 | /* Check optimized_kprobe can actually be optimized. */ | 279 | /* Check optimized_kprobe can actually be optimized. */ |
278 | int __kprobes arch_check_optimized_kprobe(struct optimized_kprobe *op) | 280 | int arch_check_optimized_kprobe(struct optimized_kprobe *op) |
279 | { | 281 | { |
280 | int i; | 282 | int i; |
281 | struct kprobe *p; | 283 | struct kprobe *p; |
@@ -290,15 +292,15 @@ int __kprobes arch_check_optimized_kprobe(struct optimized_kprobe *op) | |||
290 | } | 292 | } |
291 | 293 | ||
292 | /* Check the addr is within the optimized instructions. */ | 294 | /* Check the addr is within the optimized instructions. */ |
293 | int __kprobes | 295 | int arch_within_optimized_kprobe(struct optimized_kprobe *op, |
294 | arch_within_optimized_kprobe(struct optimized_kprobe *op, unsigned long addr) | 296 | unsigned long addr) |
295 | { | 297 | { |
296 | return ((unsigned long)op->kp.addr <= addr && | 298 | return ((unsigned long)op->kp.addr <= addr && |
297 | (unsigned long)op->kp.addr + op->optinsn.size > addr); | 299 | (unsigned long)op->kp.addr + op->optinsn.size > addr); |
298 | } | 300 | } |
299 | 301 | ||
300 | /* Free optimized instruction slot */ | 302 | /* Free optimized instruction slot */ |
301 | static __kprobes | 303 | static |
302 | void __arch_remove_optimized_kprobe(struct optimized_kprobe *op, int dirty) | 304 | void __arch_remove_optimized_kprobe(struct optimized_kprobe *op, int dirty) |
303 | { | 305 | { |
304 | if (op->optinsn.insn) { | 306 | if (op->optinsn.insn) { |
@@ -308,7 +310,7 @@ void __arch_remove_optimized_kprobe(struct optimized_kprobe *op, int dirty) | |||
308 | } | 310 | } |
309 | } | 311 | } |
310 | 312 | ||
311 | void __kprobes arch_remove_optimized_kprobe(struct optimized_kprobe *op) | 313 | void arch_remove_optimized_kprobe(struct optimized_kprobe *op) |
312 | { | 314 | { |
313 | __arch_remove_optimized_kprobe(op, 1); | 315 | __arch_remove_optimized_kprobe(op, 1); |
314 | } | 316 | } |
@@ -318,7 +320,7 @@ void __kprobes arch_remove_optimized_kprobe(struct optimized_kprobe *op) | |||
318 | * Target instructions MUST be relocatable (checked inside) | 320 | * Target instructions MUST be relocatable (checked inside) |
319 | * This is called when new aggr(opt)probe is allocated or reused. | 321 | * This is called when new aggr(opt)probe is allocated or reused. |
320 | */ | 322 | */ |
321 | int __kprobes arch_prepare_optimized_kprobe(struct optimized_kprobe *op) | 323 | int arch_prepare_optimized_kprobe(struct optimized_kprobe *op) |
322 | { | 324 | { |
323 | u8 *buf; | 325 | u8 *buf; |
324 | int ret; | 326 | int ret; |
@@ -372,7 +374,7 @@ int __kprobes arch_prepare_optimized_kprobe(struct optimized_kprobe *op) | |||
372 | * Replace breakpoints (int3) with relative jumps. | 374 | * Replace breakpoints (int3) with relative jumps. |
373 | * Caller must call with locking kprobe_mutex and text_mutex. | 375 | * Caller must call with locking kprobe_mutex and text_mutex. |
374 | */ | 376 | */ |
375 | void __kprobes arch_optimize_kprobes(struct list_head *oplist) | 377 | void arch_optimize_kprobes(struct list_head *oplist) |
376 | { | 378 | { |
377 | struct optimized_kprobe *op, *tmp; | 379 | struct optimized_kprobe *op, *tmp; |
378 | u8 insn_buf[RELATIVEJUMP_SIZE]; | 380 | u8 insn_buf[RELATIVEJUMP_SIZE]; |
@@ -398,7 +400,7 @@ void __kprobes arch_optimize_kprobes(struct list_head *oplist) | |||
398 | } | 400 | } |
399 | 401 | ||
400 | /* Replace a relative jump with a breakpoint (int3). */ | 402 | /* Replace a relative jump with a breakpoint (int3). */ |
401 | void __kprobes arch_unoptimize_kprobe(struct optimized_kprobe *op) | 403 | void arch_unoptimize_kprobe(struct optimized_kprobe *op) |
402 | { | 404 | { |
403 | u8 insn_buf[RELATIVEJUMP_SIZE]; | 405 | u8 insn_buf[RELATIVEJUMP_SIZE]; |
404 | 406 | ||
@@ -424,8 +426,7 @@ extern void arch_unoptimize_kprobes(struct list_head *oplist, | |||
424 | } | 426 | } |
425 | } | 427 | } |
426 | 428 | ||
427 | int __kprobes | 429 | int setup_detour_execution(struct kprobe *p, struct pt_regs *regs, int reenter) |
428 | setup_detour_execution(struct kprobe *p, struct pt_regs *regs, int reenter) | ||
429 | { | 430 | { |
430 | struct optimized_kprobe *op; | 431 | struct optimized_kprobe *op; |
431 | 432 | ||
@@ -441,3 +442,4 @@ setup_detour_execution(struct kprobe *p, struct pt_regs *regs, int reenter) | |||
441 | } | 442 | } |
442 | return 0; | 443 | return 0; |
443 | } | 444 | } |
445 | NOKPROBE_SYMBOL(setup_detour_execution); | ||