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

Mao, Bibo bibo.mao@intel.com
Thu Dec 1 03:32:00 GMT 2005


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);



More information about the Systemtap mailing list