mirror of
https://github.com/torvalds/linux.git
synced 2026-09-12 20:53:03 +02:00
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>
This commit is contained in:
parent
0237317ffc
commit
254c881fe0
|
|
@ -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";
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user