This is the mail archive of the
systemtap@sourceware.org
mailing list for the systemtap project.
[BUG][PATCH] Kprobes: Reference count the modules when probed on it
- From: "Mao, Bibo" <bibo dot mao at intel dot com>
- To: <linux-kernel at vger dot kernel dot org>, <akpm at osdl dot org>
- Cc: <systemtap at sources dot redhat dot com>
- Date: Thu, 1 Dec 2005 11:32:00 +0800
- Subject: [BUG][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: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
Signed-off-by: Mao Bibo <bibo.mao@intel.com>
kernel/kprobes.c | 18 ++++++++++++++++--
1 files changed, 16 insertions(+), 2 deletions(-)
Index: linux-2.6.15-rc3/kernel/kprobes.c
===================================================================
--- linux-2.6.15-rc3.orig/kernel/kprobes.c
+++ linux-2.6.15-rc3/kernel/kprobes.c
@@ -462,9 +462,16 @@ int __kprobes register_kprobe(struct kpr
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
{
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
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);