mirror of
https://github.com/adulau/aha.git
synced 2024-12-28 03:36:19 +00:00
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>
This commit is contained in:
parent
1913130553
commit
b2a5cd6938
1 changed files with 26 additions and 17 deletions
|
@ -498,27 +498,36 @@ static int __kprobes in_kprobes_functions(unsigned long addr)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we have a symbol_name argument, look it up and add the offset field
|
||||||
|
* to it. This way, we can specify a relative address to a symbol.
|
||||||
|
*/
|
||||||
|
static kprobe_opcode_t __kprobes *kprobe_addr(struct kprobe *p)
|
||||||
|
{
|
||||||
|
kprobe_opcode_t *addr = p->addr;
|
||||||
|
if (p->symbol_name) {
|
||||||
|
if (addr)
|
||||||
|
return NULL;
|
||||||
|
kprobe_lookup_name(p->symbol_name, addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!addr)
|
||||||
|
return NULL;
|
||||||
|
return (kprobe_opcode_t *)(((char *)addr) + p->offset);
|
||||||
|
}
|
||||||
|
|
||||||
static int __kprobes __register_kprobe(struct kprobe *p,
|
static int __kprobes __register_kprobe(struct kprobe *p,
|
||||||
unsigned long called_from)
|
unsigned long called_from)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct kprobe *old_p;
|
struct kprobe *old_p;
|
||||||
struct module *probed_mod;
|
struct module *probed_mod;
|
||||||
|
kprobe_opcode_t *addr;
|
||||||
|
|
||||||
/*
|
addr = kprobe_addr(p);
|
||||||
* If we have a symbol_name argument look it up,
|
if (!addr)
|
||||||
* and add it to the address. That way the addr
|
|
||||||
* field can either be global or relative to a symbol.
|
|
||||||
*/
|
|
||||||
if (p->symbol_name) {
|
|
||||||
if (p->addr)
|
|
||||||
return -EINVAL;
|
|
||||||
kprobe_lookup_name(p->symbol_name, p->addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!p->addr)
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
p->addr = (kprobe_opcode_t *)(((char *)p->addr)+ p->offset);
|
p->addr = addr;
|
||||||
|
|
||||||
if (!kernel_text_address((unsigned long) p->addr) ||
|
if (!kernel_text_address((unsigned long) p->addr) ||
|
||||||
in_kprobes_functions((unsigned long) p->addr))
|
in_kprobes_functions((unsigned long) p->addr))
|
||||||
|
@ -721,12 +730,12 @@ int __kprobes register_kretprobe(struct kretprobe *rp)
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct kretprobe_instance *inst;
|
struct kretprobe_instance *inst;
|
||||||
int i;
|
int i;
|
||||||
void *addr = rp->kp.addr;
|
void *addr;
|
||||||
|
|
||||||
if (kretprobe_blacklist_size) {
|
if (kretprobe_blacklist_size) {
|
||||||
if (addr == NULL)
|
addr = kprobe_addr(&rp->kp);
|
||||||
kprobe_lookup_name(rp->kp.symbol_name, addr);
|
if (!addr)
|
||||||
addr += rp->kp.offset;
|
return -EINVAL;
|
||||||
|
|
||||||
for (i = 0; kretprobe_blacklist[i].name != NULL; i++) {
|
for (i = 0; kretprobe_blacklist[i].name != NULL; i++) {
|
||||||
if (kretprobe_blacklist[i].addr == addr)
|
if (kretprobe_blacklist[i].addr == addr)
|
||||||
|
|
Loading…
Reference in a new issue