diff options
Diffstat (limited to 'kernel/kprobes.c')
| -rw-r--r-- | kernel/kprobes.c | 52 |
1 files changed, 29 insertions, 23 deletions
diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 7a86e6432338..fcfb580c3afc 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c | |||
| @@ -498,27 +498,36 @@ static int __kprobes in_kprobes_functions(unsigned long addr) | |||
| 498 | return 0; | 498 | return 0; |
| 499 | } | 499 | } |
| 500 | 500 | ||
| 501 | /* | ||
| 502 | * If we have a symbol_name argument, look it up and add the offset field | ||
| 503 | * to it. This way, we can specify a relative address to a symbol. | ||
| 504 | */ | ||
| 505 | static kprobe_opcode_t __kprobes *kprobe_addr(struct kprobe *p) | ||
| 506 | { | ||
| 507 | kprobe_opcode_t *addr = p->addr; | ||
| 508 | if (p->symbol_name) { | ||
| 509 | if (addr) | ||
| 510 | return NULL; | ||
| 511 | kprobe_lookup_name(p->symbol_name, addr); | ||
| 512 | } | ||
| 513 | |||
| 514 | if (!addr) | ||
| 515 | return NULL; | ||
| 516 | return (kprobe_opcode_t *)(((char *)addr) + p->offset); | ||
| 517 | } | ||
| 518 | |||
| 501 | static int __kprobes __register_kprobe(struct kprobe *p, | 519 | static int __kprobes __register_kprobe(struct kprobe *p, |
| 502 | unsigned long called_from) | 520 | unsigned long called_from) |
| 503 | { | 521 | { |
| 504 | int ret = 0; | 522 | int ret = 0; |
| 505 | struct kprobe *old_p; | 523 | struct kprobe *old_p; |
| 506 | struct module *probed_mod; | 524 | struct module *probed_mod; |
| 525 | kprobe_opcode_t *addr; | ||
| 507 | 526 | ||
| 508 | /* | 527 | addr = kprobe_addr(p); |
| 509 | * If we have a symbol_name argument look it up, | 528 | if (!addr) |
| 510 | * and add it to the address. That way the addr | ||
| 511 | * field can either be global or relative to a symbol. | ||
| 512 | */ | ||
| 513 | if (p->symbol_name) { | ||
| 514 | if (p->addr) | ||
| 515 | return -EINVAL; | ||
| 516 | kprobe_lookup_name(p->symbol_name, p->addr); | ||
| 517 | } | ||
| 518 | |||
| 519 | if (!p->addr) | ||
| 520 | return -EINVAL; | 529 | return -EINVAL; |
| 521 | p->addr = (kprobe_opcode_t *)(((char *)p->addr)+ p->offset); | 530 | p->addr = addr; |
| 522 | 531 | ||
| 523 | if (!kernel_text_address((unsigned long) p->addr) || | 532 | if (!kernel_text_address((unsigned long) p->addr) || |
| 524 | in_kprobes_functions((unsigned long) p->addr)) | 533 | in_kprobes_functions((unsigned long) p->addr)) |
| @@ -678,8 +687,7 @@ void __kprobes unregister_jprobe(struct jprobe *jp) | |||
| 678 | unregister_kprobe(&jp->kp); | 687 | unregister_kprobe(&jp->kp); |
| 679 | } | 688 | } |
| 680 | 689 | ||
| 681 | #ifdef ARCH_SUPPORTS_KRETPROBES | 690 | #ifdef CONFIG_KRETPROBES |
| 682 | |||
| 683 | /* | 691 | /* |
| 684 | * This kprobe pre_handler is registered with every kretprobe. When probe | 692 | * This kprobe pre_handler is registered with every kretprobe. When probe |
| 685 | * hits it will set up the return probe. | 693 | * hits it will set up the return probe. |
| @@ -722,12 +730,12 @@ int __kprobes register_kretprobe(struct kretprobe *rp) | |||
| 722 | int ret = 0; | 730 | int ret = 0; |
| 723 | struct kretprobe_instance *inst; | 731 | struct kretprobe_instance *inst; |
| 724 | int i; | 732 | int i; |
| 725 | void *addr = rp->kp.addr; | 733 | void *addr; |
| 726 | 734 | ||
| 727 | if (kretprobe_blacklist_size) { | 735 | if (kretprobe_blacklist_size) { |
| 728 | if (addr == NULL) | 736 | addr = kprobe_addr(&rp->kp); |
| 729 | kprobe_lookup_name(rp->kp.symbol_name, addr); | 737 | if (!addr) |
| 730 | addr += rp->kp.offset; | 738 | return -EINVAL; |
| 731 | 739 | ||
| 732 | for (i = 0; kretprobe_blacklist[i].name != NULL; i++) { | 740 | for (i = 0; kretprobe_blacklist[i].name != NULL; i++) { |
| 733 | if (kretprobe_blacklist[i].addr == addr) | 741 | if (kretprobe_blacklist[i].addr == addr) |
| @@ -769,8 +777,7 @@ int __kprobes register_kretprobe(struct kretprobe *rp) | |||
| 769 | return ret; | 777 | return ret; |
| 770 | } | 778 | } |
| 771 | 779 | ||
| 772 | #else /* ARCH_SUPPORTS_KRETPROBES */ | 780 | #else /* CONFIG_KRETPROBES */ |
| 773 | |||
| 774 | int __kprobes register_kretprobe(struct kretprobe *rp) | 781 | int __kprobes register_kretprobe(struct kretprobe *rp) |
| 775 | { | 782 | { |
| 776 | return -ENOSYS; | 783 | return -ENOSYS; |
| @@ -781,8 +788,7 @@ static int __kprobes pre_handler_kretprobe(struct kprobe *p, | |||
| 781 | { | 788 | { |
| 782 | return 0; | 789 | return 0; |
| 783 | } | 790 | } |
| 784 | 791 | #endif /* CONFIG_KRETPROBES */ | |
| 785 | #endif /* ARCH_SUPPORTS_KRETPROBES */ | ||
| 786 | 792 | ||
| 787 | void __kprobes unregister_kretprobe(struct kretprobe *rp) | 793 | void __kprobes unregister_kretprobe(struct kretprobe *rp) |
| 788 | { | 794 | { |
