Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests/bpf: Fix two net related test failures with 64K page size

When running BPF selftests on arm64 with a 64K page size, I encountered
the following two test failures:
sockmap_basic/sockmap skb_verdict change tail:FAIL
tc_change_tail:FAIL

With further debugging, I identified the root cause in the following
kernel code within __bpf_skb_change_tail():

u32 max_len = BPF_SKB_MAX_LEN;
u32 min_len = __bpf_skb_min_len(skb);
int ret;

if (unlikely(flags || new_len > max_len || new_len < min_len))
return -EINVAL;

With a 4K page size, new_len = 65535 and max_len = 16064, the function
returns -EINVAL. However, With a 64K page size, max_len increases to
261824, allowing execution to proceed further in the function. This is
because BPF_SKB_MAX_LEN scales with the page size and larger page sizes
result in higher max_len values.

Updating the new_len parameter in both tests based on actual kernel
page size resolved both failures.

Signed-off-by: Yonghong Song <yonghong.song@linux.dev>
Link: https://lore.kernel.org/r/20250612035037.2207911-1-yonghong.song@linux.dev
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Yonghong Song and committed by
Alexei Starovoitov
96fcf7e7 4fc012da

+14 -9
+7 -2
tools/testing/selftests/bpf/progs/test_sockmap_change_tail.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 /* Copyright (c) 2024 ByteDance */ 3 - #include <linux/bpf.h> 3 + #include "vmlinux.h" 4 4 #include <bpf/bpf_helpers.h> 5 + 6 + #ifndef PAGE_SIZE 7 + #define PAGE_SIZE __PAGE_SIZE 8 + #endif 9 + #define BPF_SKB_MAX_LEN (PAGE_SIZE << 2) 5 10 6 11 struct { 7 12 __uint(type, BPF_MAP_TYPE_SOCKMAP); ··· 36 31 change_tail_ret = bpf_skb_change_tail(skb, skb->len + 1, 0); 37 32 return SK_PASS; 38 33 } else if (data[0] == 'E') { /* Error */ 39 - change_tail_ret = bpf_skb_change_tail(skb, 65535, 0); 34 + change_tail_ret = bpf_skb_change_tail(skb, BPF_SKB_MAX_LEN, 0); 40 35 return SK_PASS; 41 36 } 42 37 return SK_PASS;
+7 -7
tools/testing/selftests/bpf/progs/test_tc_change_tail.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 - #include <linux/bpf.h> 2 + #include "vmlinux.h" 3 3 #include <bpf/bpf_helpers.h> 4 - #include <linux/if_ether.h> 5 - #include <linux/in.h> 6 - #include <linux/ip.h> 7 - #include <linux/udp.h> 8 - #include <linux/pkt_cls.h> 4 + 5 + #ifndef PAGE_SIZE 6 + #define PAGE_SIZE __PAGE_SIZE 7 + #endif 8 + #define BPF_SKB_MAX_LEN (PAGE_SIZE << 2) 9 9 10 10 long change_tail_ret = 1; 11 11 ··· 94 94 bpf_skb_change_tail(skb, len, 0); 95 95 return TCX_PASS; 96 96 } else if (payload[0] == 'E') { /* Error */ 97 - change_tail_ret = bpf_skb_change_tail(skb, 65535, 0); 97 + change_tail_ret = bpf_skb_change_tail(skb, BPF_SKB_MAX_LEN, 0); 98 98 return TCX_PASS; 99 99 } else if (payload[0] == 'Z') { /* Zero */ 100 100 change_tail_ret = bpf_skb_change_tail(skb, 0, 0);