bpf: Extract shared reqsk-to-listener upgrade

__bpf_sk_lookup() and bpf_sk_lookup() duplicate the same sk_to_full_sk()
reqsk-to-listener upgrade. Extract it into a helper. Leave the currently
unreachable WARN_ONCE as a defensive assert. No functional change.

Signed-off-by: Michal Luczaj <mhal@rbox.co>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>
Reviewed-by: Jakub Sitnicki <jakub@cloudflare.com>
Link: https://lore.kernel.org/bpf/20260813-sockmap-lookup-get-ref-v1-1-31f5d55f44ac@rbox.co
This commit is contained in:
Michal Luczaj 2026-08-13 14:41:59 +02:00 committed by Daniel Borkmann
parent d99bda7f01
commit 3c3d2c09ec

View File

@ -7167,6 +7167,28 @@ __bpf_skc_lookup(struct sk_buff *skb, struct bpf_sock_tuple *tuple, u32 len,
return sk;
}
static struct sock *
bpf_sk_lookup_full_sk(struct sock *sk)
{
struct sock *sk2 = sk_to_full_sk(sk);
/*
* sk_to_full_sk() may return sk->rsk_listener, make sure the original
* sk sock refcnt is decremented to prevent a request_sock leak.
*/
if (sk2 != sk) {
sock_gen_put(sk);
/* Ensure there is no need to bump sk2 refcnt. */
if (unlikely(sk2 && !sock_flag(sk2, SOCK_RCU_FREE))) {
WARN_ONCE(1, "Found non-RCU, unreferenced socket!");
return NULL;
}
sk = sk2;
}
return sk;
}
static struct sock *
__bpf_sk_lookup(struct sk_buff *skb, struct bpf_sock_tuple *tuple, u32 len,
struct net *caller_net, u32 ifindex, u8 proto, u64 netns_id,
@ -7175,24 +7197,8 @@ __bpf_sk_lookup(struct sk_buff *skb, struct bpf_sock_tuple *tuple, u32 len,
struct sock *sk = __bpf_skc_lookup(skb, tuple, len, caller_net,
ifindex, proto, netns_id, flags,
sdif);
if (sk) {
struct sock *sk2 = sk_to_full_sk(sk);
/* sk_to_full_sk() may return (sk)->rsk_listener, so make sure the original sk
* sock refcnt is decremented to prevent a request_sock leak.
*/
if (sk2 != sk) {
sock_gen_put(sk);
/* Ensure there is no need to bump sk2 refcnt */
if (unlikely(sk2 && !sock_flag(sk2, SOCK_RCU_FREE))) {
WARN_ONCE(1, "Found non-RCU, unreferenced socket!");
return NULL;
}
sk = sk2;
}
}
if (sk)
sk = bpf_sk_lookup_full_sk(sk);
return sk;
}
@ -7221,24 +7227,8 @@ bpf_sk_lookup(struct sk_buff *skb, struct bpf_sock_tuple *tuple, u32 len,
{
struct sock *sk = bpf_skc_lookup(skb, tuple, len, proto, netns_id,
flags);
if (sk) {
struct sock *sk2 = sk_to_full_sk(sk);
/* sk_to_full_sk() may return (sk)->rsk_listener, so make sure the original sk
* sock refcnt is decremented to prevent a request_sock leak.
*/
if (sk2 != sk) {
sock_gen_put(sk);
/* Ensure there is no need to bump sk2 refcnt */
if (unlikely(sk2 && !sock_flag(sk2, SOCK_RCU_FREE))) {
WARN_ONCE(1, "Found non-RCU, unreferenced socket!");
return NULL;
}
sk = sk2;
}
}
if (sk)
sk = bpf_sk_lookup_full_sk(sk);
return sk;
}