Merge branch 'bpf-fix-sock-field-tests'

Jakub Sitnicki says:

====================
I think we have reached a consensus [1] on how the test for the 4-byte load from
bpf_sock->dst_port and bpf_sk_lookup->remote_port should look, so here goes v3.

I will submit a separate set of patches for bpf_sk_lookup->remote_port tests.

This series has been tested on x86_64 and s390 on top of recent bpf-next -
ad13baf456 ("selftests/bpf: Test subprog jit when toggle bpf_jit_harden
repeatedly").

  [1] https://lore.kernel.org/bpf/87k0cwxkzs.fsf@cloudflare.com/

v2 -> v3:
- Split what was previously patch 2 which was doing two things
- Use BPF_TCP_* constants (Martin)
- Treat the result of 4-byte load from dst_port as a 16-bit value (Martin)
- Typo fixup and some rewording in patch 4 description
v1 -> v2:
- Limit read_sk_dst_port only to client traffic (patch 2)
- Make read_sk_dst_port pass on litte- and big-endian (patch 3)

v1: https://lore.kernel.org/bpf/20220225184130.483208-1-jakub@cloudflare.com/
v2: https://lore.kernel.org/bpf/20220227202757.519015-1-jakub@cloudflare.com/
====================

Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
This commit is contained in:
Daniel Borkmann 2022-03-18 15:46:59 +01:00
commit 63cc8e20b3

View File

@ -114,7 +114,7 @@ static void tpcpy(struct bpf_tcp_sock *dst,
#define RET_LOG() ({ \
linum = __LINE__; \
bpf_map_update_elem(&linum_map, &linum_idx, &linum, BPF_NOEXIST); \
bpf_map_update_elem(&linum_map, &linum_idx, &linum, BPF_ANY); \
return CG_OK; \
})
@ -134,11 +134,11 @@ int egress_read_sock_fields(struct __sk_buff *skb)
if (!sk)
RET_LOG();
/* Not the testing egress traffic or
* TCP_LISTEN (10) socket will be copied at the ingress side.
/* Not testing the egress traffic or the listening socket,
* which are covered by the cgroup_skb/ingress test program.
*/
if (sk->family != AF_INET6 || !is_loopback6(sk->src_ip6) ||
sk->state == 10)
sk->state == BPF_TCP_LISTEN)
return CG_OK;
if (sk->src_port == bpf_ntohs(srv_sa6.sin6_port)) {
@ -232,8 +232,8 @@ int ingress_read_sock_fields(struct __sk_buff *skb)
sk->src_port != bpf_ntohs(srv_sa6.sin6_port))
return CG_OK;
/* Only interested in TCP_LISTEN */
if (sk->state != 10)
/* Only interested in the listening socket */
if (sk->state != BPF_TCP_LISTEN)
return CG_OK;
/* It must be a fullsock for cgroup_skb/ingress prog */
@ -251,10 +251,16 @@ int ingress_read_sock_fields(struct __sk_buff *skb)
return CG_OK;
}
/*
* NOTE: 4-byte load from bpf_sock at dst_port offset is quirky. It
* gets rewritten by the access converter to a 2-byte load for
* backward compatibility. Treating the load result as a be16 value
* makes the code portable across little- and big-endian platforms.
*/
static __noinline bool sk_dst_port__load_word(struct bpf_sock *sk)
{
__u32 *word = (__u32 *)&sk->dst_port;
return word[0] == bpf_htonl(0xcafe0000);
return word[0] == bpf_htons(0xcafe);
}
static __noinline bool sk_dst_port__load_half(struct bpf_sock *sk)
@ -281,6 +287,10 @@ int read_sk_dst_port(struct __sk_buff *skb)
if (!sk)
RET_LOG();
/* Ignore everything but the SYN from the client socket */
if (sk->state != BPF_TCP_SYN_SENT)
return CG_OK;
if (!sk_dst_port__load_word(sk))
RET_LOG();
if (!sk_dst_port__load_half(sk))