From: Luxiao Xu Add negative verifier tests in dynptr_fail.c to verify that: - Passing an skb-backed dynptr slice to bpf_lwt_push_encap() is rejected. - Passing an skb-backed dynptr slice to bpf_skb_store_bytes() (with constant and variable length) is rejected. - Passing an skb-backed dynptr slice to bpf_dynptr_write() is rejected. - Passing a packet-backed dynptr to a mutating global subprogram is rejected. Assisted-by: LLM Signed-off-by: Luxiao Xu Signed-off-by: Ren Wei --- v1 -> v2: - v1 Link: https://lore.kernel.org/all/cover.1791433504.git.rakukuip@gmail.com/ - New patch in v2 series adding negative verifier tests in dynptr_fail.c (Alexei Starovoitov). .../testing/selftests/bpf/progs/dynptr_fail.c | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/tools/testing/selftests/bpf/progs/dynptr_fail.c b/tools/testing/selftests/bpf/progs/dynptr_fail.c index c2247b38c849..11699d87ad2b 100644 --- a/tools/testing/selftests/bpf/progs/dynptr_fail.c +++ b/tools/testing/selftests/bpf/progs/dynptr_fail.c @@ -2279,3 +2279,93 @@ int dynptr_overwrite_ref_clone_slice_valid(void *ctx) return 0; } + +/* Passing a packet dynptr slice to helper changing packet data should fail */ +SEC("?lwt_out") +__failure __msg("cannot pass packet pointer") +int slice_pkt_to_lwt_push_encap(struct __sk_buff *skb) +{ + struct bpf_dynptr ptr; + void *hdr; + + bpf_dynptr_from_skb(skb, 0, &ptr); + hdr = bpf_dynptr_slice(&ptr, 0, NULL, 20); + if (!hdr) + return 1; + + bpf_lwt_push_encap(skb, 0, hdr, 20); + return 0; +} + +/* Passing a packet dynptr slice to bpf_skb_store_bytes should fail */ +SEC("?tc") +__failure __msg("cannot pass packet pointer") +int slice_pkt_to_skb_store_bytes(struct __sk_buff *skb) +{ + struct bpf_dynptr ptr; + void *from; + + bpf_dynptr_from_skb(skb, 0, &ptr); + from = bpf_dynptr_slice(&ptr, 0, NULL, 10); + if (!from) + return 1; + + bpf_skb_store_bytes(skb, 0, from, 10, 0); + return 0; +} + +/* Passing a packet dynptr slice to bpf_dynptr_write should fail */ +SEC("?tc") +__failure __msg("cannot pass packet pointer") +int slice_pkt_to_dynptr_write(struct __sk_buff *skb) +{ + struct bpf_dynptr ptr; + void *from; + + bpf_dynptr_from_skb(skb, 0, &ptr); + from = bpf_dynptr_slice(&ptr, 0, NULL, 10); + if (!from) + return 1; + + bpf_dynptr_write(&ptr, 0, from, 10, 0); + return 0; +} + +__noinline int mutating_global_subprog(struct bpf_dynptr *ptr) +{ + char buf[4] = {0}; + + return bpf_dynptr_write(ptr, 0, buf, sizeof(buf), 0); +} + +/* Passing a packet dynptr to a mutating global subprog should fail */ +SEC("?tc") +__failure __msg("cannot pass packet dynptr") +int packet_dynptr_to_mutating_subprog(struct __sk_buff *skb) +{ + struct bpf_dynptr ptr; + + bpf_dynptr_from_skb(skb, 0, &ptr); + return mutating_global_subprog(&ptr); +} + +/* Passing a packet dynptr slice with variable length to bpf_skb_store_bytes should fail */ +SEC("?tc") +__failure __msg("cannot pass packet pointer") +int slice_pkt_to_skb_store_bytes_var_len(struct __sk_buff *skb) +{ + struct bpf_dynptr ptr; + __u32 len = skb->len; + void *from; + + if (len > 10) + len = 10; + + bpf_dynptr_from_skb(skb, 0, &ptr); + from = bpf_dynptr_slice(&ptr, 0, NULL, 10); + if (!from) + return 1; + + bpf_skb_store_bytes(skb, 0, from, len, 0); + return 0; +} -- 2.43.0