summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorJosef Bacik <josef@toxicpanda.com>2026-10-17 16:37:26 +0000
committerAlexei Starovoitov <ast@kernel.org>2026-10-17 22:01:14 +0000
commit3e6d7522af2cd1b8bf135ee7df6ca962986f44d6 (patch)
treef667ebed8ccada167347f05d433e3d723b1dc9b7 /include
parent927c9c985f3ef4d30c086884b7e0ecb933f742ef (diff)
bpf: Check the maps that sleepable callbacks use
Sleepable programs can only use the kinds of map that do without an RCU read side critical section. check_map_prog_compatibility() sees to that when a map is bound to the program, and asks whether the program is sleepable. That misses the bpf_wq or bpf_task_work callback of a program that is not, which runs sleepable all the same, and it misses an inner map, which is not bound. The bpf_wq callback of a tc program that looks a key up in a sockhash gets as far as WARNING: net/core/sock_map.c:903 at __sock_hash_lookup_elem+0x18f/0x1e0 Ask the same question for the map that is handed to a helper in sleepable context, unless the RCU read lock is held: by bpf_rcu_read_lock(), or by the helper that runs the callback, as bpf_for_each_map_elem() does for a hash map. Programs that take the lock go on working. Disabled preemption or interrupts are not enough, since the maps ask for rcu_read_lock_held(). The other parts of the program may use such a map as before. A global function that is called with preemption or interrupts disabled is verified for the non-sleepable context, in which nothing is known of all that. Verify it for a context of its own: not sleepable, and without the RCU read lock. It differs in what maps can be used, and in nothing else. What is refused from now on runs into the warning above, or uses what the map frees behind a plain RCU grace period: an entry of a devmap, of a perf event array or of a cgroup array. A bloom filter does without RCU. Add it to the list, so that callbacks which use one go on loading. As a side effect sleepable programs can use bloom filters as well. A pointer to the value of a devmap which a program keeps beyond bpf_rcu_read_unlock() is not dealt with here. Fixes: 638e4b825d52 ("bpf: Allows per-cpu maps and map-in-map in sleepable programs") Fixes: 8e83da9732d9 ("bpf: add bpf_wq_start") Signed-off-by: Josef Bacik <josef@toxicpanda.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Link: https://patch.msgid.link/20261017163745.3341787-25-alexei.starovoitov@gmail.com
Diffstat (limited to 'include')
-rw-r--r--include/linux/bpf.h14
-rw-r--r--include/linux/bpf_verifier.h2
2 files changed, 13 insertions, 3 deletions
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index db56d5d07462..1823ca3a1d5e 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -1742,12 +1742,20 @@ static inline void bpf_trampoline_multi_detach(struct bpf_prog *prog,
static inline void bpf_trampoline_set_flags(struct bpf_trampoline *tr, u32 flags) {}
#endif
+/* The contexts that a global function is called in, and is verified for. */
+enum bpf_func_context {
+ BPF_FUNC_CTX_NON_SLEEPABLE,
+ BPF_FUNC_CTX_SLEEPABLE,
+ /* Sleepable code has disabled preemption or interrupts: no RCU read lock. */
+ BPF_FUNC_CTX_NO_RCU_LOCK,
+ BPF_FUNC_CTX_CNT,
+};
+
struct bpf_func_info_aux {
u16 linkage;
bool unreliable;
- /* Indexed by in_sleepable. */
- bool called[2];
- bool verified[2];
+ bool called[BPF_FUNC_CTX_CNT];
+ bool verified[BPF_FUNC_CTX_CNT];
};
enum bpf_jit_poke_reason {
diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
index 816948df8fff..e420d211f423 100644
--- a/include/linux/bpf_verifier.h
+++ b/include/linux/bpf_verifier.h
@@ -1090,6 +1090,8 @@ struct bpf_verifier_env {
bool bypass_spec_v1;
bool bypass_spec_v4;
bool seen_direct_write;
+ /* a global function is verified for BPF_FUNC_CTX_NO_RCU_LOCK */
+ bool no_rcu_read_lock;
bool seen_exception;
bool signature;
u32 insn_aux_data_len;