diff options
Diffstat (limited to 'arch/x86/kernel/kprobes_64.c')
-rw-r--r-- | arch/x86/kernel/kprobes_64.c | 69 |
1 files changed, 35 insertions, 34 deletions
diff --git a/arch/x86/kernel/kprobes_64.c b/arch/x86/kernel/kprobes_64.c index 10d66e323c7d..f6837cd3bed5 100644 --- a/arch/x86/kernel/kprobes_64.c +++ b/arch/x86/kernel/kprobes_64.c | |||
@@ -251,7 +251,7 @@ static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs, | |||
251 | { | 251 | { |
252 | __get_cpu_var(current_kprobe) = p; | 252 | __get_cpu_var(current_kprobe) = p; |
253 | kcb->kprobe_saved_rflags = kcb->kprobe_old_rflags | 253 | kcb->kprobe_saved_rflags = kcb->kprobe_old_rflags |
254 | = (regs->eflags & (TF_MASK | IF_MASK)); | 254 | = (regs->flags & (TF_MASK | IF_MASK)); |
255 | if (is_IF_modifier(p->ainsn.insn)) | 255 | if (is_IF_modifier(p->ainsn.insn)) |
256 | kcb->kprobe_saved_rflags &= ~IF_MASK; | 256 | kcb->kprobe_saved_rflags &= ~IF_MASK; |
257 | } | 257 | } |
@@ -271,20 +271,20 @@ static __always_inline void restore_btf(void) | |||
271 | static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs) | 271 | static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs) |
272 | { | 272 | { |
273 | clear_btf(); | 273 | clear_btf(); |
274 | regs->eflags |= TF_MASK; | 274 | regs->flags |= TF_MASK; |
275 | regs->eflags &= ~IF_MASK; | 275 | regs->flags &= ~IF_MASK; |
276 | /*single step inline if the instruction is an int3*/ | 276 | /*single step inline if the instruction is an int3*/ |
277 | if (p->opcode == BREAKPOINT_INSTRUCTION) | 277 | if (p->opcode == BREAKPOINT_INSTRUCTION) |
278 | regs->rip = (unsigned long)p->addr; | 278 | regs->ip = (unsigned long)p->addr; |
279 | else | 279 | else |
280 | regs->rip = (unsigned long)p->ainsn.insn; | 280 | regs->ip = (unsigned long)p->ainsn.insn; |
281 | } | 281 | } |
282 | 282 | ||
283 | /* Called with kretprobe_lock held */ | 283 | /* Called with kretprobe_lock held */ |
284 | void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri, | 284 | void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri, |
285 | struct pt_regs *regs) | 285 | struct pt_regs *regs) |
286 | { | 286 | { |
287 | unsigned long *sara = (unsigned long *)regs->rsp; | 287 | unsigned long *sara = (unsigned long *)regs->sp; |
288 | 288 | ||
289 | ri->ret_addr = (kprobe_opcode_t *) *sara; | 289 | ri->ret_addr = (kprobe_opcode_t *) *sara; |
290 | /* Replace the return addr with trampoline addr */ | 290 | /* Replace the return addr with trampoline addr */ |
@@ -295,7 +295,7 @@ int __kprobes kprobe_handler(struct pt_regs *regs) | |||
295 | { | 295 | { |
296 | struct kprobe *p; | 296 | struct kprobe *p; |
297 | int ret = 0; | 297 | int ret = 0; |
298 | kprobe_opcode_t *addr = (kprobe_opcode_t *)(regs->rip - sizeof(kprobe_opcode_t)); | 298 | kprobe_opcode_t *addr = (kprobe_opcode_t *)(regs->ip - sizeof(kprobe_opcode_t)); |
299 | struct kprobe_ctlblk *kcb; | 299 | struct kprobe_ctlblk *kcb; |
300 | 300 | ||
301 | /* | 301 | /* |
@@ -311,8 +311,8 @@ int __kprobes kprobe_handler(struct pt_regs *regs) | |||
311 | if (p) { | 311 | if (p) { |
312 | if (kcb->kprobe_status == KPROBE_HIT_SS && | 312 | if (kcb->kprobe_status == KPROBE_HIT_SS && |
313 | *p->ainsn.insn == BREAKPOINT_INSTRUCTION) { | 313 | *p->ainsn.insn == BREAKPOINT_INSTRUCTION) { |
314 | regs->eflags &= ~TF_MASK; | 314 | regs->flags &= ~TF_MASK; |
315 | regs->eflags |= kcb->kprobe_saved_rflags; | 315 | regs->flags |= kcb->kprobe_saved_rflags; |
316 | goto no_kprobe; | 316 | goto no_kprobe; |
317 | } else if (kcb->kprobe_status == KPROBE_HIT_SSDONE) { | 317 | } else if (kcb->kprobe_status == KPROBE_HIT_SSDONE) { |
318 | /* TODO: Provide re-entrancy from | 318 | /* TODO: Provide re-entrancy from |
@@ -321,7 +321,7 @@ int __kprobes kprobe_handler(struct pt_regs *regs) | |||
321 | * the instruction of the new probe. | 321 | * the instruction of the new probe. |
322 | */ | 322 | */ |
323 | arch_disarm_kprobe(p); | 323 | arch_disarm_kprobe(p); |
324 | regs->rip = (unsigned long)p->addr; | 324 | regs->ip = (unsigned long)p->addr; |
325 | reset_current_kprobe(); | 325 | reset_current_kprobe(); |
326 | ret = 1; | 326 | ret = 1; |
327 | } else { | 327 | } else { |
@@ -345,7 +345,7 @@ int __kprobes kprobe_handler(struct pt_regs *regs) | |||
345 | * another cpu right after we hit, no further | 345 | * another cpu right after we hit, no further |
346 | * handling of this interrupt is appropriate | 346 | * handling of this interrupt is appropriate |
347 | */ | 347 | */ |
348 | regs->rip = (unsigned long)addr; | 348 | regs->ip = (unsigned long)addr; |
349 | ret = 1; | 349 | ret = 1; |
350 | goto no_kprobe; | 350 | goto no_kprobe; |
351 | } | 351 | } |
@@ -369,7 +369,7 @@ int __kprobes kprobe_handler(struct pt_regs *regs) | |||
369 | * Back up over the (now missing) int3 and run | 369 | * Back up over the (now missing) int3 and run |
370 | * the original instruction. | 370 | * the original instruction. |
371 | */ | 371 | */ |
372 | regs->rip = (unsigned long)addr; | 372 | regs->ip = (unsigned long)addr; |
373 | ret = 1; | 373 | ret = 1; |
374 | } | 374 | } |
375 | /* Not one of ours: let kernel handle it */ | 375 | /* Not one of ours: let kernel handle it */ |
@@ -454,7 +454,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) | |||
454 | } | 454 | } |
455 | 455 | ||
456 | kretprobe_assert(ri, orig_ret_address, trampoline_address); | 456 | kretprobe_assert(ri, orig_ret_address, trampoline_address); |
457 | regs->rip = orig_ret_address; | 457 | regs->ip = orig_ret_address; |
458 | 458 | ||
459 | reset_current_kprobe(); | 459 | reset_current_kprobe(); |
460 | spin_unlock_irqrestore(&kretprobe_lock, flags); | 460 | spin_unlock_irqrestore(&kretprobe_lock, flags); |
@@ -484,11 +484,11 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) | |||
484 | * interrupt. We have to fix up the stack as follows: | 484 | * interrupt. We have to fix up the stack as follows: |
485 | * | 485 | * |
486 | * 0) Except in the case of absolute or indirect jump or call instructions, | 486 | * 0) Except in the case of absolute or indirect jump or call instructions, |
487 | * the new rip is relative to the copied instruction. We need to make | 487 | * the new ip is relative to the copied instruction. We need to make |
488 | * it relative to the original instruction. | 488 | * it relative to the original instruction. |
489 | * | 489 | * |
490 | * 1) If the single-stepped instruction was pushfl, then the TF and IF | 490 | * 1) If the single-stepped instruction was pushfl, then the TF and IF |
491 | * flags are set in the just-pushed eflags, and may need to be cleared. | 491 | * flags are set in the just-pushed flags, and may need to be cleared. |
492 | * | 492 | * |
493 | * 2) If the single-stepped instruction was a call, the return address | 493 | * 2) If the single-stepped instruction was a call, the return address |
494 | * that is atop the stack is the address following the copied instruction. | 494 | * that is atop the stack is the address following the copied instruction. |
@@ -497,7 +497,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) | |||
497 | static void __kprobes resume_execution(struct kprobe *p, | 497 | static void __kprobes resume_execution(struct kprobe *p, |
498 | struct pt_regs *regs, struct kprobe_ctlblk *kcb) | 498 | struct pt_regs *regs, struct kprobe_ctlblk *kcb) |
499 | { | 499 | { |
500 | unsigned long *tos = (unsigned long *)regs->rsp; | 500 | unsigned long *tos = (unsigned long *)regs->sp; |
501 | unsigned long copy_rip = (unsigned long)p->ainsn.insn; | 501 | unsigned long copy_rip = (unsigned long)p->ainsn.insn; |
502 | unsigned long orig_rip = (unsigned long)p->addr; | 502 | unsigned long orig_rip = (unsigned long)p->addr; |
503 | kprobe_opcode_t *insn = p->ainsn.insn; | 503 | kprobe_opcode_t *insn = p->ainsn.insn; |
@@ -506,7 +506,7 @@ static void __kprobes resume_execution(struct kprobe *p, | |||
506 | if (*insn >= 0x40 && *insn <= 0x4f) | 506 | if (*insn >= 0x40 && *insn <= 0x4f) |
507 | insn++; | 507 | insn++; |
508 | 508 | ||
509 | regs->eflags &= ~TF_MASK; | 509 | regs->flags &= ~TF_MASK; |
510 | switch (*insn) { | 510 | switch (*insn) { |
511 | case 0x9c: /* pushfl */ | 511 | case 0x9c: /* pushfl */ |
512 | *tos &= ~(TF_MASK | IF_MASK); | 512 | *tos &= ~(TF_MASK | IF_MASK); |
@@ -538,7 +538,8 @@ static void __kprobes resume_execution(struct kprobe *p, | |||
538 | break; | 538 | break; |
539 | } | 539 | } |
540 | 540 | ||
541 | regs->rip = orig_rip + (regs->rip - copy_rip); | 541 | regs->ip = orig_rip + (regs->ip - copy_rip); |
542 | |||
542 | no_change: | 543 | no_change: |
543 | restore_btf(); | 544 | restore_btf(); |
544 | 545 | ||
@@ -559,8 +560,8 @@ int __kprobes post_kprobe_handler(struct pt_regs *regs) | |||
559 | } | 560 | } |
560 | 561 | ||
561 | resume_execution(cur, regs, kcb); | 562 | resume_execution(cur, regs, kcb); |
562 | regs->eflags |= kcb->kprobe_saved_rflags; | 563 | regs->flags |= kcb->kprobe_saved_rflags; |
563 | trace_hardirqs_fixup_flags(regs->eflags); | 564 | trace_hardirqs_fixup_flags(regs->flags); |
564 | 565 | ||
565 | /* Restore the original saved kprobes variables and continue. */ | 566 | /* Restore the original saved kprobes variables and continue. */ |
566 | if (kcb->kprobe_status == KPROBE_REENTER) { | 567 | if (kcb->kprobe_status == KPROBE_REENTER) { |
@@ -572,11 +573,11 @@ out: | |||
572 | preempt_enable_no_resched(); | 573 | preempt_enable_no_resched(); |
573 | 574 | ||
574 | /* | 575 | /* |
575 | * if somebody else is singlestepping across a probe point, eflags | 576 | * if somebody else is singlestepping across a probe point, flags |
576 | * will have TF set, in which case, continue the remaining processing | 577 | * will have TF set, in which case, continue the remaining processing |
577 | * of do_debug, as if this is not a probe hit. | 578 | * of do_debug, as if this is not a probe hit. |
578 | */ | 579 | */ |
579 | if (regs->eflags & TF_MASK) | 580 | if (regs->flags & TF_MASK) |
580 | return 0; | 581 | return 0; |
581 | 582 | ||
582 | return 1; | 583 | return 1; |
@@ -594,12 +595,12 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) | |||
594 | /* | 595 | /* |
595 | * We are here because the instruction being single | 596 | * We are here because the instruction being single |
596 | * stepped caused a page fault. We reset the current | 597 | * stepped caused a page fault. We reset the current |
597 | * kprobe and the rip points back to the probe address | 598 | * kprobe and the ip points back to the probe address |
598 | * and allow the page fault handler to continue as a | 599 | * and allow the page fault handler to continue as a |
599 | * normal page fault. | 600 | * normal page fault. |
600 | */ | 601 | */ |
601 | regs->rip = (unsigned long)cur->addr; | 602 | regs->ip = (unsigned long)cur->addr; |
602 | regs->eflags |= kcb->kprobe_old_rflags; | 603 | regs->flags |= kcb->kprobe_old_rflags; |
603 | if (kcb->kprobe_status == KPROBE_REENTER) | 604 | if (kcb->kprobe_status == KPROBE_REENTER) |
604 | restore_previous_kprobe(kcb); | 605 | restore_previous_kprobe(kcb); |
605 | else | 606 | else |
@@ -629,9 +630,9 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) | |||
629 | * In case the user-specified fault handler returned | 630 | * In case the user-specified fault handler returned |
630 | * zero, try to fix up. | 631 | * zero, try to fix up. |
631 | */ | 632 | */ |
632 | fixup = search_exception_tables(regs->rip); | 633 | fixup = search_exception_tables(regs->ip); |
633 | if (fixup) { | 634 | if (fixup) { |
634 | regs->rip = fixup->fixup; | 635 | regs->ip = fixup->fixup; |
635 | return 1; | 636 | return 1; |
636 | } | 637 | } |
637 | 638 | ||
@@ -688,7 +689,7 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) | |||
688 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); | 689 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); |
689 | 690 | ||
690 | kcb->jprobe_saved_regs = *regs; | 691 | kcb->jprobe_saved_regs = *regs; |
691 | kcb->jprobe_saved_rsp = (long *) regs->rsp; | 692 | kcb->jprobe_saved_rsp = (long *) regs->sp; |
692 | addr = (unsigned long)(kcb->jprobe_saved_rsp); | 693 | addr = (unsigned long)(kcb->jprobe_saved_rsp); |
693 | /* | 694 | /* |
694 | * As Linus pointed out, gcc assumes that the callee | 695 | * As Linus pointed out, gcc assumes that the callee |
@@ -699,9 +700,9 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) | |||
699 | */ | 700 | */ |
700 | memcpy(kcb->jprobes_stack, (kprobe_opcode_t *)addr, | 701 | memcpy(kcb->jprobes_stack, (kprobe_opcode_t *)addr, |
701 | MIN_STACK_SIZE(addr)); | 702 | MIN_STACK_SIZE(addr)); |
702 | regs->eflags &= ~IF_MASK; | 703 | regs->flags &= ~IF_MASK; |
703 | trace_hardirqs_off(); | 704 | trace_hardirqs_off(); |
704 | regs->rip = (unsigned long)(jp->entry); | 705 | regs->ip = (unsigned long)(jp->entry); |
705 | return 1; | 706 | return 1; |
706 | } | 707 | } |
707 | 708 | ||
@@ -720,15 +721,15 @@ void __kprobes jprobe_return(void) | |||
720 | int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) | 721 | int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) |
721 | { | 722 | { |
722 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); | 723 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); |
723 | u8 *addr = (u8 *) (regs->rip - 1); | 724 | u8 *addr = (u8 *) (regs->ip - 1); |
724 | unsigned long stack_addr = (unsigned long)(kcb->jprobe_saved_rsp); | 725 | unsigned long stack_addr = (unsigned long)(kcb->jprobe_saved_rsp); |
725 | struct jprobe *jp = container_of(p, struct jprobe, kp); | 726 | struct jprobe *jp = container_of(p, struct jprobe, kp); |
726 | 727 | ||
727 | if ((addr > (u8 *) jprobe_return) && (addr < (u8 *) jprobe_return_end)) { | 728 | if ((addr > (u8 *) jprobe_return) && (addr < (u8 *) jprobe_return_end)) { |
728 | if ((unsigned long *)regs->rsp != kcb->jprobe_saved_rsp) { | 729 | if ((unsigned long *)regs->sp != kcb->jprobe_saved_rsp) { |
729 | struct pt_regs *saved_regs = &kcb->jprobe_saved_regs; | 730 | struct pt_regs *saved_regs = &kcb->jprobe_saved_regs; |
730 | printk("current rsp %p does not match saved rsp %p\n", | 731 | printk("current sp %p does not match saved sp %p\n", |
731 | (long *)regs->rsp, kcb->jprobe_saved_rsp); | 732 | (long *)regs->sp, kcb->jprobe_saved_rsp); |
732 | printk("Saved registers for jprobe %p\n", jp); | 733 | printk("Saved registers for jprobe %p\n", jp); |
733 | show_registers(saved_regs); | 734 | show_registers(saved_regs); |
734 | printk("Current registers\n"); | 735 | printk("Current registers\n"); |