Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'trace-fixes-v3.16-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace

Pull tracing fixes from Steven Rostedt:
"Oleg Nesterov found and fixed a bug in the perf/ftrace/uprobes code
where running:

# perf probe -x /lib/libc.so.6 syscall
# echo 1 >> /sys/kernel/debug/tracing/events/probe_libc/enable
# perf record -e probe_libc:syscall whatever

kills the uprobe. Along the way he found some other minor bugs and
clean ups that he fixed up making it a total of 4 patches.

Doing unrelated work, I found that the reading of the ftrace trace
file disables all function tracer callbacks. This was fine when
ftrace was the only user, but now that it's used by perf and kprobes,
this is a bug where reading trace can disable kprobes and perf. A
very unexpected side effect and should be fixed"

* tag 'trace-fixes-v3.16-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace:
tracing: Remove ftrace_stop/start() from reading the trace file
tracing/uprobes: Fix the usage of uprobe_buffer_enable() in probe_event_enable()
tracing/uprobes: Kill the bogus UPROBE_HANDLER_REMOVE code in uprobe_dispatcher()
uprobes: Change unregister/apply to WARN() if uprobe/consumer is gone
tracing/uprobes: Revert "Support mix of ftrace and perf"

+30 -24
+3 -3
kernel/events/uprobes.c
··· 846 846 { 847 847 int err; 848 848 849 - if (!consumer_del(uprobe, uc)) /* WARN? */ 849 + if (WARN_ON(!consumer_del(uprobe, uc))) 850 850 return; 851 851 852 852 err = register_for_each_vma(uprobe, NULL); ··· 927 927 int ret = -ENOENT; 928 928 929 929 uprobe = find_uprobe(inode, offset); 930 - if (!uprobe) 930 + if (WARN_ON(!uprobe)) 931 931 return ret; 932 932 933 933 down_write(&uprobe->register_rwsem); ··· 952 952 struct uprobe *uprobe; 953 953 954 954 uprobe = find_uprobe(inode, offset); 955 - if (!uprobe) 955 + if (WARN_ON(!uprobe)) 956 956 return; 957 957 958 958 down_write(&uprobe->register_rwsem);
-2
kernel/trace/trace.c
··· 1396 1396 1397 1397 arch_spin_unlock(&global_trace.max_lock); 1398 1398 1399 - ftrace_start(); 1400 1399 out: 1401 1400 raw_spin_unlock_irqrestore(&global_trace.start_lock, flags); 1402 1401 } ··· 1442 1443 struct ring_buffer *buffer; 1443 1444 unsigned long flags; 1444 1445 1445 - ftrace_stop(); 1446 1446 raw_spin_lock_irqsave(&global_trace.start_lock, flags); 1447 1447 if (global_trace.stop_count++) 1448 1448 goto out;
+27 -19
kernel/trace/trace_uprobe.c
··· 893 893 int ret; 894 894 895 895 if (file) { 896 + if (tu->tp.flags & TP_FLAG_PROFILE) 897 + return -EINTR; 898 + 896 899 link = kmalloc(sizeof(*link), GFP_KERNEL); 897 900 if (!link) 898 901 return -ENOMEM; ··· 904 901 list_add_tail_rcu(&link->list, &tu->tp.files); 905 902 906 903 tu->tp.flags |= TP_FLAG_TRACE; 907 - } else 908 - tu->tp.flags |= TP_FLAG_PROFILE; 904 + } else { 905 + if (tu->tp.flags & TP_FLAG_TRACE) 906 + return -EINTR; 909 907 910 - ret = uprobe_buffer_enable(); 911 - if (ret < 0) 912 - return ret; 908 + tu->tp.flags |= TP_FLAG_PROFILE; 909 + } 913 910 914 911 WARN_ON(!uprobe_filter_is_empty(&tu->filter)); 915 912 916 913 if (enabled) 917 914 return 0; 918 915 916 + ret = uprobe_buffer_enable(); 917 + if (ret) 918 + goto err_flags; 919 + 919 920 tu->consumer.filter = filter; 920 921 ret = uprobe_register(tu->inode, tu->offset, &tu->consumer); 921 - if (ret) { 922 - if (file) { 923 - list_del(&link->list); 924 - kfree(link); 925 - tu->tp.flags &= ~TP_FLAG_TRACE; 926 - } else 927 - tu->tp.flags &= ~TP_FLAG_PROFILE; 928 - } 922 + if (ret) 923 + goto err_buffer; 929 924 925 + return 0; 926 + 927 + err_buffer: 928 + uprobe_buffer_disable(); 929 + 930 + err_flags: 931 + if (file) { 932 + list_del(&link->list); 933 + kfree(link); 934 + tu->tp.flags &= ~TP_FLAG_TRACE; 935 + } else { 936 + tu->tp.flags &= ~TP_FLAG_PROFILE; 937 + } 930 938 return ret; 931 939 } 932 940 ··· 1214 1200 udd.bp_addr = instruction_pointer(regs); 1215 1201 1216 1202 current->utask->vaddr = (unsigned long) &udd; 1217 - 1218 - #ifdef CONFIG_PERF_EVENTS 1219 - if ((tu->tp.flags & TP_FLAG_TRACE) == 0 && 1220 - !uprobe_perf_filter(&tu->consumer, 0, current->mm)) 1221 - return UPROBE_HANDLER_REMOVE; 1222 - #endif 1223 1203 1224 1204 if (WARN_ON_ONCE(!uprobe_cpu_buffer)) 1225 1205 return 0;