aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMao, Bibo <bibo.mao@intel.com>2005-12-12 03:37:00 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2005-12-12 11:57:41 -0500
commitb3e55c727ff7349c5db722fbdb8d99a151e8e0bf (patch)
tree90d437e565082afe25d68e530e793faeab4b49ac
parent3fe968f167975d10c639f03c4934f05a29da73c0 (diff)
[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> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--kernel/kprobes.c18
1 files changed, 16 insertions, 2 deletions
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 5beda378cc75..fde5a16a2913 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -462,9 +462,16 @@ int __kprobes register_kprobe(struct kprobe *p)
462 int ret = 0; 462 int ret = 0;
463 unsigned long flags = 0; 463 unsigned long flags = 0;
464 struct kprobe *old_p; 464 struct kprobe *old_p;
465 struct module *mod;
466
467 if ((!kernel_text_address((unsigned long) p->addr)) ||
468 in_kprobes_functions((unsigned long) p->addr))
469 return -EINVAL;
470
471 if ((mod = module_text_address((unsigned long) p->addr)) &&
472 (unlikely(!try_module_get(mod))))
473 return -EINVAL;
465 474
466 if ((ret = in_kprobes_functions((unsigned long) p->addr)) != 0)
467 return ret;
468 if ((ret = arch_prepare_kprobe(p)) != 0) 475 if ((ret = arch_prepare_kprobe(p)) != 0)
469 goto rm_kprobe; 476 goto rm_kprobe;
470 477
@@ -488,6 +495,8 @@ out:
488rm_kprobe: 495rm_kprobe:
489 if (ret == -EEXIST) 496 if (ret == -EEXIST)
490 arch_remove_kprobe(p); 497 arch_remove_kprobe(p);
498 if (ret && mod)
499 module_put(mod);
491 return ret; 500 return ret;
492} 501}
493 502
@@ -495,6 +504,7 @@ void __kprobes unregister_kprobe(struct kprobe *p)
495{ 504{
496 unsigned long flags; 505 unsigned long flags;
497 struct kprobe *old_p; 506 struct kprobe *old_p;
507 struct module *mod;
498 508
499 spin_lock_irqsave(&kprobe_lock, flags); 509 spin_lock_irqsave(&kprobe_lock, flags);
500 old_p = get_kprobe(p->addr); 510 old_p = get_kprobe(p->addr);
@@ -506,6 +516,10 @@ void __kprobes unregister_kprobe(struct kprobe *p)
506 cleanup_kprobe(p, flags); 516 cleanup_kprobe(p, flags);
507 517
508 synchronize_sched(); 518 synchronize_sched();
519
520 if ((mod = module_text_address((unsigned long)p->addr)))
521 module_put(mod);
522
509 if (old_p->pre_handler == aggr_pre_handler && 523 if (old_p->pre_handler == aggr_pre_handler &&
510 list_empty(&old_p->list)) 524 list_empty(&old_p->list))
511 kfree(old_p); 525 kfree(old_p);