Commit ed17aa92 authored by Xin Liu's avatar Xin Liu Committed by Alexei Starovoitov

bpf, sockmap: fix deadlocks in the sockhash and sockmap

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: default avatarHsin-Wei Hung <hsinweih@uci.edu>
Fixes: 604326b4 ("bpf, sockmap: convert to generic sk_msg interface")
Signed-off-by: default avatarXin Liu <liuxin350@huawei.com>
Acked-by: default avatarJohn Fastabend <john.fastabend@gmail.com>
Link: https://lore.kernel.org/r/20230406122622.109978-1-liuxin350@huawei.comSigned-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent ec48599a
...@@ -414,8 +414,9 @@ static int __sock_map_delete(struct bpf_stab *stab, struct sock *sk_test, ...@@ -414,8 +414,9 @@ static int __sock_map_delete(struct bpf_stab *stab, struct sock *sk_test,
{ {
struct sock *sk; struct sock *sk;
int err = 0; int err = 0;
unsigned long flags;
raw_spin_lock_bh(&stab->lock); raw_spin_lock_irqsave(&stab->lock, flags);
sk = *psk; sk = *psk;
if (!sk_test || sk_test == sk) if (!sk_test || sk_test == sk)
sk = xchg(psk, NULL); sk = xchg(psk, NULL);
...@@ -425,7 +426,7 @@ static int __sock_map_delete(struct bpf_stab *stab, struct sock *sk_test, ...@@ -425,7 +426,7 @@ static int __sock_map_delete(struct bpf_stab *stab, struct sock *sk_test,
else else
err = -EINVAL; err = -EINVAL;
raw_spin_unlock_bh(&stab->lock); raw_spin_unlock_irqrestore(&stab->lock, flags);
return err; return err;
} }
...@@ -932,11 +933,12 @@ static long sock_hash_delete_elem(struct bpf_map *map, void *key) ...@@ -932,11 +933,12 @@ static long sock_hash_delete_elem(struct bpf_map *map, void *key)
struct bpf_shtab_bucket *bucket; struct bpf_shtab_bucket *bucket;
struct bpf_shtab_elem *elem; struct bpf_shtab_elem *elem;
int ret = -ENOENT; int ret = -ENOENT;
unsigned long flags;
hash = sock_hash_bucket_hash(key, key_size); hash = sock_hash_bucket_hash(key, key_size);
bucket = sock_hash_select_bucket(htab, hash); 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); elem = sock_hash_lookup_elem_raw(&bucket->head, hash, key, key_size);
if (elem) { if (elem) {
hlist_del_rcu(&elem->node); hlist_del_rcu(&elem->node);
...@@ -944,7 +946,7 @@ static long sock_hash_delete_elem(struct bpf_map *map, void *key) ...@@ -944,7 +946,7 @@ static long sock_hash_delete_elem(struct bpf_map *map, void *key)
sock_hash_free_elem(htab, elem); sock_hash_free_elem(htab, elem);
ret = 0; ret = 0;
} }
raw_spin_unlock_bh(&bucket->lock); raw_spin_unlock_irqrestore(&bucket->lock, flags);
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment