diff options
Diffstat (limited to 'arch/i386/kernel/kprobes.c')
-rw-r--r-- | arch/i386/kernel/kprobes.c | 253 |
1 files changed, 194 insertions, 59 deletions
diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c index 7a59050242a7..f19768789e8a 100644 --- a/arch/i386/kernel/kprobes.c +++ b/arch/i386/kernel/kprobes.c | |||
@@ -35,12 +35,56 @@ | |||
35 | #include <asm/cacheflush.h> | 35 | #include <asm/cacheflush.h> |
36 | #include <asm/kdebug.h> | 36 | #include <asm/kdebug.h> |
37 | #include <asm/desc.h> | 37 | #include <asm/desc.h> |
38 | #include <asm/uaccess.h> | ||
38 | 39 | ||
39 | void jprobe_return_end(void); | 40 | void jprobe_return_end(void); |
40 | 41 | ||
41 | DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; | 42 | DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; |
42 | DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); | 43 | DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); |
43 | 44 | ||
45 | /* insert a jmp code */ | ||
46 | static inline void set_jmp_op(void *from, void *to) | ||
47 | { | ||
48 | struct __arch_jmp_op { | ||
49 | char op; | ||
50 | long raddr; | ||
51 | } __attribute__((packed)) *jop; | ||
52 | jop = (struct __arch_jmp_op *)from; | ||
53 | jop->raddr = (long)(to) - ((long)(from) + 5); | ||
54 | jop->op = RELATIVEJUMP_INSTRUCTION; | ||
55 | } | ||
56 | |||
57 | /* | ||
58 | * returns non-zero if opcodes can be boosted. | ||
59 | */ | ||
60 | static inline int can_boost(kprobe_opcode_t opcode) | ||
61 | { | ||
62 | switch (opcode & 0xf0 ) { | ||
63 | case 0x70: | ||
64 | return 0; /* can't boost conditional jump */ | ||
65 | case 0x90: | ||
66 | /* can't boost call and pushf */ | ||
67 | return opcode != 0x9a && opcode != 0x9c; | ||
68 | case 0xc0: | ||
69 | /* can't boost undefined opcodes and soft-interruptions */ | ||
70 | return (0xc1 < opcode && opcode < 0xc6) || | ||
71 | (0xc7 < opcode && opcode < 0xcc) || opcode == 0xcf; | ||
72 | case 0xd0: | ||
73 | /* can boost AA* and XLAT */ | ||
74 | return (opcode == 0xd4 || opcode == 0xd5 || opcode == 0xd7); | ||
75 | case 0xe0: | ||
76 | /* can boost in/out and (may be) jmps */ | ||
77 | return (0xe3 < opcode && opcode != 0xe8); | ||
78 | case 0xf0: | ||
79 | /* clear and set flags can be boost */ | ||
80 | return (opcode == 0xf5 || (0xf7 < opcode && opcode < 0xfe)); | ||
81 | default: | ||
82 | /* currently, can't boost 2 bytes opcodes */ | ||
83 | return opcode != 0x0f; | ||
84 | } | ||
85 | } | ||
86 | |||
87 | |||
44 | /* | 88 | /* |
45 | * returns non-zero if opcode modifies the interrupt flag. | 89 | * returns non-zero if opcode modifies the interrupt flag. |
46 | */ | 90 | */ |
@@ -65,6 +109,11 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) | |||
65 | 109 | ||
66 | memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); | 110 | memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); |
67 | p->opcode = *p->addr; | 111 | p->opcode = *p->addr; |
112 | if (can_boost(p->opcode)) { | ||
113 | p->ainsn.boostable = 0; | ||
114 | } else { | ||
115 | p->ainsn.boostable = -1; | ||
116 | } | ||
68 | return 0; | 117 | return 0; |
69 | } | 118 | } |
70 | 119 | ||
@@ -155,9 +204,13 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) | |||
155 | { | 204 | { |
156 | struct kprobe *p; | 205 | struct kprobe *p; |
157 | int ret = 0; | 206 | int ret = 0; |
158 | kprobe_opcode_t *addr = NULL; | 207 | kprobe_opcode_t *addr; |
159 | unsigned long *lp; | ||
160 | struct kprobe_ctlblk *kcb; | 208 | struct kprobe_ctlblk *kcb; |
209 | #ifdef CONFIG_PREEMPT | ||
210 | unsigned pre_preempt_count = preempt_count(); | ||
211 | #endif /* CONFIG_PREEMPT */ | ||
212 | |||
213 | addr = (kprobe_opcode_t *)(regs->eip - sizeof(kprobe_opcode_t)); | ||
161 | 214 | ||
162 | /* | 215 | /* |
163 | * We don't want to be preempted for the entire | 216 | * We don't want to be preempted for the entire |
@@ -166,17 +219,6 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) | |||
166 | preempt_disable(); | 219 | preempt_disable(); |
167 | kcb = get_kprobe_ctlblk(); | 220 | kcb = get_kprobe_ctlblk(); |
168 | 221 | ||
169 | /* Check if the application is using LDT entry for its code segment and | ||
170 | * calculate the address by reading the base address from the LDT entry. | ||
171 | */ | ||
172 | if ((regs->xcs & 4) && (current->mm)) { | ||
173 | lp = (unsigned long *) ((unsigned long)((regs->xcs >> 3) * 8) | ||
174 | + (char *) current->mm->context.ldt); | ||
175 | addr = (kprobe_opcode_t *) (get_desc_base(lp) + regs->eip - | ||
176 | sizeof(kprobe_opcode_t)); | ||
177 | } else { | ||
178 | addr = (kprobe_opcode_t *)(regs->eip - sizeof(kprobe_opcode_t)); | ||
179 | } | ||
180 | /* Check we're not actually recursing */ | 222 | /* Check we're not actually recursing */ |
181 | if (kprobe_running()) { | 223 | if (kprobe_running()) { |
182 | p = get_kprobe(addr); | 224 | p = get_kprobe(addr); |
@@ -252,6 +294,21 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) | |||
252 | /* handler has already set things up, so skip ss setup */ | 294 | /* handler has already set things up, so skip ss setup */ |
253 | return 1; | 295 | return 1; |
254 | 296 | ||
297 | if (p->ainsn.boostable == 1 && | ||
298 | #ifdef CONFIG_PREEMPT | ||
299 | !(pre_preempt_count) && /* | ||
300 | * This enables booster when the direct | ||
301 | * execution path aren't preempted. | ||
302 | */ | ||
303 | #endif /* CONFIG_PREEMPT */ | ||
304 | !p->post_handler && !p->break_handler ) { | ||
305 | /* Boost up -- we can execute copied instructions directly */ | ||
306 | reset_current_kprobe(); | ||
307 | regs->eip = (unsigned long)p->ainsn.insn; | ||
308 | preempt_enable_no_resched(); | ||
309 | return 1; | ||
310 | } | ||
311 | |||
255 | ss_probe: | 312 | ss_probe: |
256 | prepare_singlestep(p, regs); | 313 | prepare_singlestep(p, regs); |
257 | kcb->kprobe_status = KPROBE_HIT_SS; | 314 | kcb->kprobe_status = KPROBE_HIT_SS; |
@@ -267,17 +324,44 @@ no_kprobe: | |||
267 | * here. When a retprobed function returns, this probe is hit and | 324 | * here. When a retprobed function returns, this probe is hit and |
268 | * trampoline_probe_handler() runs, calling the kretprobe's handler. | 325 | * trampoline_probe_handler() runs, calling the kretprobe's handler. |
269 | */ | 326 | */ |
270 | void kretprobe_trampoline_holder(void) | 327 | void __kprobes kretprobe_trampoline_holder(void) |
271 | { | 328 | { |
272 | asm volatile ( ".global kretprobe_trampoline\n" | 329 | asm volatile ( ".global kretprobe_trampoline\n" |
273 | "kretprobe_trampoline: \n" | 330 | "kretprobe_trampoline: \n" |
274 | "nop\n"); | 331 | " pushf\n" |
275 | } | 332 | /* skip cs, eip, orig_eax, es, ds */ |
333 | " subl $20, %esp\n" | ||
334 | " pushl %eax\n" | ||
335 | " pushl %ebp\n" | ||
336 | " pushl %edi\n" | ||
337 | " pushl %esi\n" | ||
338 | " pushl %edx\n" | ||
339 | " pushl %ecx\n" | ||
340 | " pushl %ebx\n" | ||
341 | " movl %esp, %eax\n" | ||
342 | " call trampoline_handler\n" | ||
343 | /* move eflags to cs */ | ||
344 | " movl 48(%esp), %edx\n" | ||
345 | " movl %edx, 44(%esp)\n" | ||
346 | /* save true return address on eflags */ | ||
347 | " movl %eax, 48(%esp)\n" | ||
348 | " popl %ebx\n" | ||
349 | " popl %ecx\n" | ||
350 | " popl %edx\n" | ||
351 | " popl %esi\n" | ||
352 | " popl %edi\n" | ||
353 | " popl %ebp\n" | ||
354 | " popl %eax\n" | ||
355 | /* skip eip, orig_eax, es, ds */ | ||
356 | " addl $16, %esp\n" | ||
357 | " popf\n" | ||
358 | " ret\n"); | ||
359 | } | ||
276 | 360 | ||
277 | /* | 361 | /* |
278 | * Called when we hit the probe point at kretprobe_trampoline | 362 | * Called from kretprobe_trampoline |
279 | */ | 363 | */ |
280 | int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) | 364 | fastcall void *__kprobes trampoline_handler(struct pt_regs *regs) |
281 | { | 365 | { |
282 | struct kretprobe_instance *ri = NULL; | 366 | struct kretprobe_instance *ri = NULL; |
283 | struct hlist_head *head; | 367 | struct hlist_head *head; |
@@ -306,8 +390,11 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) | |||
306 | /* another task is sharing our hash bucket */ | 390 | /* another task is sharing our hash bucket */ |
307 | continue; | 391 | continue; |
308 | 392 | ||
309 | if (ri->rp && ri->rp->handler) | 393 | if (ri->rp && ri->rp->handler){ |
394 | __get_cpu_var(current_kprobe) = &ri->rp->kp; | ||
310 | ri->rp->handler(ri, regs); | 395 | ri->rp->handler(ri, regs); |
396 | __get_cpu_var(current_kprobe) = NULL; | ||
397 | } | ||
311 | 398 | ||
312 | orig_ret_address = (unsigned long)ri->ret_addr; | 399 | orig_ret_address = (unsigned long)ri->ret_addr; |
313 | recycle_rp_inst(ri); | 400 | recycle_rp_inst(ri); |
@@ -322,18 +409,10 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) | |||
322 | } | 409 | } |
323 | 410 | ||
324 | BUG_ON(!orig_ret_address || (orig_ret_address == trampoline_address)); | 411 | BUG_ON(!orig_ret_address || (orig_ret_address == trampoline_address)); |
325 | regs->eip = orig_ret_address; | ||
326 | 412 | ||
327 | reset_current_kprobe(); | ||
328 | spin_unlock_irqrestore(&kretprobe_lock, flags); | 413 | spin_unlock_irqrestore(&kretprobe_lock, flags); |
329 | preempt_enable_no_resched(); | ||
330 | 414 | ||
331 | /* | 415 | return (void*)orig_ret_address; |
332 | * By returning a non-zero value, we are telling | ||
333 | * kprobe_handler() that we don't want the post_handler | ||
334 | * to run (and have re-enabled preemption) | ||
335 | */ | ||
336 | return 1; | ||
337 | } | 416 | } |
338 | 417 | ||
339 | /* | 418 | /* |
@@ -357,15 +436,17 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) | |||
357 | * 2) If the single-stepped instruction was a call, the return address | 436 | * 2) If the single-stepped instruction was a call, the return address |
358 | * that is atop the stack is the address following the copied instruction. | 437 | * that is atop the stack is the address following the copied instruction. |
359 | * We need to make it the address following the original instruction. | 438 | * We need to make it the address following the original instruction. |
439 | * | ||
440 | * This function also checks instruction size for preparing direct execution. | ||
360 | */ | 441 | */ |
361 | static void __kprobes resume_execution(struct kprobe *p, | 442 | static void __kprobes resume_execution(struct kprobe *p, |
362 | struct pt_regs *regs, struct kprobe_ctlblk *kcb) | 443 | struct pt_regs *regs, struct kprobe_ctlblk *kcb) |
363 | { | 444 | { |
364 | unsigned long *tos = (unsigned long *)®s->esp; | 445 | unsigned long *tos = (unsigned long *)®s->esp; |
365 | unsigned long next_eip = 0; | ||
366 | unsigned long copy_eip = (unsigned long)p->ainsn.insn; | 446 | unsigned long copy_eip = (unsigned long)p->ainsn.insn; |
367 | unsigned long orig_eip = (unsigned long)p->addr; | 447 | unsigned long orig_eip = (unsigned long)p->addr; |
368 | 448 | ||
449 | regs->eflags &= ~TF_MASK; | ||
369 | switch (p->ainsn.insn[0]) { | 450 | switch (p->ainsn.insn[0]) { |
370 | case 0x9c: /* pushfl */ | 451 | case 0x9c: /* pushfl */ |
371 | *tos &= ~(TF_MASK | IF_MASK); | 452 | *tos &= ~(TF_MASK | IF_MASK); |
@@ -375,37 +456,51 @@ static void __kprobes resume_execution(struct kprobe *p, | |||
375 | case 0xcb: | 456 | case 0xcb: |
376 | case 0xc2: | 457 | case 0xc2: |
377 | case 0xca: | 458 | case 0xca: |
378 | regs->eflags &= ~TF_MASK; | 459 | case 0xea: /* jmp absolute -- eip is correct */ |
379 | /* eip is already adjusted, no more changes required*/ | 460 | /* eip is already adjusted, no more changes required */ |
380 | return; | 461 | p->ainsn.boostable = 1; |
462 | goto no_change; | ||
381 | case 0xe8: /* call relative - Fix return addr */ | 463 | case 0xe8: /* call relative - Fix return addr */ |
382 | *tos = orig_eip + (*tos - copy_eip); | 464 | *tos = orig_eip + (*tos - copy_eip); |
383 | break; | 465 | break; |
384 | case 0xff: | 466 | case 0xff: |
385 | if ((p->ainsn.insn[1] & 0x30) == 0x10) { | 467 | if ((p->ainsn.insn[1] & 0x30) == 0x10) { |
386 | /* call absolute, indirect */ | 468 | /* call absolute, indirect */ |
387 | /* Fix return addr; eip is correct. */ | 469 | /* |
388 | next_eip = regs->eip; | 470 | * Fix return addr; eip is correct. |
471 | * But this is not boostable | ||
472 | */ | ||
389 | *tos = orig_eip + (*tos - copy_eip); | 473 | *tos = orig_eip + (*tos - copy_eip); |
474 | goto no_change; | ||
390 | } else if (((p->ainsn.insn[1] & 0x31) == 0x20) || /* jmp near, absolute indirect */ | 475 | } else if (((p->ainsn.insn[1] & 0x31) == 0x20) || /* jmp near, absolute indirect */ |
391 | ((p->ainsn.insn[1] & 0x31) == 0x21)) { /* jmp far, absolute indirect */ | 476 | ((p->ainsn.insn[1] & 0x31) == 0x21)) { /* jmp far, absolute indirect */ |
392 | /* eip is correct. */ | 477 | /* eip is correct. And this is boostable */ |
393 | next_eip = regs->eip; | 478 | p->ainsn.boostable = 1; |
479 | goto no_change; | ||
394 | } | 480 | } |
395 | break; | ||
396 | case 0xea: /* jmp absolute -- eip is correct */ | ||
397 | next_eip = regs->eip; | ||
398 | break; | ||
399 | default: | 481 | default: |
400 | break; | 482 | break; |
401 | } | 483 | } |
402 | 484 | ||
403 | regs->eflags &= ~TF_MASK; | 485 | if (p->ainsn.boostable == 0) { |
404 | if (next_eip) { | 486 | if ((regs->eip > copy_eip) && |
405 | regs->eip = next_eip; | 487 | (regs->eip - copy_eip) + 5 < MAX_INSN_SIZE) { |
406 | } else { | 488 | /* |
407 | regs->eip = orig_eip + (regs->eip - copy_eip); | 489 | * These instructions can be executed directly if it |
490 | * jumps back to correct address. | ||
491 | */ | ||
492 | set_jmp_op((void *)regs->eip, | ||
493 | (void *)orig_eip + (regs->eip - copy_eip)); | ||
494 | p->ainsn.boostable = 1; | ||
495 | } else { | ||
496 | p->ainsn.boostable = -1; | ||
497 | } | ||
408 | } | 498 | } |
499 | |||
500 | regs->eip = orig_eip + (regs->eip - copy_eip); | ||
501 | |||
502 | no_change: | ||
503 | return; | ||
409 | } | 504 | } |
410 | 505 | ||
411 | /* | 506 | /* |
@@ -453,15 +548,57 @@ static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr) | |||
453 | struct kprobe *cur = kprobe_running(); | 548 | struct kprobe *cur = kprobe_running(); |
454 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); | 549 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); |
455 | 550 | ||
456 | if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr)) | 551 | switch(kcb->kprobe_status) { |
457 | return 1; | 552 | case KPROBE_HIT_SS: |
458 | 553 | case KPROBE_REENTER: | |
459 | if (kcb->kprobe_status & KPROBE_HIT_SS) { | 554 | /* |
460 | resume_execution(cur, regs, kcb); | 555 | * We are here because the instruction being single |
556 | * stepped caused a page fault. We reset the current | ||
557 | * kprobe and the eip points back to the probe address | ||
558 | * and allow the page fault handler to continue as a | ||
559 | * normal page fault. | ||
560 | */ | ||
561 | regs->eip = (unsigned long)cur->addr; | ||
461 | regs->eflags |= kcb->kprobe_old_eflags; | 562 | regs->eflags |= kcb->kprobe_old_eflags; |
462 | 563 | if (kcb->kprobe_status == KPROBE_REENTER) | |
463 | reset_current_kprobe(); | 564 | restore_previous_kprobe(kcb); |
565 | else | ||
566 | reset_current_kprobe(); | ||
464 | preempt_enable_no_resched(); | 567 | preempt_enable_no_resched(); |
568 | break; | ||
569 | case KPROBE_HIT_ACTIVE: | ||
570 | case KPROBE_HIT_SSDONE: | ||
571 | /* | ||
572 | * We increment the nmissed count for accounting, | ||
573 | * we can also use npre/npostfault count for accouting | ||
574 | * these specific fault cases. | ||
575 | */ | ||
576 | kprobes_inc_nmissed_count(cur); | ||
577 | |||
578 | /* | ||
579 | * We come here because instructions in the pre/post | ||
580 | * handler caused the page_fault, this could happen | ||
581 | * if handler tries to access user space by | ||
582 | * copy_from_user(), get_user() etc. Let the | ||
583 | * user-specified handler try to fix it first. | ||
584 | */ | ||
585 | if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr)) | ||
586 | return 1; | ||
587 | |||
588 | /* | ||
589 | * In case the user-specified fault handler returned | ||
590 | * zero, try to fix up. | ||
591 | */ | ||
592 | if (fixup_exception(regs)) | ||
593 | return 1; | ||
594 | |||
595 | /* | ||
596 | * fixup_exception() could not handle it, | ||
597 | * Let do_page_fault() fix it. | ||
598 | */ | ||
599 | break; | ||
600 | default: | ||
601 | break; | ||
465 | } | 602 | } |
466 | return 0; | 603 | return 0; |
467 | } | 604 | } |
@@ -475,6 +612,9 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, | |||
475 | struct die_args *args = (struct die_args *)data; | 612 | struct die_args *args = (struct die_args *)data; |
476 | int ret = NOTIFY_DONE; | 613 | int ret = NOTIFY_DONE; |
477 | 614 | ||
615 | if (args->regs && user_mode(args->regs)) | ||
616 | return ret; | ||
617 | |||
478 | switch (val) { | 618 | switch (val) { |
479 | case DIE_INT3: | 619 | case DIE_INT3: |
480 | if (kprobe_handler(args->regs)) | 620 | if (kprobe_handler(args->regs)) |
@@ -564,12 +704,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) | |||
564 | return 0; | 704 | return 0; |
565 | } | 705 | } |
566 | 706 | ||
567 | static struct kprobe trampoline_p = { | ||
568 | .addr = (kprobe_opcode_t *) &kretprobe_trampoline, | ||
569 | .pre_handler = trampoline_probe_handler | ||
570 | }; | ||
571 | |||
572 | int __init arch_init_kprobes(void) | 707 | int __init arch_init_kprobes(void) |
573 | { | 708 | { |
574 | return register_kprobe(&trampoline_p); | 709 | return 0; |
575 | } | 710 | } |