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

bpf: Make sure bpf_disable_instrumentation() is safe vs preemption.

The initial implementation of migrate_disable() for mainline was a
wrapper around preempt_disable(). RT kernels substituted this with a
real migrate disable implementation.

Later on mainline gained true migrate disable support, but neither
documentation nor affected code were updated.

Remove stale comments claiming that migrate_disable() is PREEMPT_RT only.

Don't use __this_cpu_inc() in the !PREEMPT_RT path because preemption is
not disabled and the RMW operation can be preempted.

Fixes: 74d862b682f51 ("sched: Make migrate_disable/enable() independent of RT")
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Link: https://lore.kernel.org/bpf/20211127163200.10466-3-bigeasy@linutronix.de

authored by

Sebastian Andrzej Siewior and committed by
Daniel Borkmann
79364031 6a631c04

+2 -17
+2 -14
include/linux/bpf.h
··· 1353 1353 * kprobes, tracepoints) to prevent deadlocks on map operations as any of 1354 1354 * these events can happen inside a region which holds a map bucket lock 1355 1355 * and can deadlock on it. 1356 - * 1357 - * Use the preemption safe inc/dec variants on RT because migrate disable 1358 - * is preemptible on RT and preemption in the middle of the RMW operation 1359 - * might lead to inconsistent state. Use the raw variants for non RT 1360 - * kernels as migrate_disable() maps to preempt_disable() so the slightly 1361 - * more expensive save operation can be avoided. 1362 1356 */ 1363 1357 static inline void bpf_disable_instrumentation(void) 1364 1358 { 1365 1359 migrate_disable(); 1366 - if (IS_ENABLED(CONFIG_PREEMPT_RT)) 1367 - this_cpu_inc(bpf_prog_active); 1368 - else 1369 - __this_cpu_inc(bpf_prog_active); 1360 + this_cpu_inc(bpf_prog_active); 1370 1361 } 1371 1362 1372 1363 static inline void bpf_enable_instrumentation(void) 1373 1364 { 1374 - if (IS_ENABLED(CONFIG_PREEMPT_RT)) 1375 - this_cpu_dec(bpf_prog_active); 1376 - else 1377 - __this_cpu_dec(bpf_prog_active); 1365 + this_cpu_dec(bpf_prog_active); 1378 1366 migrate_enable(); 1379 1367 } 1380 1368
-3
include/linux/filter.h
··· 640 640 * This uses migrate_disable/enable() explicitly to document that the 641 641 * invocation of a BPF program does not require reentrancy protection 642 642 * against a BPF program which is invoked from a preempting task. 643 - * 644 - * For non RT enabled kernels migrate_disable/enable() maps to 645 - * preempt_disable/enable(), i.e. it disables also preemption. 646 643 */ 647 644 static inline u32 bpf_prog_run_pin_on_cpu(const struct bpf_prog *prog, 648 645 const void *ctx)