diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/kprobes.c | 18 |
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: | |||
488 | rm_kprobe: | 495 | rm_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); |