mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-27 12:57:53 +00:00
bpf, sockmap: fix deadlocks in the sockhash and sockmap
[ Upstream commited17aa92dc
] When huang uses sched_switch tracepoint, the tracepoint does only one thing in the mounted ebpf program, which deletes the fixed elements in sockhash ([0]) It seems that elements in sockhash are rarely actively deleted by users or ebpf program. Therefore, we do not pay much attention to their deletion. Compared with hash maps, sockhash only provides spin_lock_bh protection. This causes it to appear to have self-locking behavior in the interrupt context. [0]:https://lore.kernel.org/all/CABcoxUayum5oOqFMMqAeWuS8+EzojquSOSyDA3J_2omY=2EeAg@mail.gmail.com/ Reported-by: Hsin-Wei Hung <hsinweih@uci.edu> Fixes:604326b41a
("bpf, sockmap: convert to generic sk_msg interface") Signed-off-by: Xin Liu <liuxin350@huawei.com> Acked-by: John Fastabend <john.fastabend@gmail.com> Link: https://lore.kernel.org/r/20230406122622.109978-1-liuxin350@huawei.com Signed-off-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
92345acc93
commit
d0e34aaea1
1 changed files with 6 additions and 4 deletions
|
@ -414,8 +414,9 @@ static int __sock_map_delete(struct bpf_stab *stab, struct sock *sk_test,
|
|||
{
|
||||
struct sock *sk;
|
||||
int err = 0;
|
||||
unsigned long flags;
|
||||
|
||||
raw_spin_lock_bh(&stab->lock);
|
||||
raw_spin_lock_irqsave(&stab->lock, flags);
|
||||
sk = *psk;
|
||||
if (!sk_test || sk_test == sk)
|
||||
sk = xchg(psk, NULL);
|
||||
|
@ -425,7 +426,7 @@ static int __sock_map_delete(struct bpf_stab *stab, struct sock *sk_test,
|
|||
else
|
||||
err = -EINVAL;
|
||||
|
||||
raw_spin_unlock_bh(&stab->lock);
|
||||
raw_spin_unlock_irqrestore(&stab->lock, flags);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -923,11 +924,12 @@ static long sock_hash_delete_elem(struct bpf_map *map, void *key)
|
|||
struct bpf_shtab_bucket *bucket;
|
||||
struct bpf_shtab_elem *elem;
|
||||
int ret = -ENOENT;
|
||||
unsigned long flags;
|
||||
|
||||
hash = sock_hash_bucket_hash(key, key_size);
|
||||
bucket = sock_hash_select_bucket(htab, hash);
|
||||
|
||||
raw_spin_lock_bh(&bucket->lock);
|
||||
raw_spin_lock_irqsave(&bucket->lock, flags);
|
||||
elem = sock_hash_lookup_elem_raw(&bucket->head, hash, key, key_size);
|
||||
if (elem) {
|
||||
hlist_del_rcu(&elem->node);
|
||||
|
@ -935,7 +937,7 @@ static long sock_hash_delete_elem(struct bpf_map *map, void *key)
|
|||
sock_hash_free_elem(htab, elem);
|
||||
ret = 0;
|
||||
}
|
||||
raw_spin_unlock_bh(&bucket->lock);
|
||||
raw_spin_unlock_irqrestore(&bucket->lock, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue