Commit b3e55c72 authored by Mao, Bibo's avatar Mao, Bibo Committed by Linus Torvalds

[PATCH] Kprobes: Reference count the modules when probed on it

When a Kprobes are inserted/removed on a modules, the modules must be ref
counted so as not to allow to unload while probes are registered on that
module.

Without this patch, the probed module is free to unload, and when the
probing module unregister the probe, the kpobes code while trying to
replace the original instruction might crash.
Signed-off-by: default avatarAnil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
Signed-off-by: default avatarMao Bibo <bibo.mao@intel.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 3fe968f1
...@@ -462,9 +462,16 @@ int __kprobes register_kprobe(struct kprobe *p) ...@@ -462,9 +462,16 @@ int __kprobes register_kprobe(struct kprobe *p)
int ret = 0; int ret = 0;
unsigned long flags = 0; unsigned long flags = 0;
struct kprobe *old_p; struct kprobe *old_p;
struct module *mod;
if ((!kernel_text_address((unsigned long) p->addr)) ||
in_kprobes_functions((unsigned long) p->addr))
return -EINVAL;
if ((mod = module_text_address((unsigned long) p->addr)) &&
(unlikely(!try_module_get(mod))))
return -EINVAL;
if ((ret = in_kprobes_functions((unsigned long) p->addr)) != 0)
return ret;
if ((ret = arch_prepare_kprobe(p)) != 0) if ((ret = arch_prepare_kprobe(p)) != 0)
goto rm_kprobe; goto rm_kprobe;
...@@ -488,6 +495,8 @@ int __kprobes register_kprobe(struct kprobe *p) ...@@ -488,6 +495,8 @@ int __kprobes register_kprobe(struct kprobe *p)
rm_kprobe: rm_kprobe:
if (ret == -EEXIST) if (ret == -EEXIST)
arch_remove_kprobe(p); arch_remove_kprobe(p);
if (ret && mod)
module_put(mod);
return ret; return ret;
} }
...@@ -495,6 +504,7 @@ void __kprobes unregister_kprobe(struct kprobe *p) ...@@ -495,6 +504,7 @@ void __kprobes unregister_kprobe(struct kprobe *p)
{ {
unsigned long flags; unsigned long flags;
struct kprobe *old_p; struct kprobe *old_p;
struct module *mod;
spin_lock_irqsave(&kprobe_lock, flags); spin_lock_irqsave(&kprobe_lock, flags);
old_p = get_kprobe(p->addr); old_p = get_kprobe(p->addr);
...@@ -506,6 +516,10 @@ void __kprobes unregister_kprobe(struct kprobe *p) ...@@ -506,6 +516,10 @@ void __kprobes unregister_kprobe(struct kprobe *p)
cleanup_kprobe(p, flags); cleanup_kprobe(p, flags);
synchronize_sched(); synchronize_sched();
if ((mod = module_text_address((unsigned long)p->addr)))
module_put(mod);
if (old_p->pre_handler == aggr_pre_handler && if (old_p->pre_handler == aggr_pre_handler &&
list_empty(&old_p->list)) list_empty(&old_p->list))
kfree(old_p); kfree(old_p);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment