summaryrefslogtreecommitdiff
path: root/tools/testing/selftests/bpf
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2026-09-03 08:58:45 +0200
committerAlexei Starovoitov <ast@kernel.org>2026-09-03 21:41:58 -0700
commit254c881fe0554c5efb16d355c273702a27a32a20 (patch)
tree7974537ee435b63250363a62553c140490acb76e /tools/testing/selftests/bpf
parent0237317ffc70ae9d643161d176999b6283920fe4 (diff)
downloadlinux-next-254c881fe0554c5efb16d355c273702a27a32a20.tar.gz
linux-next-254c881fe0554c5efb16d355c273702a27a32a20.zip
selftests/bpf: Add tests to assert that netfilter progs cannot write to skb
The netfilter framework is allergic to ip header changing after validation done by ip/ipv6 stack. Assert that bpf netfilter programs do not allow skb write access. Following additional tests are expected to be rejected by verifier: 1. alter skb->len. 2. alter skb->data. 3. prog calls bpf_dynptr_slice_rdwr. 4. alter location returned by dynptr API. Add following test case for bpf runtime: - alter skb data via bpf_dynptr_write() Test checks via __retval() that bpf_dynptr_write() returned nonzero value. Signed-off-by: Florian Westphal <fw@strlen.de> Reviewed-by: Jiayuan Chen <jiayuan.chen@linux.dev> Link: https://lore.kernel.org/r/20260903065845.22762-1-fw@strlen.de Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Diffstat (limited to 'tools/testing/selftests/bpf')
-rw-r--r--tools/testing/selftests/bpf/progs/verifier_netfilter_ctx.c78
1 files changed, 78 insertions, 0 deletions
diff --git a/tools/testing/selftests/bpf/progs/verifier_netfilter_ctx.c b/tools/testing/selftests/bpf/progs/verifier_netfilter_ctx.c
index e2cbc5bda65e..b5d7f567d0d4 100644
--- a/tools/testing/selftests/bpf/progs/verifier_netfilter_ctx.c
+++ b/tools/testing/selftests/bpf/progs/verifier_netfilter_ctx.c
@@ -113,4 +113,82 @@ int with_valid_ctx_access_test6(struct bpf_nf_ctx *ctx)
return th->dest == bpf_htons(22) ? NF_ACCEPT : NF_DROP;
}
+SEC("netfilter")
+__description("netfilter test prog with skb write access")
+__failure __msg("only read is supported")
+int skb_len_write(struct bpf_nf_ctx *ctx)
+{
+ ctx->skb->len = 1;
+ return 1;
+}
+
+SEC("netfilter")
+__description("netfilter test prog with skb data write access")
+__failure __msg("cannot write into rdonly_untrusted_mem")
+int skb_data_write(struct bpf_nf_ctx *ctx)
+{
+ ctx->skb->data[0] = 0;
+ return 1;
+}
+
+SEC("netfilter")
+__description("netfilter test prog with bpf_dynptr_write")
+__success __failure_unpriv
+__retval(0)
+int with_dynptr_write(struct bpf_nf_ctx *ctx)
+{
+ struct __sk_buff *skb = (struct __sk_buff *)ctx->skb;
+ struct bpf_dynptr ptr;
+ u8 buffer[1] = {};
+
+ if (bpf_dynptr_from_skb(skb, 0, &ptr))
+ return 1;
+
+ if (bpf_dynptr_write(&ptr, 0, buffer, sizeof(buffer), 0))
+ return 0; /* must always fail */
+
+ return 1;
+}
+
+SEC("netfilter")
+__description("netfilter test prog with bpf_dynptr_slice_rdwr")
+__failure __msg("the prog does not allow writes to packet data")
+int with_dynptr_rdwr(struct bpf_nf_ctx *ctx)
+{
+ struct __sk_buff *skb = (struct __sk_buff *)ctx->skb;
+ u8 buffer_iph[20] = {};
+ struct bpf_dynptr ptr;
+ struct iphdr *iph;
+
+ if (bpf_dynptr_from_skb(skb, 0, &ptr))
+ return 1;
+
+ iph = bpf_dynptr_slice_rdwr(&ptr, 0, buffer_iph, sizeof(buffer_iph));
+ if (!iph)
+ return 0;
+
+ return 1;
+}
+
+SEC("netfilter")
+__description("netfilter test prog with bpf_dynptr_slice + write")
+__failure __msg("cannot write into rdonly_mem")
+int with_dynptr_store(struct bpf_nf_ctx *ctx)
+{
+ struct __sk_buff *skb = (struct __sk_buff *)ctx->skb;
+ u8 buffer_iph[20] = {};
+ struct bpf_dynptr ptr;
+ struct iphdr *iph;
+
+ if (bpf_dynptr_from_skb(skb, 0, &ptr))
+ return 1;
+
+ iph = bpf_dynptr_slice(&ptr, 0, buffer_iph, sizeof(buffer_iph));
+ if (!iph)
+ return 0;
+ iph->protocol = 42;
+
+ return 1;
+}
+
char _license[] SEC("license") = "GPL";