Commit 63cc8e20 authored by Daniel Borkmann's avatar Daniel Borkmann
Browse files

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 -
ad13baf4 ("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: default avatarDaniel Borkmann <daniel@iogearbox.net>
parents 60911970 deb59400
Loading
Loading
Loading
Loading
+17 −7
Original line number Diff line number Diff line
@@ -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))