mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 17:47:41 +02:00
Merge branch 'bpf-lpm_trie-allow-sleepable-bpf-programs-to-use-lpm-tries'
Vlad Poenaru says:
====================
bpf, lpm_trie: Allow sleepable BPF programs to use LPM tries
trie_lookup_elem() annotates its rcu_dereference_check() walks with only
rcu_read_lock_bh_held(), so a sleepable BPF program that touches an LPM
trie (e.g. a sleepable LSM hook calling bpf_map_lookup_elem()) trips a
"suspicious RCU usage" lockdep splat on debug kernels: it holds only
rcu_read_lock_trace(), which that annotation does not accept.
Patch 1 relaxes the rcu_dereference annotations in the trie walks so they
no longer trip lockdep from the Tasks Trace context, including the
trie_update_elem()/trie_delete_elem() writer walks (protected by
trie->lock). Patch 2 adds BPF_MAP_TYPE_LPM_TRIE to the verifier's
sleepable map whitelist so sleepable programs can reference an LPM trie
directly, not just as the inner map of a map-of-maps. LPM trie nodes are
reclaimed via bpf_mem_cache_free_rcu(), which chains a regular RCU grace
period into a Tasks Trace grace period before freeing -- the same
discipline BPF_MAP_TYPE_HASH relies on for sleepable access.
Changes since v1:
- Split into a 2-patch series.
- Patch 1 now also converts the trie_update_elem()/trie_delete_elem()
walks from rcu_dereference() to rcu_dereference_protected(*p, 1),
addressing review feedback that v1 only fixed the lookup path and left
the same splat on the writer paths.
- New patch 2 adds the verifier whitelist entry so the fix is actually
reachable for directly-referenced LPM tries.
- Retitled v1 ("Allow lookups from sleepable BPF programs").
v1: https://lore.kernel.org/all/20260529174233.2954240-1-vlad.wing@gmail.com/
====================
Link: https://patch.msgid.link/20260609135558.193287-1-vlad.wing@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
commit
c15261b1bb
|
|
@ -246,7 +246,7 @@ static void *trie_lookup_elem(struct bpf_map *map, void *_key)
|
|||
|
||||
/* Start walking the trie from the root node ... */
|
||||
|
||||
for (node = rcu_dereference_check(trie->root, rcu_read_lock_bh_held());
|
||||
for (node = rcu_dereference_check(trie->root, bpf_rcu_lock_held());
|
||||
node;) {
|
||||
unsigned int next_bit;
|
||||
size_t matchlen;
|
||||
|
|
@ -280,7 +280,7 @@ static void *trie_lookup_elem(struct bpf_map *map, void *_key)
|
|||
*/
|
||||
next_bit = extract_bit(key->data, node->prefixlen);
|
||||
node = rcu_dereference_check(node->child[next_bit],
|
||||
rcu_read_lock_bh_held());
|
||||
bpf_rcu_lock_held());
|
||||
}
|
||||
|
||||
if (!found)
|
||||
|
|
@ -359,7 +359,7 @@ static long trie_update_elem(struct bpf_map *map,
|
|||
*/
|
||||
slot = &trie->root;
|
||||
|
||||
while ((node = rcu_dereference(*slot))) {
|
||||
while ((node = rcu_dereference_protected(*slot, 1))) {
|
||||
matchlen = longest_prefix_match(trie, node, key);
|
||||
|
||||
if (node->prefixlen != matchlen ||
|
||||
|
|
@ -482,7 +482,7 @@ static long trie_delete_elem(struct bpf_map *map, void *_key)
|
|||
trim = &trie->root;
|
||||
trim2 = trim;
|
||||
parent = NULL;
|
||||
while ((node = rcu_dereference(*trim))) {
|
||||
while ((node = rcu_dereference_protected(*trim, 1))) {
|
||||
matchlen = longest_prefix_match(trie, node, key);
|
||||
|
||||
if (node->prefixlen != matchlen ||
|
||||
|
|
|
|||
|
|
@ -17737,6 +17737,7 @@ static int check_map_prog_compatibility(struct bpf_verifier_env *env,
|
|||
case BPF_MAP_TYPE_PERCPU_HASH:
|
||||
case BPF_MAP_TYPE_PERCPU_ARRAY:
|
||||
case BPF_MAP_TYPE_LRU_PERCPU_HASH:
|
||||
case BPF_MAP_TYPE_LPM_TRIE:
|
||||
case BPF_MAP_TYPE_ARRAY_OF_MAPS:
|
||||
case BPF_MAP_TYPE_HASH_OF_MAPS:
|
||||
case BPF_MAP_TYPE_RINGBUF:
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user