aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/kprobes.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/kprobes.c')
-rw-r--r--kernel/kprobes.c15
1 files changed, 13 insertions, 2 deletions
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 7ba8cd9845cb..479d4d5672f9 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
715out_unlock_text:
716 mutex_unlock(&text_mutex);
713out: 717out:
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))
@@ -1280,12 +1287,14 @@ static void __kprobes enable_all_kprobes(void)
1280 if (kprobe_enabled) 1287 if (kprobe_enabled)
1281 goto already_enabled; 1288 goto already_enabled;
1282 1289
1290 mutex_lock(&text_mutex);
1283 for (i = 0; i < KPROBE_TABLE_SIZE; i++) { 1291 for (i = 0; i < KPROBE_TABLE_SIZE; i++) {
1284 head = &kprobe_table[i]; 1292 head = &kprobe_table[i];
1285 hlist_for_each_entry_rcu(p, node, head, hlist) 1293 hlist_for_each_entry_rcu(p, node, head, hlist)
1286 if (!kprobe_gone(p)) 1294 if (!kprobe_gone(p))
1287 arch_arm_kprobe(p); 1295 arch_arm_kprobe(p);
1288 } 1296 }
1297 mutex_unlock(&text_mutex);
1289 1298
1290 kprobe_enabled = true; 1299 kprobe_enabled = true;
1291 printk(KERN_INFO "Kprobes globally enabled\n"); 1300 printk(KERN_INFO "Kprobes globally enabled\n");
@@ -1310,6 +1319,7 @@ static void __kprobes disable_all_kprobes(void)
1310 1319
1311 kprobe_enabled = false; 1320 kprobe_enabled = false;
1312 printk(KERN_INFO "Kprobes globally disabled\n"); 1321 printk(KERN_INFO "Kprobes globally disabled\n");
1322 mutex_lock(&text_mutex);
1313 for (i = 0; i < KPROBE_TABLE_SIZE; i++) { 1323 for (i = 0; i < KPROBE_TABLE_SIZE; i++) {
1314 head = &kprobe_table[i]; 1324 head = &kprobe_table[i];
1315 hlist_for_each_entry_rcu(p, node, head, hlist) { 1325 hlist_for_each_entry_rcu(p, node, head, hlist) {
@@ -1318,6 +1328,7 @@ static void __kprobes disable_all_kprobes(void)
1318 } 1328 }
1319 } 1329 }
1320 1330
1331 mutex_unlock(&text_mutex);
1321 mutex_unlock(&kprobe_mutex); 1332 mutex_unlock(&kprobe_mutex);
1322 /* Allow all currently running kprobes to complete */ 1333 /* Allow all currently running kprobes to complete */
1323 synchronize_sched(); 1334 synchronize_sched();