projects/linux·commit b3e55c72

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

b3e55c72 · Mao, Bibo <[email protected]> · 2005-12-12 00:37:00 -08:00

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: Anil S Keshavamurthy <[email protected]>
Signed-off-by: Mao Bibo <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
Commit
b3e55c727ff7349c5db722fbdb8d99a151e8e0bf
Parents
3fe968f1

Changes

1 files changed · +16 −2

FileStatusAddDelContent
kernel/kprobes.cmodified+16−2View file

kernel/kprobes.c

View file
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 5beda37..fde5a16 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -462,9 +462,16 @@ int __kprobes register_kprobe(struct kprobe *p)
int ret = 0;
unsigned long flags = 0;
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)
goto rm_kprobe;
@@ -488,6 +495,8 @@ out:
rm_kprobe:
if (ret == -EEXIST)
arch_remove_kprobe(p);
+ if (ret && mod)
+ module_put(mod);
return ret;
}
@@ -495,6 +504,7 @@ void __kprobes unregister_kprobe(struct kprobe *p)
{
unsigned long flags;
struct kprobe *old_p;
+ struct module *mod;
spin_lock_irqsave(&kprobe_lock, flags);
old_p = get_kprobe(p->addr);
@@ -506,6 +516,10 @@ void __kprobes unregister_kprobe(struct kprobe *p)
cleanup_kprobe(p, flags);
synchronize_sched();
+
+ if ((mod = module_text_address((unsigned long)p->addr)))
+ module_put(mod);
+
if (old_p->pre_handler == aggr_pre_handler &&
list_empty(&old_p->list))
kfree(old_p);