bpf: Support socket lookup in CGROUP_SOCK_ADDR progs
Subsystems (6)
v2 cover bpf: Support socket lookup in CGROUP_SOCK_ADDR progs
This patch set makes bpf_sk_lookup_tcp, bpf_sk_lookup_udp and bpf_sk_release helpers available in programs of type BPF_PROG_TYPE_CGROUP_SOCK_ADDR.
Patch 1 is a fix for bpf_sk_lookup_udp that was already merged to bpf (stable) tree. Here it's prerequisite for patch 3.
Patch 2 is the main patch in the set, it makes the helpers available for BPF_PROG_TYPE_CGROUP_SOCK_ADDR and provides more details about use-case.
Patch 3 adds selftest for new functionality.
v1->v2:
- remove "Split bpf_sk_lookup" patch since it was already split by:
commit c8123ead13a5 ("bpf: Extend the sk_lookup() helper to XDP hookpoint.");
- avoid unnecessary bpf_sock_addr_sk_lookup function.
Andrey Ignatov (3):
bpf: Fix IPv6 dport byte order in bpf_sk_lookup_udp
bpf: Support socket lookup in CGROUP_SOCK_ADDR progs selftest/bpf: Use bpf_sk_lookup_{tcp,udp} in test_sock_addr
net/core/filter.c | 50 ++++++++++++++++-- tools/testing/selftests/bpf/connect4_prog.c | 43 ++++++++++++---- tools/testing/selftests/bpf/connect6_prog.c | 56 ++++++++++++++++----- 3 files changed, 125 insertions(+), 24 deletions(-)
Signature · 1 line
2.17.1
PATCH v2 1/3 bpf: Fix IPv6 dport byte order in bpf_sk_lookup_udp
Lookup functions in sk_lookup have different expectations about byte order of provided arguments.
Specifically __inet_lookup, __udp4_lib_lookup and __udp6_lib_lookup expect dport to be in network byte order and do ntohs(dport) internally.
At the same time __inet6_lookup expects dport to be in host byte order and correspondingly name the argument hnum.
sk_lookup works correctly with __inet_lookup, __udp4_lib_lookup and __inet6_lookup with regard to dport. But in __udp6_lib_lookup case it uses host instead of expected network byte order. It makes result returned by bpf_sk_lookup_udp for IPv6 incorrect.
The patch fixes byte order of dport passed to __udp6_lib_lookup.
Originally sk_lookup properly handled UDPv6, but not TCPv6. 5ef0ae84f02a fixes TCPv6 but breaks UDPv6.
--- net/core/filter.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
net/core/filter.c +2 -3
@@ -4867,17 +4867,16 @@ static struct sock *sk_lookup(struct net *net, struct bpf_sock_tuple *tuple, } else {struct in6_addr *src6 = (struct in6_addr *)&tuple->ipv6.saddr;struct in6_addr *dst6 = (struct in6_addr *)&tuple->ipv6.daddr; -u16 hnum =ntohs (tuple->ipv6.dport);if (proto ==IPPROTO_TCP ) sk =__inet6_lookup (net, &tcp_hashinfo,NULL ,0 , src6, tuple->ipv6.sport, - dst6, hnum, + dst6,ntohs (tuple->ipv6.dport), dif, sdif, &refcounted);else if (likely (ipv6_bpf_stub)) sk = ipv6_bpf_stub->udp6_lib_lookup (net, src6, tuple->ipv6.sport, - dst6, hnum, + dst6, tuple->ipv6.dport, dif, sdif, &udp_table,NULL );#endif
Signature · 1 line
2.17.1
PATCH v2 2/3 bpf: Support socket lookup in CGROUP_SOCK_ADDR progs
In reply to Andrey IgnatovMake bpf_sk_lookup_tcp, bpf_sk_lookup_udp and bpf_sk_release helpers available in programs of type BPF_PROG_TYPE_CGROUP_SOCK_ADDR.
Such programs operate on sockets and have access to socket and struct sockaddr passed by user to system calls such as sys_bind, sys_connect, sys_sendmsg.
It's useful to be able to lookup other sockets from these programs. E.g. sys_connect may lookup IP:port endpoint and if there is a server socket bound to that endpoint ("server" can be defined by saddr & sport being zero), redirect client connection to it by rewriting IP:port in sockaddr passed to sys_connect.
--- net/core/filter.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+)
net/core/filter.c +45 -0
@@ -5042,6 +5042,43 @@ static const struct bpf_func_proto bpf_xdp_sk_lookup_tcp_proto = { .arg4_type = ARG_ANYTHING, .arg5_type =ARG_ANYTHING , }; + +BPF_CALL_5(bpf_sock_addr_sk_lookup_tcp, struct bpf_sock_addr_kern *, ctx, + struct bpf_sock_tuple *, tuple, u32, len, u64, netns_id, u64, flags) +{ +return __bpf_sk_lookup (NULL , tuple, len,sock_net (ctx->sk),0 , +IPPROTO_TCP , netns_id, flags); +} + +static const struct bpf_func_proto bpf_sock_addr_sk_lookup_tcp_proto = { + .func = bpf_sock_addr_sk_lookup_tcp, + .gpl_only = false, + .ret_type =RET_PTR_TO_SOCKET_OR_NULL , + .arg1_type =ARG_PTR_TO_CTX , + .arg2_type =ARG_PTR_TO_MEM , + .arg3_type =ARG_CONST_SIZE , + .arg4_type =ARG_ANYTHING , + .arg5_type =ARG_ANYTHING , +}; + +BPF_CALL_5(bpf_sock_addr_sk_lookup_udp, struct bpf_sock_addr_kern *, ctx, + struct bpf_sock_tuple *, tuple, u32, len, u64, netns_id, u64, flags) +{ +return __bpf_sk_lookup (NULL , tuple, len,sock_net (ctx->sk),0 , +IPPROTO_UDP , netns_id, flags); +} + +static const struct bpf_func_proto bpf_sock_addr_sk_lookup_udp_proto = { + .func = bpf_sock_addr_sk_lookup_udp, + .gpl_only = false, + .ret_type =RET_PTR_TO_SOCKET_OR_NULL , + .arg1_type =ARG_PTR_TO_CTX , + .arg2_type =ARG_PTR_TO_MEM , + .arg3_type =ARG_CONST_SIZE , + .arg4_type =ARG_ANYTHING , + .arg5_type =ARG_ANYTHING , +}; +#endif /* CONFIG_INET */ bool bpf_helper_changes_pkt_data (void *func)
@@ -5148,6 +5185,14 @@ sock_addr_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)return &bpf_get_socket_cookie_sock_addr_proto;case BPF_FUNC_get_local_storage:return &bpf_get_local_storage_proto; +#ifdef CONFIG_INET +case BPF_FUNC_sk_lookup_tcp: +return &bpf_sock_addr_sk_lookup_tcp_proto; +case BPF_FUNC_sk_lookup_udp: +return &bpf_sock_addr_sk_lookup_udp_proto; +case BPF_FUNC_sk_release: +return &bpf_sk_release_proto; +#endif /* CONFIG_INET */ default :return bpf_base_func_proto (func_id); }
Signature · 1 line
2.17.1
Quoted 7 lines · Andrey Ignatov
Make
bpf_sk_lookup_tcp,bpf_sk_lookup_udpandbpf_sk_releasehelpers available in programs of typeBPF_PROG_TYPE_CGROUP_SOCK_ADDR.Such programs operate on sockets and have access to socket and struct sockaddr passed by user to system calls such as
sys_bind,sys_connect,sys_sendmsg.
Quoted 5 lines
It's useful to be able to lookup other sockets from these programs. E.g.
sys_connectmay lookup IP:port endpoint and if there is a server socket bound to that endpoint ("server" can be defined by saddr & sport being zero), redirect client connection to it by rewriting IP:port in sockaddr passed tosys_connect.
PATCH v2 3/3 selftest/bpf: Use bpf_sk_lookup_{tcp,udp} in test_sock_addr
In reply to Andrey IgnatovUse bpf_sk_lookup_tcp, bpf_sk_lookup_udp and bpf_sk_release helpers from test_sock_addr programs to make sure they're available and can lookup and release socket properly for IPv4/IPv4, TCP/UDP.
Reading from a few fields of returned struct bpf_sock is also tested.
--- tools/testing/selftests/bpf/connect4_prog.c | 43 ++++++++++++---- tools/testing/selftests/bpf/connect6_prog.c | 56 ++++++++++++++++----- 2 files changed, 78 insertions(+), 21 deletions(-)
tools/testing/selftests/bpf/connect4_prog.c +34 -9
@@ -21,23 +21,48 @@ int _version SEC("version") = 1; SEC("cgroup/connect4")int connect_v4_prog (struct bpf_sock_addr *ctx) { +struct bpf_sock_tuple tuple = {};struct sockaddr_in sa; +struct bpf_sock *sk; + +/* Verify that new destination is available. */ +memset (&tuple.ipv4.saddr,0 ,sizeof (tuple.ipv4.saddr)); +memset (&tuple.ipv4.sport,0 ,sizeof (tuple.ipv4.sport)); + + tuple.ipv4.daddr =bpf_htonl (DST_REWRITE_IP4 ); + tuple.ipv4.dport =bpf_htons (DST_REWRITE_PORT4 ); + +if (ctx->type !=SOCK_STREAM && ctx->type !=SOCK_DGRAM ) +return 0 ; +else if (ctx->type ==SOCK_STREAM ) + sk =bpf_sk_lookup_tcp (ctx, &tuple,sizeof (tuple.ipv4),0 ,0 ); +else + sk =bpf_sk_lookup_udp (ctx, &tuple,sizeof (tuple.ipv4),0 ,0 ); + +if (!sk) +return 0 ; + +if (sk->src_ip4 != tuple.ipv4.daddr || + sk->src_port !=DST_REWRITE_PORT4 ) { +bpf_sk_release (sk); +return 0 ; + } + +bpf_sk_release (sk);/* Rewrite destination. */ ctx->user_ip4 =bpf_htonl (DST_REWRITE_IP4 ); ctx->user_port =bpf_htons (DST_REWRITE_PORT4 ); -if (ctx->type ==SOCK_DGRAM || ctx->type ==SOCK_STREAM ) { -///* Rewrite source. */ -memset (&sa,0 ,sizeof (sa)); +/* Rewrite source. */ +memset (&sa,0 ,sizeof (sa)); - sa.sin_family =AF_INET ; - sa.sin_port =bpf_htons (0 ); - sa.sin_addr.s_addr =bpf_htonl (SRC_REWRITE_IP4 ); + sa.sin_family =AF_INET ; + sa.sin_port =bpf_htons (0 ); + sa.sin_addr.s_addr =bpf_htonl (SRC_REWRITE_IP4 ); -if (bpf_bind (ctx, (struct sockaddr *)&sa,sizeof (sa)) !=0 ) -return 0 ; - } +if (bpf_bind (ctx, (struct sockaddr *)&sa,sizeof (sa)) !=0 ) +return 0 ;return 1 ; }
tools/testing/selftests/bpf/connect6_prog.c +44 -12
72 lines not on this page · raw message
Signature · 1 line
2.17.1
Alexei Starovoitov
AppliedQuoted 11 lines · Andrey Ignatov
This patch set makes
bpf_sk_lookup_tcp,bpf_sk_lookup_udpandbpf_sk_releasehelpers available in programs of typeBPF_PROG_TYPE_CGROUP_SOCK_ADDR.Patch 1 is a fix for
bpf_sk_lookup_udpthat was already merged to bpf (stable) tree. Here it's prerequisite for patch 3.Patch 2 is the main patch in the set, it makes the helpers available for
BPF_PROG_TYPE_CGROUP_SOCK_ADDRand provides more details about use-case.
Quoted 7 lines
Patch 3 adds selftest for new functionality.
v1->v2:
- remove "Splitbpf_sk_lookup" patch since it was already split by:
commitc8123ead13a5("bpf: Extend thesk_lookup()helper to XDP hookpoint.");
- avoid unnecessarybpf_sock_addr_sk_lookupfunction.
applied, thanks