Skip to content

Commit 2cd14df

Browse files
committed
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
2 parents 6093a68 + 9cf9aa7 commit 2cd14df

File tree

4 files changed

+28
-14
lines changed

4 files changed

+28
-14
lines changed

kernel/trace/trace_fprobe.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -522,13 +522,14 @@ static int fentry_dispatcher(struct fprobe *fp, unsigned long entry_ip,
522522
void *entry_data)
523523
{
524524
struct trace_fprobe *tf = container_of(fp, struct trace_fprobe, fp);
525+
unsigned int flags = trace_probe_load_flag(&tf->tp);
525526
int ret = 0;
526527

527-
if (trace_probe_test_flag(&tf->tp, TP_FLAG_TRACE))
528+
if (flags & TP_FLAG_TRACE)
528529
fentry_trace_func(tf, entry_ip, fregs);
529530

530531
#ifdef CONFIG_PERF_EVENTS
531-
if (trace_probe_test_flag(&tf->tp, TP_FLAG_PROFILE))
532+
if (flags & TP_FLAG_PROFILE)
532533
ret = fentry_perf_func(tf, entry_ip, fregs);
533534
#endif
534535
return ret;
@@ -540,11 +541,12 @@ static void fexit_dispatcher(struct fprobe *fp, unsigned long entry_ip,
540541
void *entry_data)
541542
{
542543
struct trace_fprobe *tf = container_of(fp, struct trace_fprobe, fp);
544+
unsigned int flags = trace_probe_load_flag(&tf->tp);
543545

544-
if (trace_probe_test_flag(&tf->tp, TP_FLAG_TRACE))
546+
if (flags & TP_FLAG_TRACE)
545547
fexit_trace_func(tf, entry_ip, ret_ip, fregs, entry_data);
546548
#ifdef CONFIG_PERF_EVENTS
547-
if (trace_probe_test_flag(&tf->tp, TP_FLAG_PROFILE))
549+
if (flags & TP_FLAG_PROFILE)
548550
fexit_perf_func(tf, entry_ip, ret_ip, fregs, entry_data);
549551
#endif
550552
}

kernel/trace/trace_kprobe.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1815,14 +1815,15 @@ static int kprobe_register(struct trace_event_call *event,
18151815
static int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs)
18161816
{
18171817
struct trace_kprobe *tk = container_of(kp, struct trace_kprobe, rp.kp);
1818+
unsigned int flags = trace_probe_load_flag(&tk->tp);
18181819
int ret = 0;
18191820

18201821
raw_cpu_inc(*tk->nhit);
18211822

1822-
if (trace_probe_test_flag(&tk->tp, TP_FLAG_TRACE))
1823+
if (flags & TP_FLAG_TRACE)
18231824
kprobe_trace_func(tk, regs);
18241825
#ifdef CONFIG_PERF_EVENTS
1825-
if (trace_probe_test_flag(&tk->tp, TP_FLAG_PROFILE))
1826+
if (flags & TP_FLAG_PROFILE)
18261827
ret = kprobe_perf_func(tk, regs);
18271828
#endif
18281829
return ret;
@@ -1834,6 +1835,7 @@ kretprobe_dispatcher(struct kretprobe_instance *ri, struct pt_regs *regs)
18341835
{
18351836
struct kretprobe *rp = get_kretprobe(ri);
18361837
struct trace_kprobe *tk;
1838+
unsigned int flags;
18371839

18381840
/*
18391841
* There is a small chance that get_kretprobe(ri) returns NULL when
@@ -1846,10 +1848,11 @@ kretprobe_dispatcher(struct kretprobe_instance *ri, struct pt_regs *regs)
18461848
tk = container_of(rp, struct trace_kprobe, rp);
18471849
raw_cpu_inc(*tk->nhit);
18481850

1849-
if (trace_probe_test_flag(&tk->tp, TP_FLAG_TRACE))
1851+
flags = trace_probe_load_flag(&tk->tp);
1852+
if (flags & TP_FLAG_TRACE)
18501853
kretprobe_trace_func(tk, ri, regs);
18511854
#ifdef CONFIG_PERF_EVENTS
1852-
if (trace_probe_test_flag(&tk->tp, TP_FLAG_PROFILE))
1855+
if (flags & TP_FLAG_PROFILE)
18531856
kretprobe_perf_func(tk, ri, regs);
18541857
#endif
18551858
return 0; /* We don't tweak kernel, so just return 0 */

kernel/trace/trace_probe.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -271,16 +271,21 @@ struct event_file_link {
271271
struct list_head list;
272272
};
273273

274+
static inline unsigned int trace_probe_load_flag(struct trace_probe *tp)
275+
{
276+
return smp_load_acquire(&tp->event->flags);
277+
}
278+
274279
static inline bool trace_probe_test_flag(struct trace_probe *tp,
275280
unsigned int flag)
276281
{
277-
return !!(tp->event->flags & flag);
282+
return !!(trace_probe_load_flag(tp) & flag);
278283
}
279284

280285
static inline void trace_probe_set_flag(struct trace_probe *tp,
281286
unsigned int flag)
282287
{
283-
tp->event->flags |= flag;
288+
smp_store_release(&tp->event->flags, tp->event->flags | flag);
284289
}
285290

286291
static inline void trace_probe_clear_flag(struct trace_probe *tp,

kernel/trace/trace_uprobe.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1547,6 +1547,7 @@ static int uprobe_dispatcher(struct uprobe_consumer *con, struct pt_regs *regs,
15471547
struct trace_uprobe *tu;
15481548
struct uprobe_dispatch_data udd;
15491549
struct uprobe_cpu_buffer *ucb = NULL;
1550+
unsigned int flags;
15501551
int ret = 0;
15511552

15521553
tu = container_of(con, struct trace_uprobe, consumer);
@@ -1561,11 +1562,12 @@ static int uprobe_dispatcher(struct uprobe_consumer *con, struct pt_regs *regs,
15611562
if (WARN_ON_ONCE(!uprobe_cpu_buffer))
15621563
return 0;
15631564

1564-
if (trace_probe_test_flag(&tu->tp, TP_FLAG_TRACE))
1565+
flags = trace_probe_load_flag(&tu->tp);
1566+
if (flags & TP_FLAG_TRACE)
15651567
ret |= uprobe_trace_func(tu, regs, &ucb);
15661568

15671569
#ifdef CONFIG_PERF_EVENTS
1568-
if (trace_probe_test_flag(&tu->tp, TP_FLAG_PROFILE))
1570+
if (flags & TP_FLAG_PROFILE)
15691571
ret |= uprobe_perf_func(tu, regs, &ucb);
15701572
#endif
15711573
uprobe_buffer_put(ucb);
@@ -1579,6 +1581,7 @@ static int uretprobe_dispatcher(struct uprobe_consumer *con,
15791581
struct trace_uprobe *tu;
15801582
struct uprobe_dispatch_data udd;
15811583
struct uprobe_cpu_buffer *ucb = NULL;
1584+
unsigned int flags;
15821585

15831586
tu = container_of(con, struct trace_uprobe, consumer);
15841587

@@ -1590,11 +1593,12 @@ static int uretprobe_dispatcher(struct uprobe_consumer *con,
15901593
if (WARN_ON_ONCE(!uprobe_cpu_buffer))
15911594
return 0;
15921595

1593-
if (trace_probe_test_flag(&tu->tp, TP_FLAG_TRACE))
1596+
flags = trace_probe_load_flag(&tu->tp);
1597+
if (flags & TP_FLAG_TRACE)
15941598
uretprobe_trace_func(tu, func, regs, &ucb);
15951599

15961600
#ifdef CONFIG_PERF_EVENTS
1597-
if (trace_probe_test_flag(&tu->tp, TP_FLAG_PROFILE))
1601+
if (flags & TP_FLAG_PROFILE)
15981602
uretprobe_perf_func(tu, func, regs, &ucb);
15991603
#endif
16001604
uprobe_buffer_put(ucb);

0 commit comments

Comments
 (0)