diff options
| author | Masami Hiramatsu <mhiramat@redhat.com> | 2008-03-04 17:29:44 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-03-04 19:35:19 -0500 |
| commit | b2a5cd6938879b5bcfef0a73c28fea84c49519c2 (patch) | |
| tree | e2039a9f7a4766dbea703c6ed32db881863efc1d | |
| parent | 1913130553aa231644eb4e955b1a2c533fe33d17 (diff) | |
kprobes: fix a null pointer bug in register_kretprobe()
Fix a bug in regiseter_kretprobe() which does not check rp->kp.symbol_name ==
NULL before calling kprobe_lookup_name.
For maintainability, this introduces kprobe_addr helper function which
resolves addr field. It is used by register_kprobe and register_kretprobe.
Signed-off-by: Masami Hiramatsu <mhiramat@redhat.com>
Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Cc: Jim Keniston <jkenisto@us.ibm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
| -rw-r--r-- | kernel/kprobes.c | 43 |
1 files changed, 26 insertions, 17 deletions
diff --git a/kernel/kprobes.c b/kernel/kprobes.c index e6a61dcbc578..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)) |
| @@ -721,12 +730,12 @@ int __kprobes register_kretprobe(struct kretprobe *rp) | |||
| 721 | int ret = 0; | 730 | int ret = 0; |
| 722 | struct kretprobe_instance *inst; | 731 | struct kretprobe_instance *inst; |
| 723 | int i; | 732 | int i; |
| 724 | void *addr = rp->kp.addr; | 733 | void *addr; |
| 725 | 734 | ||
| 726 | if (kretprobe_blacklist_size) { | 735 | if (kretprobe_blacklist_size) { |
| 727 | if (addr == NULL) | 736 | addr = kprobe_addr(&rp->kp); |
| 728 | kprobe_lookup_name(rp->kp.symbol_name, addr); | 737 | if (!addr) |
| 729 | addr += rp->kp.offset; | 738 | return -EINVAL; |
| 730 | 739 | ||
| 731 | for (i = 0; kretprobe_blacklist[i].name != NULL; i++) { | 740 | for (i = 0; kretprobe_blacklist[i].name != NULL; i++) { |
| 732 | if (kretprobe_blacklist[i].addr == addr) | 741 | if (kretprobe_blacklist[i].addr == addr) |
