aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJessica Yu <jeyu@kernel.org>2018-01-09 18:51:23 -0500
committerIngo Molnar <mingo@kernel.org>2018-02-16 03:12:52 -0500
commit12310e3437554328bcd75186cf331bc712cb30b2 (patch)
tree2c1a0bd4b6f30c11f90cbf75066001a402148e98
parent3f9e6463132ac2447351805875d4e06b4fd51683 (diff)
kprobes: Propagate error from arm_kprobe_ftrace()
Improve error handling when arming ftrace-based kprobes. Specifically, if we fail to arm a ftrace-based kprobe, register_kprobe()/enable_kprobe() should report an error instead of success. Previously, this has lead to confusing situations where register_kprobe() would return 0 indicating success, but the kprobe would not be functional if ftrace registration during the kprobe arming process had failed. We should therefore take any errors returned by ftrace into account and propagate this error so that we do not register/enable kprobes that cannot be armed. This can happen if, for example, register_ftrace_function() finds an IPMODIFY conflict (since kprobe_ftrace_ops has this flag set) and returns an error. Such a conflict is possible since livepatches also set the IPMODIFY flag for their ftrace_ops. arm_all_kprobes() keeps its current behavior and attempts to arm all kprobes. It returns the last encountered error and gives a warning if not all probes could be armed. This patch is based on Petr Mladek's original patchset (patches 2 and 3) back in 2015, which improved kprobes error handling, found here: https://lkml.org/lkml/2015/2/26/452 However, further work on this had been paused since then and the patches were not upstreamed. Based-on-patches-by: Petr Mladek <pmladek@suse.com> Signed-off-by: Jessica Yu <jeyu@kernel.org> Acked-by: Masami Hiramatsu <mhiramat@kernel.org> Cc: Ananth N Mavinakayanahalli <ananth@linux.vnet.ibm.com> Cc: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com> Cc: David S . Miller <davem@davemloft.net> Cc: Jiri Kosina <jikos@kernel.org> Cc: Joe Lawrence <joe.lawrence@redhat.com> Cc: Josh Poimboeuf <jpoimboe@redhat.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Miroslav Benes <mbenes@suse.cz> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Petr Mladek <pmladek@suse.com> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: live-patching@vger.kernel.org Link: http://lkml.kernel.org/r/20180109235124.30886-2-jeyu@kernel.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--kernel/kprobes.c100
1 files changed, 75 insertions, 25 deletions
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index da2ccf142358..2d988141ab85 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -978,18 +978,36 @@ static int prepare_kprobe(struct kprobe *p)
978} 978}
979 979
980/* Caller must lock kprobe_mutex */ 980/* Caller must lock kprobe_mutex */
981static void arm_kprobe_ftrace(struct kprobe *p) 981static int arm_kprobe_ftrace(struct kprobe *p)
982{ 982{
983 int ret; 983 int ret = 0;
984 984
985 ret = ftrace_set_filter_ip(&kprobe_ftrace_ops, 985 ret = ftrace_set_filter_ip(&kprobe_ftrace_ops,
986 (unsigned long)p->addr, 0, 0); 986 (unsigned long)p->addr, 0, 0);
987 WARN(ret < 0, "Failed to arm kprobe-ftrace at %p (%d)\n", p->addr, ret); 987 if (ret) {
988 kprobe_ftrace_enabled++; 988 pr_debug("Failed to arm kprobe-ftrace at %p (%d)\n", p->addr, ret);
989 if (kprobe_ftrace_enabled == 1) { 989 return ret;
990 }
991
992 if (kprobe_ftrace_enabled == 0) {
990 ret = register_ftrace_function(&kprobe_ftrace_ops); 993 ret = register_ftrace_function(&kprobe_ftrace_ops);
991 WARN(ret < 0, "Failed to init kprobe-ftrace (%d)\n", ret); 994 if (ret) {
995 pr_debug("Failed to init kprobe-ftrace (%d)\n", ret);
996 goto err_ftrace;
997 }
992 } 998 }
999
1000 kprobe_ftrace_enabled++;
1001 return ret;
1002
1003err_ftrace:
1004 /*
1005 * Note: Since kprobe_ftrace_ops has IPMODIFY set, and ftrace requires a
1006 * non-empty filter_hash for IPMODIFY ops, we're safe from an accidental
1007 * empty filter_hash which would undesirably trace all functions.
1008 */
1009 ftrace_set_filter_ip(&kprobe_ftrace_ops, (unsigned long)p->addr, 1, 0);
1010 return ret;
993} 1011}
994 1012
995/* Caller must lock kprobe_mutex */ 1013/* Caller must lock kprobe_mutex */
@@ -1008,22 +1026,23 @@ static void disarm_kprobe_ftrace(struct kprobe *p)
1008} 1026}
1009#else /* !CONFIG_KPROBES_ON_FTRACE */ 1027#else /* !CONFIG_KPROBES_ON_FTRACE */
1010#define prepare_kprobe(p) arch_prepare_kprobe(p) 1028#define prepare_kprobe(p) arch_prepare_kprobe(p)
1011#define arm_kprobe_ftrace(p) do {} while (0) 1029#define arm_kprobe_ftrace(p) (-ENODEV)
1012#define disarm_kprobe_ftrace(p) do {} while (0) 1030#define disarm_kprobe_ftrace(p) do {} while (0)
1013#endif 1031#endif
1014 1032
1015/* Arm a kprobe with text_mutex */ 1033/* Arm a kprobe with text_mutex */
1016static void arm_kprobe(struct kprobe *kp) 1034static int arm_kprobe(struct kprobe *kp)
1017{ 1035{
1018 if (unlikely(kprobe_ftrace(kp))) { 1036 if (unlikely(kprobe_ftrace(kp)))
1019 arm_kprobe_ftrace(kp); 1037 return arm_kprobe_ftrace(kp);
1020 return; 1038
1021 }
1022 cpus_read_lock(); 1039 cpus_read_lock();
1023 mutex_lock(&text_mutex); 1040 mutex_lock(&text_mutex);
1024 __arm_kprobe(kp); 1041 __arm_kprobe(kp);
1025 mutex_unlock(&text_mutex); 1042 mutex_unlock(&text_mutex);
1026 cpus_read_unlock(); 1043 cpus_read_unlock();
1044
1045 return 0;
1027} 1046}
1028 1047
1029/* Disarm a kprobe with text_mutex */ 1048/* Disarm a kprobe with text_mutex */
@@ -1362,9 +1381,15 @@ out:
1362 1381
1363 if (ret == 0 && kprobe_disabled(ap) && !kprobe_disabled(p)) { 1382 if (ret == 0 && kprobe_disabled(ap) && !kprobe_disabled(p)) {
1364 ap->flags &= ~KPROBE_FLAG_DISABLED; 1383 ap->flags &= ~KPROBE_FLAG_DISABLED;
1365 if (!kprobes_all_disarmed) 1384 if (!kprobes_all_disarmed) {
1366 /* Arm the breakpoint again. */ 1385 /* Arm the breakpoint again. */
1367 arm_kprobe(ap); 1386 ret = arm_kprobe(ap);
1387 if (ret) {
1388 ap->flags |= KPROBE_FLAG_DISABLED;
1389 list_del_rcu(&p->list);
1390 synchronize_sched();
1391 }
1392 }
1368 } 1393 }
1369 return ret; 1394 return ret;
1370} 1395}
@@ -1573,8 +1598,14 @@ int register_kprobe(struct kprobe *p)
1573 hlist_add_head_rcu(&p->hlist, 1598 hlist_add_head_rcu(&p->hlist,
1574 &kprobe_table[hash_ptr(p->addr, KPROBE_HASH_BITS)]); 1599 &kprobe_table[hash_ptr(p->addr, KPROBE_HASH_BITS)]);
1575 1600
1576 if (!kprobes_all_disarmed && !kprobe_disabled(p)) 1601 if (!kprobes_all_disarmed && !kprobe_disabled(p)) {
1577 arm_kprobe(p); 1602 ret = arm_kprobe(p);
1603 if (ret) {
1604 hlist_del_rcu(&p->hlist);
1605 synchronize_sched();
1606 goto out;
1607 }
1608 }
1578 1609
1579 /* Try to optimize kprobe */ 1610 /* Try to optimize kprobe */
1580 try_to_optimize_kprobe(p); 1611 try_to_optimize_kprobe(p);
@@ -2116,7 +2147,9 @@ int enable_kprobe(struct kprobe *kp)
2116 2147
2117 if (!kprobes_all_disarmed && kprobe_disabled(p)) { 2148 if (!kprobes_all_disarmed && kprobe_disabled(p)) {
2118 p->flags &= ~KPROBE_FLAG_DISABLED; 2149 p->flags &= ~KPROBE_FLAG_DISABLED;
2119 arm_kprobe(p); 2150 ret = arm_kprobe(p);
2151 if (ret)
2152 p->flags |= KPROBE_FLAG_DISABLED;
2120 } 2153 }
2121out: 2154out:
2122 mutex_unlock(&kprobe_mutex); 2155 mutex_unlock(&kprobe_mutex);
@@ -2407,11 +2440,12 @@ static const struct file_operations debugfs_kprobe_blacklist_ops = {
2407 .release = seq_release, 2440 .release = seq_release,
2408}; 2441};
2409 2442
2410static void arm_all_kprobes(void) 2443static int arm_all_kprobes(void)
2411{ 2444{
2412 struct hlist_head *head; 2445 struct hlist_head *head;
2413 struct kprobe *p; 2446 struct kprobe *p;
2414 unsigned int i; 2447 unsigned int i, total = 0, errors = 0;
2448 int err, ret = 0;
2415 2449
2416 mutex_lock(&kprobe_mutex); 2450 mutex_lock(&kprobe_mutex);
2417 2451
@@ -2428,16 +2462,28 @@ static void arm_all_kprobes(void)
2428 /* Arming kprobes doesn't optimize kprobe itself */ 2462 /* Arming kprobes doesn't optimize kprobe itself */
2429 for (i = 0; i < KPROBE_TABLE_SIZE; i++) { 2463 for (i = 0; i < KPROBE_TABLE_SIZE; i++) {
2430 head = &kprobe_table[i]; 2464 head = &kprobe_table[i];
2431 hlist_for_each_entry_rcu(p, head, hlist) 2465 /* Arm all kprobes on a best-effort basis */
2432 if (!kprobe_disabled(p)) 2466 hlist_for_each_entry_rcu(p, head, hlist) {
2433 arm_kprobe(p); 2467 if (!kprobe_disabled(p)) {
2468 err = arm_kprobe(p);
2469 if (err) {
2470 errors++;
2471 ret = err;
2472 }
2473 total++;
2474 }
2475 }
2434 } 2476 }
2435 2477
2436 printk(KERN_INFO "Kprobes globally enabled\n"); 2478 if (errors)
2479 pr_warn("Kprobes globally enabled, but failed to arm %d out of %d probes\n",
2480 errors, total);
2481 else
2482 pr_info("Kprobes globally enabled\n");
2437 2483
2438already_enabled: 2484already_enabled:
2439 mutex_unlock(&kprobe_mutex); 2485 mutex_unlock(&kprobe_mutex);
2440 return; 2486 return ret;
2441} 2487}
2442 2488
2443static void disarm_all_kprobes(void) 2489static void disarm_all_kprobes(void)
@@ -2494,6 +2540,7 @@ static ssize_t write_enabled_file_bool(struct file *file,
2494{ 2540{
2495 char buf[32]; 2541 char buf[32];
2496 size_t buf_size; 2542 size_t buf_size;
2543 int ret = 0;
2497 2544
2498 buf_size = min(count, (sizeof(buf)-1)); 2545 buf_size = min(count, (sizeof(buf)-1));
2499 if (copy_from_user(buf, user_buf, buf_size)) 2546 if (copy_from_user(buf, user_buf, buf_size))
@@ -2504,7 +2551,7 @@ static ssize_t write_enabled_file_bool(struct file *file,
2504 case 'y': 2551 case 'y':
2505 case 'Y': 2552 case 'Y':
2506 case '1': 2553 case '1':
2507 arm_all_kprobes(); 2554 ret = arm_all_kprobes();
2508 break; 2555 break;
2509 case 'n': 2556 case 'n':
2510 case 'N': 2557 case 'N':
@@ -2515,6 +2562,9 @@ static ssize_t write_enabled_file_bool(struct file *file,
2515 return -EINVAL; 2562 return -EINVAL;
2516 } 2563 }
2517 2564
2565 if (ret)
2566 return ret;
2567
2518 return count; 2568 return count;
2519} 2569}
2520 2570