diff options
Diffstat (limited to 'kernel/kprobes.c')
-rw-r--r-- | kernel/kprobes.c | 19 |
1 files changed, 14 insertions, 5 deletions
diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 7ba8cd9845cb..5016bfb682b9 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <linux/seq_file.h> | 43 | #include <linux/seq_file.h> |
44 | #include <linux/debugfs.h> | 44 | #include <linux/debugfs.h> |
45 | #include <linux/kdebug.h> | 45 | #include <linux/kdebug.h> |
46 | #include <linux/memory.h> | ||
46 | 47 | ||
47 | #include <asm-generic/sections.h> | 48 | #include <asm-generic/sections.h> |
48 | #include <asm/cacheflush.h> | 49 | #include <asm/cacheflush.h> |
@@ -699,9 +700,10 @@ int __kprobes register_kprobe(struct kprobe *p) | |||
699 | goto out; | 700 | goto out; |
700 | } | 701 | } |
701 | 702 | ||
703 | mutex_lock(&text_mutex); | ||
702 | ret = arch_prepare_kprobe(p); | 704 | ret = arch_prepare_kprobe(p); |
703 | if (ret) | 705 | if (ret) |
704 | goto out; | 706 | goto out_unlock_text; |
705 | 707 | ||
706 | INIT_HLIST_NODE(&p->hlist); | 708 | INIT_HLIST_NODE(&p->hlist); |
707 | hlist_add_head_rcu(&p->hlist, | 709 | hlist_add_head_rcu(&p->hlist, |
@@ -710,6 +712,8 @@ int __kprobes register_kprobe(struct kprobe *p) | |||
710 | if (kprobe_enabled) | 712 | if (kprobe_enabled) |
711 | arch_arm_kprobe(p); | 713 | arch_arm_kprobe(p); |
712 | 714 | ||
715 | out_unlock_text: | ||
716 | mutex_unlock(&text_mutex); | ||
713 | out: | 717 | out: |
714 | mutex_unlock(&kprobe_mutex); | 718 | mutex_unlock(&kprobe_mutex); |
715 | 719 | ||
@@ -746,8 +750,11 @@ valid_p: | |||
746 | * enabled and not gone - otherwise, the breakpoint would | 750 | * enabled and not gone - otherwise, the breakpoint would |
747 | * already have been removed. We save on flushing icache. | 751 | * already have been removed. We save on flushing icache. |
748 | */ | 752 | */ |
749 | if (kprobe_enabled && !kprobe_gone(old_p)) | 753 | if (kprobe_enabled && !kprobe_gone(old_p)) { |
754 | mutex_lock(&text_mutex); | ||
750 | arch_disarm_kprobe(p); | 755 | arch_disarm_kprobe(p); |
756 | mutex_unlock(&text_mutex); | ||
757 | } | ||
751 | hlist_del_rcu(&old_p->hlist); | 758 | hlist_del_rcu(&old_p->hlist); |
752 | } else { | 759 | } else { |
753 | if (p->break_handler && !kprobe_gone(p)) | 760 | if (p->break_handler && !kprobe_gone(p)) |
@@ -912,10 +919,8 @@ static int __kprobes pre_handler_kretprobe(struct kprobe *p, | |||
912 | ri->rp = rp; | 919 | ri->rp = rp; |
913 | ri->task = current; | 920 | ri->task = current; |
914 | 921 | ||
915 | if (rp->entry_handler && rp->entry_handler(ri, regs)) { | 922 | if (rp->entry_handler && rp->entry_handler(ri, regs)) |
916 | spin_unlock_irqrestore(&rp->lock, flags); | ||
917 | return 0; | 923 | return 0; |
918 | } | ||
919 | 924 | ||
920 | arch_prepare_kretprobe(ri, regs); | 925 | arch_prepare_kretprobe(ri, regs); |
921 | 926 | ||
@@ -1280,12 +1285,14 @@ static void __kprobes enable_all_kprobes(void) | |||
1280 | if (kprobe_enabled) | 1285 | if (kprobe_enabled) |
1281 | goto already_enabled; | 1286 | goto already_enabled; |
1282 | 1287 | ||
1288 | mutex_lock(&text_mutex); | ||
1283 | for (i = 0; i < KPROBE_TABLE_SIZE; i++) { | 1289 | for (i = 0; i < KPROBE_TABLE_SIZE; i++) { |
1284 | head = &kprobe_table[i]; | 1290 | head = &kprobe_table[i]; |
1285 | hlist_for_each_entry_rcu(p, node, head, hlist) | 1291 | hlist_for_each_entry_rcu(p, node, head, hlist) |
1286 | if (!kprobe_gone(p)) | 1292 | if (!kprobe_gone(p)) |
1287 | arch_arm_kprobe(p); | 1293 | arch_arm_kprobe(p); |
1288 | } | 1294 | } |
1295 | mutex_unlock(&text_mutex); | ||
1289 | 1296 | ||
1290 | kprobe_enabled = true; | 1297 | kprobe_enabled = true; |
1291 | printk(KERN_INFO "Kprobes globally enabled\n"); | 1298 | printk(KERN_INFO "Kprobes globally enabled\n"); |
@@ -1310,6 +1317,7 @@ static void __kprobes disable_all_kprobes(void) | |||
1310 | 1317 | ||
1311 | kprobe_enabled = false; | 1318 | kprobe_enabled = false; |
1312 | printk(KERN_INFO "Kprobes globally disabled\n"); | 1319 | printk(KERN_INFO "Kprobes globally disabled\n"); |
1320 | mutex_lock(&text_mutex); | ||
1313 | for (i = 0; i < KPROBE_TABLE_SIZE; i++) { | 1321 | for (i = 0; i < KPROBE_TABLE_SIZE; i++) { |
1314 | head = &kprobe_table[i]; | 1322 | head = &kprobe_table[i]; |
1315 | hlist_for_each_entry_rcu(p, node, head, hlist) { | 1323 | hlist_for_each_entry_rcu(p, node, head, hlist) { |
@@ -1318,6 +1326,7 @@ static void __kprobes disable_all_kprobes(void) | |||
1318 | } | 1326 | } |
1319 | } | 1327 | } |
1320 | 1328 | ||
1329 | mutex_unlock(&text_mutex); | ||
1321 | mutex_unlock(&kprobe_mutex); | 1330 | mutex_unlock(&kprobe_mutex); |
1322 | /* Allow all currently running kprobes to complete */ | 1331 | /* Allow all currently running kprobes to complete */ |
1323 | synchronize_sched(); | 1332 | synchronize_sched(); |