Skip to content

Commit dbafd7d

Browse files
iamkafaiAlexei Starovoitov
authored and
Alexei Starovoitov
committed
bpf: Add bpf_get_listener_sock(struct bpf_sock *sk) helper
Add a new helper "struct bpf_sock *bpf_get_listener_sock(struct bpf_sock *sk)" which returns a bpf_sock in TCP_LISTEN state. It will trace back to the listener sk from a request_sock if possible. It returns NULL for all other cases. No reference is taken because the helper ensures the sk is in SOCK_RCU_FREE (where the TCP_LISTEN sock should be in). Hence, bpf_sk_release() is unnecessary and the verifier does not allow bpf_sk_release(listen_sk) to be called either. The following is also allowed because the bpf_prog is run under rcu_read_lock(): sk = bpf_sk_lookup_tcp(); /* if (!sk) { ... } */ listen_sk = bpf_get_listener_sock(sk); /* if (!listen_sk) { ... } */ bpf_sk_release(sk); src_port = listen_sk->src_port; /* Allowed */ Signed-off-by: Martin KaFai Lau <[email protected]> Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent 1b98658 commit dbafd7d

File tree

2 files changed

+31
-1
lines changed

2 files changed

+31
-1
lines changed

Diff for: include/uapi/linux/bpf.h

+10-1
Original file line numberDiff line numberDiff line change
@@ -2366,6 +2366,14 @@ union bpf_attr {
23662366
* current value is ect (ECN capable). Works with IPv6 and IPv4.
23672367
* Return
23682368
* 1 if set, 0 if not set.
2369+
*
2370+
* struct bpf_sock *bpf_get_listener_sock(struct bpf_sock *sk)
2371+
* Description
2372+
* Return a **struct bpf_sock** pointer in TCP_LISTEN state.
2373+
* bpf_sk_release() is unnecessary and not allowed.
2374+
* Return
2375+
* A **struct bpf_sock** pointer on success, or NULL in
2376+
* case of failure.
23692377
*/
23702378
#define __BPF_FUNC_MAPPER(FN) \
23712379
FN(unspec), \
@@ -2465,7 +2473,8 @@ union bpf_attr {
24652473
FN(spin_unlock), \
24662474
FN(sk_fullsock), \
24672475
FN(tcp_sock), \
2468-
FN(skb_ecn_set_ce),
2476+
FN(skb_ecn_set_ce), \
2477+
FN(get_listener_sock),
24692478

24702479
/* integer value in 'imm' field of BPF_CALL instruction selects which helper
24712480
* function eBPF program intends to call

Diff for: net/core/filter.c

+21
Original file line numberDiff line numberDiff line change
@@ -5418,6 +5418,23 @@ static const struct bpf_func_proto bpf_tcp_sock_proto = {
54185418
.arg1_type = ARG_PTR_TO_SOCK_COMMON,
54195419
};
54205420

5421+
BPF_CALL_1(bpf_get_listener_sock, struct sock *, sk)
5422+
{
5423+
sk = sk_to_full_sk(sk);
5424+
5425+
if (sk->sk_state == TCP_LISTEN && sock_flag(sk, SOCK_RCU_FREE))
5426+
return (unsigned long)sk;
5427+
5428+
return (unsigned long)NULL;
5429+
}
5430+
5431+
static const struct bpf_func_proto bpf_get_listener_sock_proto = {
5432+
.func = bpf_get_listener_sock,
5433+
.gpl_only = false,
5434+
.ret_type = RET_PTR_TO_SOCKET_OR_NULL,
5435+
.arg1_type = ARG_PTR_TO_SOCK_COMMON,
5436+
};
5437+
54215438
BPF_CALL_1(bpf_skb_ecn_set_ce, struct sk_buff *, skb)
54225439
{
54235440
unsigned int iphdr_len;
@@ -5603,6 +5620,8 @@ cg_skb_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
56035620
#ifdef CONFIG_INET
56045621
case BPF_FUNC_tcp_sock:
56055622
return &bpf_tcp_sock_proto;
5623+
case BPF_FUNC_get_listener_sock:
5624+
return &bpf_get_listener_sock_proto;
56065625
case BPF_FUNC_skb_ecn_set_ce:
56075626
return &bpf_skb_ecn_set_ce_proto;
56085627
#endif
@@ -5698,6 +5717,8 @@ tc_cls_act_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
56985717
return &bpf_sk_release_proto;
56995718
case BPF_FUNC_tcp_sock:
57005719
return &bpf_tcp_sock_proto;
5720+
case BPF_FUNC_get_listener_sock:
5721+
return &bpf_get_listener_sock_proto;
57015722
#endif
57025723
default:
57035724
return bpf_base_func_proto(func_id);

0 commit comments

Comments
 (0)