Skip to content

Commit deb5940

Browse files
jsitnickiborkmann
authored andcommitted
selftests/bpf: Fix test for 4-byte load from dst_port on big-endian
The check for 4-byte load from dst_port offset into bpf_sock is failing on big-endian architecture - s390. The bpf access converter rewrites the 4-byte load to a 2-byte load from sock_common at skc_dport offset, as shown below. * s390 / llvm-objdump -S --no-show-raw-insn 00000000000002a0 <sk_dst_port__load_word>: 84: r1 = *(u32 *)(r1 + 48) 85: w0 = 1 86: if w1 == 51966 goto +1 <LBB5_2> 87: w0 = 0 00000000000002c0 <LBB5_2>: 88: exit * s390 / bpftool prog dump xlated _Bool sk_dst_port__load_word(struct bpf_sock * sk): 35: (69) r1 = *(u16 *)(r1 +12) 36: (bc) w1 = w1 37: (b4) w0 = 1 38: (16) if w1 == 0xcafe goto pc+1 39: (b4) w0 = 0 40: (95) exit * x86_64 / llvm-objdump -S --no-show-raw-insn 00000000000002a0 <sk_dst_port__load_word>: 84: r1 = *(u32 *)(r1 + 48) 85: w0 = 1 86: if w1 == 65226 goto +1 <LBB5_2> 87: w0 = 0 00000000000002c0 <LBB5_2>: 88: exit * x86_64 / bpftool prog dump xlated _Bool sk_dst_port__load_word(struct bpf_sock * sk): 33: (69) r1 = *(u16 *)(r1 +12) 34: (b4) w0 = 1 35: (16) if w1 == 0xfeca goto pc+1 36: (b4) w0 = 0 37: (95) exit This leads to surprises if we treat the destination register contents as a 32-bit value, ignoring the fact that in reality it contains a 16-bit value. On little-endian the register contents reflect the bpf_sock struct definition, where the lower 16-bits contain the port number: struct bpf_sock { ... __be16 dst_port; /* offset 48 */ __u16 :16; ... }; However, on big-endian the register contents suggest that field the layout of bpf_sock struct is as so: struct bpf_sock { ... __u16 :16; /* offset 48 */ __be16 dst_port; ... }; Account for this quirky access conversion in the test case exercising the 4-byte load by treating the result as 16-bit wide. Signed-off-by: Jakub Sitnicki <[email protected]> Signed-off-by: Daniel Borkmann <[email protected]> Acked-by: Martin KaFai Lau <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent e06b5bb commit deb5940

File tree

1 file changed

+7
-1
lines changed

1 file changed

+7
-1
lines changed

tools/testing/selftests/bpf/progs/test_sock_fields.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,10 +251,16 @@ int ingress_read_sock_fields(struct __sk_buff *skb)
251251
return CG_OK;
252252
}
253253

254+
/*
255+
* NOTE: 4-byte load from bpf_sock at dst_port offset is quirky. It
256+
* gets rewritten by the access converter to a 2-byte load for
257+
* backward compatibility. Treating the load result as a be16 value
258+
* makes the code portable across little- and big-endian platforms.
259+
*/
254260
static __noinline bool sk_dst_port__load_word(struct bpf_sock *sk)
255261
{
256262
__u32 *word = (__u32 *)&sk->dst_port;
257-
return word[0] == bpf_htonl(0xcafe0000);
263+
return word[0] == bpf_htons(0xcafe);
258264
}
259265

260266
static __noinline bool sk_dst_port__load_half(struct bpf_sock *sk)

0 commit comments

Comments
 (0)