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 'probes-fixes-v6.17' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace

Pull probe fix from Masami Hiramatsu:

- Fix race condition in kprobe initialization causing NULL pointer
dereference. This happens on weak memory model, which does not
correctly manage the flags access with appropriate memory barriers.
Use RELEASE-ACQUIRE to fix it.

* tag 'probes-fixes-v6.17' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace:
tracing: Fix race condition in kprobe initialization causing NULL pointer dereference

+28 -14
+6 -4
kernel/trace/trace_fprobe.c
··· 522 522 void *entry_data) 523 523 { 524 524 struct trace_fprobe *tf = container_of(fp, struct trace_fprobe, fp); 525 + unsigned int flags = trace_probe_load_flag(&tf->tp); 525 526 int ret = 0; 526 527 527 - if (trace_probe_test_flag(&tf->tp, TP_FLAG_TRACE)) 528 + if (flags & TP_FLAG_TRACE) 528 529 fentry_trace_func(tf, entry_ip, fregs); 529 530 530 531 #ifdef CONFIG_PERF_EVENTS 531 - if (trace_probe_test_flag(&tf->tp, TP_FLAG_PROFILE)) 532 + if (flags & TP_FLAG_PROFILE) 532 533 ret = fentry_perf_func(tf, entry_ip, fregs); 533 534 #endif 534 535 return ret; ··· 541 540 void *entry_data) 542 541 { 543 542 struct trace_fprobe *tf = container_of(fp, struct trace_fprobe, fp); 543 + unsigned int flags = trace_probe_load_flag(&tf->tp); 544 544 545 - if (trace_probe_test_flag(&tf->tp, TP_FLAG_TRACE)) 545 + if (flags & TP_FLAG_TRACE) 546 546 fexit_trace_func(tf, entry_ip, ret_ip, fregs, entry_data); 547 547 #ifdef CONFIG_PERF_EVENTS 548 - if (trace_probe_test_flag(&tf->tp, TP_FLAG_PROFILE)) 548 + if (flags & TP_FLAG_PROFILE) 549 549 fexit_perf_func(tf, entry_ip, ret_ip, fregs, entry_data); 550 550 #endif 551 551 }
+7 -4
kernel/trace/trace_kprobe.c
··· 1815 1815 static int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs) 1816 1816 { 1817 1817 struct trace_kprobe *tk = container_of(kp, struct trace_kprobe, rp.kp); 1818 + unsigned int flags = trace_probe_load_flag(&tk->tp); 1818 1819 int ret = 0; 1819 1820 1820 1821 raw_cpu_inc(*tk->nhit); 1821 1822 1822 - if (trace_probe_test_flag(&tk->tp, TP_FLAG_TRACE)) 1823 + if (flags & TP_FLAG_TRACE) 1823 1824 kprobe_trace_func(tk, regs); 1824 1825 #ifdef CONFIG_PERF_EVENTS 1825 - if (trace_probe_test_flag(&tk->tp, TP_FLAG_PROFILE)) 1826 + if (flags & TP_FLAG_PROFILE) 1826 1827 ret = kprobe_perf_func(tk, regs); 1827 1828 #endif 1828 1829 return ret; ··· 1835 1834 { 1836 1835 struct kretprobe *rp = get_kretprobe(ri); 1837 1836 struct trace_kprobe *tk; 1837 + unsigned int flags; 1838 1838 1839 1839 /* 1840 1840 * There is a small chance that get_kretprobe(ri) returns NULL when ··· 1848 1846 tk = container_of(rp, struct trace_kprobe, rp); 1849 1847 raw_cpu_inc(*tk->nhit); 1850 1848 1851 - if (trace_probe_test_flag(&tk->tp, TP_FLAG_TRACE)) 1849 + flags = trace_probe_load_flag(&tk->tp); 1850 + if (flags & TP_FLAG_TRACE) 1852 1851 kretprobe_trace_func(tk, ri, regs); 1853 1852 #ifdef CONFIG_PERF_EVENTS 1854 - if (trace_probe_test_flag(&tk->tp, TP_FLAG_PROFILE)) 1853 + if (flags & TP_FLAG_PROFILE) 1855 1854 kretprobe_perf_func(tk, ri, regs); 1856 1855 #endif 1857 1856 return 0; /* We don't tweak kernel, so just return 0 */
+7 -2
kernel/trace/trace_probe.h
··· 271 271 struct list_head list; 272 272 }; 273 273 274 + static inline unsigned int trace_probe_load_flag(struct trace_probe *tp) 275 + { 276 + return smp_load_acquire(&tp->event->flags); 277 + } 278 + 274 279 static inline bool trace_probe_test_flag(struct trace_probe *tp, 275 280 unsigned int flag) 276 281 { 277 - return !!(tp->event->flags & flag); 282 + return !!(trace_probe_load_flag(tp) & flag); 278 283 } 279 284 280 285 static inline void trace_probe_set_flag(struct trace_probe *tp, 281 286 unsigned int flag) 282 287 { 283 - tp->event->flags |= flag; 288 + smp_store_release(&tp->event->flags, tp->event->flags | flag); 284 289 } 285 290 286 291 static inline void trace_probe_clear_flag(struct trace_probe *tp,
+8 -4
kernel/trace/trace_uprobe.c
··· 1547 1547 struct trace_uprobe *tu; 1548 1548 struct uprobe_dispatch_data udd; 1549 1549 struct uprobe_cpu_buffer *ucb = NULL; 1550 + unsigned int flags; 1550 1551 int ret = 0; 1551 1552 1552 1553 tu = container_of(con, struct trace_uprobe, consumer); ··· 1562 1561 if (WARN_ON_ONCE(!uprobe_cpu_buffer)) 1563 1562 return 0; 1564 1563 1565 - if (trace_probe_test_flag(&tu->tp, TP_FLAG_TRACE)) 1564 + flags = trace_probe_load_flag(&tu->tp); 1565 + if (flags & TP_FLAG_TRACE) 1566 1566 ret |= uprobe_trace_func(tu, regs, &ucb); 1567 1567 1568 1568 #ifdef CONFIG_PERF_EVENTS 1569 - if (trace_probe_test_flag(&tu->tp, TP_FLAG_PROFILE)) 1569 + if (flags & TP_FLAG_PROFILE) 1570 1570 ret |= uprobe_perf_func(tu, regs, &ucb); 1571 1571 #endif 1572 1572 uprobe_buffer_put(ucb); ··· 1581 1579 struct trace_uprobe *tu; 1582 1580 struct uprobe_dispatch_data udd; 1583 1581 struct uprobe_cpu_buffer *ucb = NULL; 1582 + unsigned int flags; 1584 1583 1585 1584 tu = container_of(con, struct trace_uprobe, consumer); 1586 1585 ··· 1593 1590 if (WARN_ON_ONCE(!uprobe_cpu_buffer)) 1594 1591 return 0; 1595 1592 1596 - if (trace_probe_test_flag(&tu->tp, TP_FLAG_TRACE)) 1593 + flags = trace_probe_load_flag(&tu->tp); 1594 + if (flags & TP_FLAG_TRACE) 1597 1595 uretprobe_trace_func(tu, func, regs, &ucb); 1598 1596 1599 1597 #ifdef CONFIG_PERF_EVENTS 1600 - if (trace_probe_test_flag(&tu->tp, TP_FLAG_PROFILE)) 1598 + if (flags & TP_FLAG_PROFILE) 1601 1599 uretprobe_perf_func(tu, func, regs, &ucb); 1602 1600 #endif 1603 1601 uprobe_buffer_put(ucb);