Skip to content

Commit 7e81a35

Browse files
jrfastabborkmann
authored andcommitted
bpf: Sockmap, ensure sock lock held during tear down
The sock_map_free() and sock_hash_free() paths used to delete sockmap and sockhash maps walk the maps and destroy psock and bpf state associated with the socks in the map. When done the socks no longer have BPF programs attached and will function normally. This can happen while the socks in the map are still "live" meaning data may be sent/received during the walk. Currently, though we don't take the sock_lock when the psock and bpf state is removed through this path. Specifically, this means we can be writing into the ops structure pointers such as sendmsg, sendpage, recvmsg, etc. while they are also being called from the networking side. This is not safe, we never used proper READ_ONCE/WRITE_ONCE semantics here if we believed it was safe. Further its not clear to me its even a good idea to try and do this on "live" sockets while networking side might also be using the socket. Instead of trying to reason about using the socks from both sides lets realize that every use case I'm aware of rarely deletes maps, in fact kubernetes/Cilium case builds map at init and never tears it down except on errors. So lets do the simple fix and grab sock lock. This patch wraps sock deletes from maps in sock lock and adds some annotations so we catch any other cases easier. Fixes: 604326b ("bpf, sockmap: convert to generic sk_msg interface") Signed-off-by: John Fastabend <[email protected]> Signed-off-by: Daniel Borkmann <[email protected]> Acked-by: Song Liu <[email protected]> Cc: [email protected] Link: https://lore.kernel.org/bpf/[email protected]
1 parent 4da6a19 commit 7e81a35

File tree

2 files changed

+8
-1
lines changed

2 files changed

+8
-1
lines changed

net/core/skmsg.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,8 @@ EXPORT_SYMBOL_GPL(sk_psock_destroy);
594594

595595
void sk_psock_drop(struct sock *sk, struct sk_psock *psock)
596596
{
597+
sock_owned_by_me(sk);
598+
597599
sk_psock_cork_free(psock);
598600
sk_psock_zap_ingress(psock);
599601

net/core/sock_map.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,8 +241,11 @@ static void sock_map_free(struct bpf_map *map)
241241
struct sock *sk;
242242

243243
sk = xchg(psk, NULL);
244-
if (sk)
244+
if (sk) {
245+
lock_sock(sk);
245246
sock_map_unref(sk, psk);
247+
release_sock(sk);
248+
}
246249
}
247250
raw_spin_unlock_bh(&stab->lock);
248251
rcu_read_unlock();
@@ -862,7 +865,9 @@ static void sock_hash_free(struct bpf_map *map)
862865
raw_spin_lock_bh(&bucket->lock);
863866
hlist_for_each_entry_safe(elem, node, &bucket->head, node) {
864867
hlist_del_rcu(&elem->node);
868+
lock_sock(elem->sk);
865869
sock_map_unref(elem->sk, elem);
870+
release_sock(elem->sk);
866871
}
867872
raw_spin_unlock_bh(&bucket->lock);
868873
}

0 commit comments

Comments
 (0)