Skip to content

Commit 9511b84

Browse files
Tao ChenKernel Patches Daemon
authored andcommitted
bpf: Add preempt_disable to protect get_perf_callchain
As Alexei suggested, the return value from get_perf_callchain() may be reused if another task preempts and requests the stack after BPF program switched to migrate disable. Reported-by: Alexei Starovoitov <[email protected]> Signed-off-by: Tao Chen <[email protected]>
1 parent a98c373 commit 9511b84

File tree

1 file changed

+5
-9
lines changed

1 file changed

+5
-9
lines changed

kernel/bpf/stackmap.c

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -314,8 +314,10 @@ BPF_CALL_3(bpf_get_stackid, struct pt_regs *, regs, struct bpf_map *, map,
314314
if (max_depth > sysctl_perf_event_max_stack)
315315
max_depth = sysctl_perf_event_max_stack;
316316

317+
preempt_disable();
317318
trace = get_perf_callchain(regs, 0, kernel, user, max_depth,
318319
false, false);
320+
preempt_enable();
319321

320322
if (unlikely(!trace))
321323
/* couldn't fetch the stack trace */
@@ -443,9 +445,7 @@ static long __bpf_get_stack(struct pt_regs *regs, struct task_struct *task,
443445
if (sysctl_perf_event_max_stack < max_depth)
444446
max_depth = sysctl_perf_event_max_stack;
445447

446-
if (may_fault)
447-
rcu_read_lock(); /* need RCU for perf's callchain below */
448-
448+
preempt_disable();
449449
if (trace_in)
450450
trace = trace_in;
451451
else if (kernel && task)
@@ -455,8 +455,7 @@ static long __bpf_get_stack(struct pt_regs *regs, struct task_struct *task,
455455
crosstask, false);
456456

457457
if (unlikely(!trace) || trace->nr < skip) {
458-
if (may_fault)
459-
rcu_read_unlock();
458+
preempt_enable();
460459
goto err_fault;
461460
}
462461

@@ -474,10 +473,7 @@ static long __bpf_get_stack(struct pt_regs *regs, struct task_struct *task,
474473
} else {
475474
memcpy(buf, ips, copy_len);
476475
}
477-
478-
/* trace/ips should not be dereferenced after this point */
479-
if (may_fault)
480-
rcu_read_unlock();
476+
preempt_enable();
481477

482478
if (user_build_id)
483479
stack_map_get_build_id_offset(buf, trace_nr, user, may_fault);

0 commit comments

Comments
 (0)