Re: [PATCH bpf-next v1 1/2] selftests/bpf: Check alignment flag if expected result is REJECT

From: Tiezhu Yang

Date: Thu Mar 12 2026 - 03:00:37 EST


Hi Emil and Paul,

On 2026/3/11 下午11:56, Emil Tsalapatis wrote:
On Tue Mar 10, 2026 at 2:45 AM EDT, Tiezhu Yang wrote:
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is set unconditionally for the
most archs such as x86_64, aarch64, ppc64el and s390x, but this config
may be not set by users for riscv64 and loongarch64.

If CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set, the BPF verifier
detects if a program has unaligned access and then rejects them. So it
should also check the flag F_NEEDS_EFFICIENT_UNALIGNED_ACCESS if the
expected result is REJECT and set alignment_prevented_execution as 1,
then the message "(NOTE: not executed due to unknown alignment)" can
be printed for some testcases of test_verifier to reflect the reality.

Signed-off-by: Tiezhu Yang <yangtiezhu@xxxxxxxxxxx>
---
tools/testing/selftests/bpf/test_verifier.c | 5 +++++
1 file changed, 5 insertions(+)

diff --git a/tools/testing/selftests/bpf/test_verifier.c b/tools/testing/selftests/bpf/test_verifier.c
index a8ae03c57bba..a1ae2f044e96 100644
--- a/tools/testing/selftests/bpf/test_verifier.c
+++ b/tools/testing/selftests/bpf/test_verifier.c
@@ -1640,6 +1640,11 @@ static void do_test_single(struct bpf_test *test, bool unpriv,
printf("FAIL\nUnexpected success to load!\n");
goto fail_log;
}
+#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
+ if (fd_prog < 0 &&
+ (test->flags & F_NEEDS_EFFICIENT_UNALIGNED_ACCESS))
+ alignment_prevented_execution = 1;
+#endif

This doesn't look like it's breaking anything, but it will cause all
tests with F_NEEDS_EFFICIENT_UNALIGNED ACCESS to be reported as failing
due to unaligned accesses even if they actually failed due to expected
errors at load time.

Which test programs is this fix targeted towards? Can't we just skip
those tests for riscv/loongarch instead of adding this workaround?

Thanks for your reviews.

It does not fix any failed testcases, the testcases passed without
and with this patch. It only affects the output for some testcases
such as test_verifier 14, 153, 190, 191, 193, 197, 200, 201, 202,
204, 255, 256, 295, 297, 298, 300, 301, 302, 307, 308, 331, 341,
342, 475, 477, 500, 512, 514, 515, 517, 520, 522, 523, 525.

For example, for the test_verifier 14,
verifier/atomic_cmpxchg.c:215
"Dest pointer in r0 - succeed, check 5",
if remove ".flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,",
here is the test result if HAVE_EFFICIENT_UNALIGNED_ACCESS is not set:

$ sudo ./test_verifier 14
#14/u Dest pointer in r0 - succeed, check 5 OK
#14/p Dest pointer in r0 - succeed, check 5 FAIL
Unexpected verifier log!
EXP: R0 invalid mem access
RES:
FAIL
Unexpected error message!
EXP: R0 invalid mem access
RES: misaligned access off (0x0; 0xffffffff)+-8 size 4
verification time 27 usec
stack depth 8
processed 5 insns (limit 1000000) max_states_per_insn 0 total_states 0 peak_states 0 mark_read 0

misaligned access off (0x0; 0xffffffff)+-8 size 4
verification time 27 usec
stack depth 8
processed 5 insns (limit 1000000) max_states_per_insn 0 total_states 0 peak_states 0 mark_read 0
Summary: 1 PASSED, 0 SKIPPED, 1 FAILED

It seems that this is because the program has unaligned accesses,
but the kernel sets CONFIG_ARCH_STRICT_ALIGN by default to enable
-mstrict-align to prevent unaligned accesses.

So I think add "(NOTE: not executed due to unknown alignment)" to the
output is reasonable. Something I missed?

Without this patch:

sudo ./test_verifier > log.before

With this patch:

sudo ./test_verifier > log.after

Here is the diff:

$ diff -uNr log.before log.after
--- log.before 2026-03-12 14:19:04.119957887 +0800
+++ log.after 2026-03-12 14:23:03.468251328 +0800
@@ -26,7 +26,7 @@
#12/p Dest pointer in r0 - succeed, check 3 OK
#13/u Dest pointer in r0 - succeed, check 4 OK
#13/p Dest pointer in r0 - succeed, check 4 OK
-#14/p Dest pointer in r0 - succeed, check 5 OK
+#14/p Dest pointer in r0 - succeed, check 5 OK (NOTE: not executed due to unknown alignment)
#15/u BPF_ATOMIC_FETCH_ADD smoketest - 64bit OK
#15/p BPF_ATOMIC_FETCH_ADD smoketest - 64bit OK
#16/u BPF_ATOMIC_FETCH_ADD smoketest - 32bit OK
@@ -254,7 +254,7 @@
#151/p calls: callee using wrong args2 OK
#152/u calls: callee using two args OK
#152/p calls: callee using two args OK
-#153/p calls: callee changing pkt pointers OK
+#153/p calls: callee changing pkt pointers OK (NOTE: not executed due to unknown alignment)
#154/u calls: ptr null check in subprog OK
#154/p calls: ptr null check in subprog OK
#155/p calls: two calls with args OK
@@ -293,21 +293,21 @@
#187/p calls: ambiguous return value OK
#188/p calls: two calls that return map_value OK
#189/p calls: two calls that return map_value with bool condition OK
-#190/p calls: two calls that return map_value with incorrect bool check OK
-#191/p calls: two calls that receive map_value via arg=ptr_stack_of_caller. test1 OK
+#190/p calls: two calls that return map_value with incorrect bool check OK (NOTE: not executed due to unknown alignment)
+#191/p calls: two calls that receive map_value via arg=ptr_stack_of_caller. test1 OK (NOTE: not executed due to unknown alignment)
#192/p calls: two calls that receive map_value via arg=ptr_stack_of_caller. test2 OK
-#193/p calls: two jumps that receive map_value via arg=ptr_stack_of_jumper. test3 OK
+#193/p calls: two jumps that receive map_value via arg=ptr_stack_of_jumper. test3 OK (NOTE: not executed due to unknown alignment)
#194/p calls: two calls that receive map_value_ptr_or_null via arg. test1 OK
#195/p calls: two calls that receive map_value_ptr_or_null via arg. test2 OK
#196/p calls: pkt_ptr spill into caller stack OK (NOTE: not executed due to unknown alignment)
-#197/p calls: pkt_ptr spill into caller stack 2 OK
+#197/p calls: pkt_ptr spill into caller stack 2 OK (NOTE: not executed due to unknown alignment)
#198/p calls: pkt_ptr spill into caller stack 3 OK (NOTE: not executed due to unknown alignment)
#199/p calls: pkt_ptr spill into caller stack 4 OK (NOTE: not executed due to unknown alignment)
-#200/p calls: pkt_ptr spill into caller stack 5 OK
-#201/p calls: pkt_ptr spill into caller stack 6 OK
-#202/p calls: pkt_ptr spill into caller stack 7 OK
+#200/p calls: pkt_ptr spill into caller stack 5 OK (NOTE: not executed due to unknown alignment)
+#201/p calls: pkt_ptr spill into caller stack 6 OK (NOTE: not executed due to unknown alignment)
+#202/p calls: pkt_ptr spill into caller stack 7 OK (NOTE: not executed due to unknown alignment)
#203/p calls: pkt_ptr spill into caller stack 8 OK (NOTE: not executed due to unknown alignment)
-#204/p calls: pkt_ptr spill into caller stack 9 OK
+#204/p calls: pkt_ptr spill into caller stack 9 OK (NOTE: not executed due to unknown alignment)
#205/p calls: caller stack init to zero or map_value_or_null OK
#206/u calls: stack init to zero and pruning OK
#206/p calls: stack init to zero and pruning OK
@@ -390,8 +390,8 @@
#253/p check skb->hash half load permitted OK
#254/u check skb->hash half load permitted 2 OK
#254/p check skb->hash half load permitted 2 OK
-#255/p check skb->hash half load not permitted, unaligned 1 OK
-#256/p check skb->hash half load not permitted, unaligned 3 OK
+#255/p check skb->hash half load not permitted, unaligned 1 OK (NOTE: not executed due to unknown alignment)
+#256/p check skb->hash half load not permitted, unaligned 3 OK (NOTE: not executed due to unknown alignment)
#257/p check cb access: half, wrong type OK
#258/u check cb access: word OK
#258/p check cb access: word OK
@@ -454,20 +454,20 @@
#292/p pkt_end < pkt taken check OK (NOTE: not executed due to unknown alignment)
#293/p valid 1,2,4,8-byte reads from bpf_sk_lookup OK
#294/p invalid 8-byte read from bpf_sk_lookup family field OK
-#295/p invalid 8-byte read from bpf_sk_lookup protocol field OK
+#295/p invalid 8-byte read from bpf_sk_lookup protocol field OK (NOTE: not executed due to unknown alignment)
#296/p invalid 8-byte read from bpf_sk_lookup remote_ip4 field OK
-#297/p invalid 8-byte read from bpf_sk_lookup remote_ip6 field OK
-#298/p invalid 8-byte read from bpf_sk_lookup remote_port field OK
+#297/p invalid 8-byte read from bpf_sk_lookup remote_ip6 field OK (NOTE: not executed due to unknown alignment)
+#298/p invalid 8-byte read from bpf_sk_lookup remote_port field OK (NOTE: not executed due to unknown alignment)
#299/p invalid 8-byte read from bpf_sk_lookup local_ip4 field OK
-#300/p invalid 8-byte read from bpf_sk_lookup local_ip6 field OK
-#301/p invalid 8-byte read from bpf_sk_lookup local_port field OK
-#302/p invalid 8-byte read from bpf_sk_lookup ingress_ifindex field OK
+#300/p invalid 8-byte read from bpf_sk_lookup local_ip6 field OK (NOTE: not executed due to unknown alignment)
+#301/p invalid 8-byte read from bpf_sk_lookup local_port field OK (NOTE: not executed due to unknown alignment)
+#302/p invalid 8-byte read from bpf_sk_lookup ingress_ifindex field OK (NOTE: not executed due to unknown alignment)
#303/p invalid 4-byte read from bpf_sk_lookup sk field OK
#304/p invalid 2-byte read from bpf_sk_lookup sk field OK
#305/p invalid 1-byte read from bpf_sk_lookup sk field OK
#306/p invalid 4-byte read past end of bpf_sk_lookup OK
-#307/p invalid 4-byte unaligned read from bpf_sk_lookup at odd offset OK
-#308/p invalid 4-byte unaligned read from bpf_sk_lookup at even offset OK
+#307/p invalid 4-byte unaligned read from bpf_sk_lookup at odd offset OK (NOTE: not executed due to unknown alignment)
+#308/p invalid 4-byte unaligned read from bpf_sk_lookup at even offset OK (NOTE: not executed due to unknown alignment)
#309/p invalid 8-byte write to bpf_sk_lookup OK
#310/p invalid 4-byte write to bpf_sk_lookup OK
#311/p invalid 2-byte write to bpf_sk_lookup OK
@@ -507,7 +507,7 @@
#329/p direct map access, write test 4 OK
#330/u direct map access, write test 5 OK
#330/p direct map access, write test 5 OK
-#331/p direct map access, write test 6 OK
+#331/p direct map access, write test 6 OK (NOTE: not executed due to unknown alignment)
#332/u direct map access, write test 7 OK
#332/p direct map access, write test 7 OK
#333/u direct map access, write test 8 OK
@@ -526,8 +526,8 @@
#339/p direct map access, write test 14 OK
#340/u direct map access, write test 15 OK
#340/p direct map access, write test 15 OK
-#341/p direct map access, write test 16 OK
-#342/p direct map access, write test 17 OK
+#341/p direct map access, write test 16 OK (NOTE: not executed due to unknown alignment)
+#342/p direct map access, write test 17 OK (NOTE: not executed due to unknown alignment)
#343/u direct map access, write test 18 OK
#343/p direct map access, write test 18 OK
#344/u direct map access, write test 19 OK
@@ -723,9 +723,9 @@
#472/p test14 ld_imm64: reject 2nd imm != 0 OK
#473/p map_kptr: BPF_ST imm != 0 OK
#474/p map_kptr: size != bpf_size_to_bytes(BPF_DW) OK
-#475/p map_kptr: map_value non-const var_off OK
+#475/p map_kptr: map_value non-const var_off OK (NOTE: not executed due to unknown alignment)
#476/p map_kptr: bpf_kptr_xchg non-const var_off OK
-#477/p map_kptr: unaligned boundary load/store OK
+#477/p map_kptr: unaligned boundary load/store OK (NOTE: not executed due to unknown alignment)
#478/p map_kptr: reject var_off != 0 OK
#479/p map_kptr: unref: reject btf_struct_ids_match == false OK
#480/p map_kptr: unref: loaded pointer marked as untrusted OK
@@ -748,7 +748,7 @@
#497/p precise: cross frame pruning OK
#498/p precise: ST zero to stack insn is supported OK
#499/p precise: STX insn causing spi > allocated_stack OK
-#500/p precise: mark_chain_precision for ARG_CONST_ALLOC_SIZE_OR_ZERO OK
+#500/p precise: mark_chain_precision for ARG_CONST_ALLOC_SIZE_OR_ZERO OK (NOTE: not executed due to unknown alignment)
#501/p precise: program doesn't prematurely prune branches OK
#502/p scale: scale test 1 OK
#503/p scale: scale test 2 OK
@@ -760,19 +760,19 @@
#509/p sleepable uprobe accept OK
#510/p sleepable raw tracepoint reject OK
#511/p wide store to bpf_sock_addr.user_ip6[0] Did not run the program (not supported) OK
-#512/p wide store to bpf_sock_addr.user_ip6[1] OK
+#512/p wide store to bpf_sock_addr.user_ip6[1] OK (NOTE: not executed due to unknown alignment)
#513/p wide store to bpf_sock_addr.user_ip6[2] Did not run the program (not supported) OK
-#514/p wide store to bpf_sock_addr.user_ip6[3] OK
-#515/p wide store to bpf_sock_addr.msg_src_ip6[0] OK
+#514/p wide store to bpf_sock_addr.user_ip6[3] OK (NOTE: not executed due to unknown alignment)
+#515/p wide store to bpf_sock_addr.msg_src_ip6[0] OK (NOTE: not executed due to unknown alignment)
#516/p wide store to bpf_sock_addr.msg_src_ip6[1] Did not run the program (not supported) OK
-#517/p wide store to bpf_sock_addr.msg_src_ip6[2] OK
+#517/p wide store to bpf_sock_addr.msg_src_ip6[2] OK (NOTE: not executed due to unknown alignment)
#518/p wide store to bpf_sock_addr.msg_src_ip6[3] OK
#519/p wide load from bpf_sock_addr.user_ip6[0] Did not run the program (not supported) OK
-#520/p wide load from bpf_sock_addr.user_ip6[1] OK
+#520/p wide load from bpf_sock_addr.user_ip6[1] OK (NOTE: not executed due to unknown alignment)
#521/p wide load from bpf_sock_addr.user_ip6[2] Did not run the program (not supported) OK
-#522/p wide load from bpf_sock_addr.user_ip6[3] OK
-#523/p wide load from bpf_sock_addr.msg_src_ip6[0] OK
+#522/p wide load from bpf_sock_addr.user_ip6[3] OK (NOTE: not executed due to unknown alignment)
+#523/p wide load from bpf_sock_addr.msg_src_ip6[0] OK (NOTE: not executed due to unknown alignment)
#524/p wide load from bpf_sock_addr.msg_src_ip6[1] Did not run the program (not supported) OK
-#525/p wide load from bpf_sock_addr.msg_src_ip6[2] OK
+#525/p wide load from bpf_sock_addr.msg_src_ip6[2] OK (NOTE: not executed due to unknown alignment)
#526/p wide load from bpf_sock_addr.msg_src_ip6[3] OK
Summary: 777 PASSED, 0 SKIPPED, 0 FAILED

Thanks,
Tiezhu