Repository navigation
bpf: the verifier gives the result of Linux for test_verifier - #701
Merged
Merged
Conversation
Add state pruning, the back edge rules of Linux with CAP_BPF, the bounds after BPF_JSET and BPF_JMP32, the alignment and context access rules, and BPF_PROG_TEST_RUN. The kselftest boot test runs bpf/test_verifier: 281 passed and 0 failed for the program types of #537.
This was referenced Nov 12, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #537 (the verifier item).
This finishes the first part of the eBPF verifier for the program types of #537. For each program of bpf/test_verifier of the types
SOCKET_FILTER,CGROUP_SKB,CGROUP_SOCK,CGROUP_SOCK_ADDRandCGROUP_DEVICE, rukernel now accepts or refuses the program as kernel/bpf/verifier.c of Linux does, with the same verifier message. The kselftest boot test now builds and runs test_verifier.Changes
core/rk-bpf/src/verifier.rs:is_state_visitedof Linux. At each prune point (the jump targets and the instructions after a jump or a call), the verifier keeps the states that it saw. A path with a state that is equal to a saved state stops. An equal state on the current path is a loop that does not end, and gives "infinite loop detected at insn N" (EINVAL).CAP_BPF,check_cfgallows back edges, as in Linux. A loop that changes its state goes on to the limit of 1000000 instructions. A function that calls itself makes frames until "the call stack of 9 frames is too deep" (E2BIG).BPF_JSETrefines the bounds of the register, and aBPF_JMP32compare of a register with a 64-bit value that fits in 32 bits refines the bounds as a 64-bit compare.BPF_F_STRICT_ALIGNMENTand for the atomic instructions, the size and offset rules of each context field (skb_is_valid_access,sock_addr_is_valid_access, with the wide access of the IPv6 fields), and the bounds of map values with the messages ofcheck_mem_region_access.check_alu_op,check_regnoandBPF_LD_IMM64is as in Linux, so that each refused program gives the first message of Linux.core/rk-bpf/src/test_run.rs,syscall.rs,uapi.rs,attr.rs:BPF_PROG_TEST_RUN, as net/bpf/test_run.c. A socket filter and aCGROUP_SKBprogram run on a packet from user space that comes in on the loopback device, withrepeat,ctx_inandctx_out. The other program types giveENOTSUPP(524, new incore/rk-abi/src/errno.rs). test_verifier uses this command to run each program that the verifier accepts.core/rk-bpf/src/prog.rs: the fieldststamp,gso_segs,gso_sizeandhwtstampofstruct __sk_buff.tools/kselftest/build.sh: builds bpf/test_verifier of Linux v6.17 with a static libbpf. It skips the program types that R5 eBPF: the interpreter, maps and cgroup programs #537 does not cover, with the messageSKIP (program type N), and it runs without bpf_testmod.ko.tools/kselftest/bpf.md: the result of test_verifier and the reasons for each skip.tests/user/init.c: the checks "the verifier refuses a loop" and "the verifier refuses recursion" now expect the result of Linux withCAP_BPF: "infinite loop detected at insn 10" withEINVAL, and "the call stack of 9 frames is too deep" withE2BIG.Tests
cargo test -p rk-bpf -p rk-abion server2: 80 and 7 passed. New tests:jset_and_jmp32_refine_the_bounds,the_order_of_the_errors_is_as_in_linux,a_socket_filter_runs_on_the_packet_after_the_ethernet_header,the_errors_of_a_test_run,the_context_of_a_test_run.cargo clippy -p rk-bpf -p rk-syscall -p rk-abi --all-targetson server2: no new warnings.rustfmt --edition 2024 --checkis clean on the changed Rust files. Load average of server2: 14.6 to 18.5.kselftestboot test with bpf/test_verifier, built on server2 and run on server1:Summary: 281 PASSED, 510 SKIPPED, 0 FAILED. Before this change, 259 passed and 22 failed. tools/kselftest/bpf.md gives the skips. Load average of server1: 2.6 to 3.3.ltpboot test with the bpf tests, run on server1: exit 33. bpf_map01 and bpf_prog01 to bpf_prog04 pass. bpf_prog05, bpf_prog06 and bpf_prog07 give TCONF, as on Linux withkernel.unprivileged_bpf_disabled=2, because they dropCAP_BPF. Load average of server1: 0.18 to 0.44.cargo xtask boot-test initwithRK_CMDLINE="-- only bpf", run on server1: exit 33, "init: each check passed", 94 checks ok. Load average of server1: 0.03 to 0.11.RK_AARCH64_TESTS=init cargo xtask boot-test aarch64withRK_CMDLINE="-- only bpf"on server2: pass, "init: each check passed", 94 checks ok. Load average of server2: 5.4 to 5.7.The full gate did not run.