Skip to content

Commit

Permalink
bpf, sockmap: fix deadlocks in the sockhash and sockmap
Browse files Browse the repository at this point in the history
[ Upstream commit ed17aa9 ]

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: 604326b ("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>
  • Loading branch information
bitcoffeeiux authored and gregkh committed May 11, 2023
1 parent a0f3055 commit d2b8cf3
Showing 1 changed file with 6 additions and 4 deletions.
10 changes: 6 additions & 4 deletions net/core/sock_map.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;
}

Expand Down Expand Up @@ -923,19 +924,20 @@ 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);
sock_map_unref(elem->sk, elem);
sock_hash_free_elem(htab, elem);
ret = 0;
}
raw_spin_unlock_bh(&bucket->lock);
raw_spin_unlock_irqrestore(&bucket->lock, flags);
return ret;
}

Expand Down

0 comments on commit d2b8cf3

Please sign in to comment.