bpf: Fix IPv6 dport byte order in bpf_sk_lookup_udp
Subsystems (4)
PATCH 1/1 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
@@ -4852,18 +4852,17 @@ 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);int sdif =inet6_sdif (skb);if (proto ==IPPROTO_TCP ) sk =__inet6_lookup (net, &tcp_hashinfo, skb,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, skb);#endif
Signature · 1 line
2.17.1
Quoted 15 lines · Andrey Ignatov
Lookup functions in
sk_lookuphave different expectations about byte order of provided arguments.Specifically
__inet_lookup,__udp4_lib_lookupand__udp6_lib_lookupexpect dport to be in network byte order and do ntohs(dport) internally.At the same time
__inet6_lookupexpects dport to be in host byte order and correspondingly name the argument hnum.
sk_lookupworks correctly with__inet_lookup,__udp4_lib_lookupand__inet6_lookupwith regard to dport. But in__udp6_lib_lookupcase it uses host instead of expected network byte order. It makes result returned bybpf_sk_lookup_udpfor IPv6 incorrect.
Quoted 7 lines
The patch fixes byte order of dport passed to
__udp6_lib_lookup.Originally
sk_lookupproperly handled UDPv6, but not TCPv6.5ef0ae84f02afixes TCPv6 but breaks UDPv6.Fixes 5ef0ae84f02a ("bpf: Fix IPv6 dport byte-order in bpf_sk_lookup")Signed-off-by Andrey Ignatov <[email protected]>
Thanks for the fix, makes sense.
Quoted 14 lines · Andrey Ignatov
Lookup functions in
sk_lookuphave different expectations about byte order of provided arguments.Specifically
__inet_lookup,__udp4_lib_lookupand__udp6_lib_lookupexpect dport to be in network byte order and do ntohs(dport) internally.At the same time
__inet6_lookupexpects dport to be in host byte order and correspondingly name the argument hnum.
sk_lookupworks correctly with__inet_lookup,__udp4_lib_lookupand__inet6_lookupwith regard to dport. But in__udp6_lib_lookupcase it uses host instead of expected network byte order. It makes result returned bybpf_sk_lookup_udpfor IPv6 incorrect.
Quoted 7 lines
The patch fixes byte order of dport passed to
__udp6_lib_lookup.Originally
sk_lookupproperly handled UDPv6, but not TCPv6.5ef0ae84f02afixes TCPv6 but breaks UDPv6.Fixes 5ef0ae84f02a ("bpf: Fix IPv6 dport byte-order in bpf_sk_lookup")Signed-off-by Andrey Ignatov <[email protected]>
Good catch.
Quoted 32 lines
--- net/core/filter.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)net/core/filter.c +2
-3@@ -4852,18 +4852,17 @@ 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);int sdif =inet6_sdif (skb);if (proto ==IPPROTO_TCP ) sk =__inet6_lookup (net, &tcp_hashinfo, skb,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, skb);#endif Signature · 1 line
2.17.1
Quoted 14 lines · Andrey Ignatov
Lookup functions in
sk_lookuphave different expectations about byte order of provided arguments.Specifically
__inet_lookup,__udp4_lib_lookupand__udp6_lib_lookupexpect dport to be in network byte order and do ntohs(dport) internally.At the same time
__inet6_lookupexpects dport to be in host byte order and correspondingly name the argument hnum.
sk_lookupworks correctly with__inet_lookup,__udp4_lib_lookupand__inet6_lookupwith regard to dport. But in__udp6_lib_lookupcase it uses host instead of expected network byte order. It makes result returned bybpf_sk_lookup_udpfor IPv6 incorrect.
Quoted 7 lines
The patch fixes byte order of dport passed to
__udp6_lib_lookup.Originally
sk_lookupproperly handled UDPv6, but not TCPv6.5ef0ae84f02afixes TCPv6 but breaks UDPv6.Fixes 5ef0ae84f02a ("bpf: Fix IPv6 dport byte-order in bpf_sk_lookup")Signed-off-by Andrey Ignatov <[email protected]>
Applied to bpf, thanks Andrey!