aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/kprobes.c
diff options
context:
space:
mode:
authorMasami Hiramatsu <mhiramat@redhat.com>2008-03-04 17:29:44 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-03-04 19:35:19 -0500
commitb2a5cd6938879b5bcfef0a73c28fea84c49519c2 (patch)
treee2039a9f7a4766dbea703c6ed32db881863efc1d /kernel/kprobes.c
parent1913130553aa231644eb4e955b1a2c533fe33d17 (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>
Diffstat (limited to 'kernel/kprobes.c')
-rw-r--r--kernel/kprobes.c43
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 */
505static 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
501static int __kprobes __register_kprobe(struct kprobe *p, 519static 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)