diff options
author | Hou Tao <houtao1@huawei.com> | 2025-01-17 18:18:14 +0800 |
---|---|---|
committer | Alexei Starovoitov <ast@kernel.org> | 2025-01-20 09:09:01 -0800 |
commit | 47363f1553e69b8c2e3269f9883799a4ea898cd4 (patch) | |
tree | d99b35e82c4ba442ed37549d2c2158a010146222 | |
parent | 588c6ead325aecc9894c9925cf1f771b77437bee (diff) |
bpf: Free element after unlock in __htab_map_lookup_and_delete_elem()
The freeing of special fields in map value may acquire a spin-lock
(e.g., the freeing of bpf_timer), however, the lookup_and_delete_elem
procedure has already held a raw-spin-lock, which violates the lockdep
rule.
The running context of __htab_map_lookup_and_delete_elem() has already
disabled the migration. Therefore, it is OK to invoke free_htab_elem()
after unlocking the bucket lock.
Fix the potential problem by freeing element after unlocking bucket lock
in __htab_map_lookup_and_delete_elem().
Signed-off-by: Hou Tao <houtao1@huawei.com>
Link: https://lore.kernel.org/r/20250117101816.2101857-4-houtao@huaweicloud.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
-rw-r--r-- | kernel/bpf/hashtab.c | 10 |
1 files changed, 6 insertions, 4 deletions
diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c index 6545ef40e128..4a9eeb7aef85 100644 --- a/kernel/bpf/hashtab.c +++ b/kernel/bpf/hashtab.c @@ -1663,14 +1663,16 @@ static int __htab_map_lookup_and_delete_elem(struct bpf_map *map, void *key, check_and_init_map_value(map, value); } hlist_nulls_del_rcu(&l->hash_node); - if (!is_lru_map) - free_htab_elem(htab, l); out_unlock: htab_unlock_bucket(htab, b, hash, bflags); - if (is_lru_map && l) - htab_lru_push_free(htab, l); + if (l) { + if (is_lru_map) + htab_lru_push_free(htab, l); + else + free_htab_elem(htab, l); + } return ret; } |