bpf: Make sure bpf_disable_instrumentation() is safe vs preemption.
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>
Sat, 27 Nov 2021 16:32:00 +0000 (17:32 +0100)
committerDaniel Borkmann <daniel@iogearbox.net>
Tue, 30 Nov 2021 14:40:49 +0000 (15:40 +0100)
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
include/linux/bpf.h
include/linux/filter.h

index 84ff6ef4946276af76fbfe88b1b7068bc9b4c502..755f38e893be1b141e932403fc12d6ff93086795 100644 (file)
@@ -1353,28 +1353,16 @@ extern struct mutex bpf_stats_enabled_mutex;
  * kprobes, tracepoints) to prevent deadlocks on map operations as any of
  * these events can happen inside a region which holds a map bucket lock
  * and can deadlock on it.
- *
- * Use the preemption safe inc/dec variants on RT because migrate disable
- * is preemptible on RT and preemption in the middle of the RMW operation
- * might lead to inconsistent state. Use the raw variants for non RT
- * kernels as migrate_disable() maps to preempt_disable() so the slightly
- * more expensive save operation can be avoided.
  */
 static inline void bpf_disable_instrumentation(void)
 {
        migrate_disable();
-       if (IS_ENABLED(CONFIG_PREEMPT_RT))
-               this_cpu_inc(bpf_prog_active);
-       else
-               __this_cpu_inc(bpf_prog_active);
+       this_cpu_inc(bpf_prog_active);
 }
 
 static inline void bpf_enable_instrumentation(void)
 {
-       if (IS_ENABLED(CONFIG_PREEMPT_RT))
-               this_cpu_dec(bpf_prog_active);
-       else
-               __this_cpu_dec(bpf_prog_active);
+       this_cpu_dec(bpf_prog_active);
        migrate_enable();
 }
 
index 24b7ed2677afd26b0ffd1ce80f34469adc7129b0..534f678ca50fa39f886c03f70207f13d0e1adb58 100644 (file)
@@ -640,9 +640,6 @@ static __always_inline u32 bpf_prog_run(const struct bpf_prog *prog, const void
  * This uses migrate_disable/enable() explicitly to document that the
  * invocation of a BPF program does not require reentrancy protection
  * against a BPF program which is invoked from a preempting task.
- *
- * For non RT enabled kernels migrate_disable/enable() maps to
- * preempt_disable/enable(), i.e. it disables also preemption.
  */
 static inline u32 bpf_prog_run_pin_on_cpu(const struct bpf_prog *prog,
                                          const void *ctx)