1*006c0e44SFlorian Westphal // SPDX-License-Identifier: GPL-2.0
2*006c0e44SFlorian Westphal
3*006c0e44SFlorian Westphal #include "vmlinux.h"
4*006c0e44SFlorian Westphal
5*006c0e44SFlorian Westphal #include "bpf_misc.h"
6*006c0e44SFlorian Westphal
7*006c0e44SFlorian Westphal #include <bpf/bpf_endian.h>
8*006c0e44SFlorian Westphal #include <bpf/bpf_tracing.h>
9*006c0e44SFlorian Westphal #include <bpf/bpf_helpers.h>
10*006c0e44SFlorian Westphal
11*006c0e44SFlorian Westphal SEC("netfilter")
12*006c0e44SFlorian Westphal __description("netfilter invalid context access, size too short")
13*006c0e44SFlorian Westphal __failure __msg("invalid bpf_context access")
with_invalid_ctx_access_test1(void)14*006c0e44SFlorian Westphal __naked void with_invalid_ctx_access_test1(void)
15*006c0e44SFlorian Westphal {
16*006c0e44SFlorian Westphal asm volatile (" \
17*006c0e44SFlorian Westphal r2 = *(u8*)(r1 + %[__bpf_nf_ctx_state]); \
18*006c0e44SFlorian Westphal r0 = 0; \
19*006c0e44SFlorian Westphal exit; \
20*006c0e44SFlorian Westphal " :
21*006c0e44SFlorian Westphal : __imm_const(__bpf_nf_ctx_state, offsetof(struct bpf_nf_ctx, state))
22*006c0e44SFlorian Westphal : __clobber_all);
23*006c0e44SFlorian Westphal }
24*006c0e44SFlorian Westphal
25*006c0e44SFlorian Westphal SEC("netfilter")
26*006c0e44SFlorian Westphal __description("netfilter invalid context access, size too short")
27*006c0e44SFlorian Westphal __failure __msg("invalid bpf_context access")
with_invalid_ctx_access_test2(void)28*006c0e44SFlorian Westphal __naked void with_invalid_ctx_access_test2(void)
29*006c0e44SFlorian Westphal {
30*006c0e44SFlorian Westphal asm volatile (" \
31*006c0e44SFlorian Westphal r2 = *(u16*)(r1 + %[__bpf_nf_ctx_skb]); \
32*006c0e44SFlorian Westphal r0 = 0; \
33*006c0e44SFlorian Westphal exit; \
34*006c0e44SFlorian Westphal " :
35*006c0e44SFlorian Westphal : __imm_const(__bpf_nf_ctx_skb, offsetof(struct bpf_nf_ctx, skb))
36*006c0e44SFlorian Westphal : __clobber_all);
37*006c0e44SFlorian Westphal }
38*006c0e44SFlorian Westphal
39*006c0e44SFlorian Westphal SEC("netfilter")
40*006c0e44SFlorian Westphal __description("netfilter invalid context access, past end of ctx")
41*006c0e44SFlorian Westphal __failure __msg("invalid bpf_context access")
with_invalid_ctx_access_test3(void)42*006c0e44SFlorian Westphal __naked void with_invalid_ctx_access_test3(void)
43*006c0e44SFlorian Westphal {
44*006c0e44SFlorian Westphal asm volatile (" \
45*006c0e44SFlorian Westphal r2 = *(u64*)(r1 + %[__bpf_nf_ctx_size]); \
46*006c0e44SFlorian Westphal r0 = 0; \
47*006c0e44SFlorian Westphal exit; \
48*006c0e44SFlorian Westphal " :
49*006c0e44SFlorian Westphal : __imm_const(__bpf_nf_ctx_size, sizeof(struct bpf_nf_ctx))
50*006c0e44SFlorian Westphal : __clobber_all);
51*006c0e44SFlorian Westphal }
52*006c0e44SFlorian Westphal
53*006c0e44SFlorian Westphal SEC("netfilter")
54*006c0e44SFlorian Westphal __description("netfilter invalid context, write")
55*006c0e44SFlorian Westphal __failure __msg("invalid bpf_context access")
with_invalid_ctx_access_test4(void)56*006c0e44SFlorian Westphal __naked void with_invalid_ctx_access_test4(void)
57*006c0e44SFlorian Westphal {
58*006c0e44SFlorian Westphal asm volatile (" \
59*006c0e44SFlorian Westphal r2 = r1; \
60*006c0e44SFlorian Westphal *(u64*)(r2 + 0) = r1; \
61*006c0e44SFlorian Westphal r0 = 1; \
62*006c0e44SFlorian Westphal exit; \
63*006c0e44SFlorian Westphal " :
64*006c0e44SFlorian Westphal : __imm_const(__bpf_nf_ctx_skb, offsetof(struct bpf_nf_ctx, skb))
65*006c0e44SFlorian Westphal : __clobber_all);
66*006c0e44SFlorian Westphal }
67*006c0e44SFlorian Westphal
68*006c0e44SFlorian Westphal #define NF_DROP 0
69*006c0e44SFlorian Westphal #define NF_ACCEPT 1
70*006c0e44SFlorian Westphal
71*006c0e44SFlorian Westphal SEC("netfilter")
72*006c0e44SFlorian Westphal __description("netfilter valid context read and invalid write")
73*006c0e44SFlorian Westphal __failure __msg("only read is supported")
with_invalid_ctx_access_test5(struct bpf_nf_ctx * ctx)74*006c0e44SFlorian Westphal int with_invalid_ctx_access_test5(struct bpf_nf_ctx *ctx)
75*006c0e44SFlorian Westphal {
76*006c0e44SFlorian Westphal struct nf_hook_state *state = (void *)ctx->state;
77*006c0e44SFlorian Westphal
78*006c0e44SFlorian Westphal state->sk = NULL;
79*006c0e44SFlorian Westphal return NF_ACCEPT;
80*006c0e44SFlorian Westphal }
81*006c0e44SFlorian Westphal
82*006c0e44SFlorian Westphal extern int bpf_dynptr_from_skb(struct sk_buff *skb, __u64 flags,
83*006c0e44SFlorian Westphal struct bpf_dynptr *ptr__uninit) __ksym;
84*006c0e44SFlorian Westphal extern void *bpf_dynptr_slice(const struct bpf_dynptr *ptr, uint32_t offset,
85*006c0e44SFlorian Westphal void *buffer, uint32_t buffer__sz) __ksym;
86*006c0e44SFlorian Westphal
87*006c0e44SFlorian Westphal SEC("netfilter")
88*006c0e44SFlorian Westphal __description("netfilter test prog with skb and state read access")
89*006c0e44SFlorian Westphal __success __failure_unpriv
90*006c0e44SFlorian Westphal __retval(0)
with_valid_ctx_access_test6(struct bpf_nf_ctx * ctx)91*006c0e44SFlorian Westphal int with_valid_ctx_access_test6(struct bpf_nf_ctx *ctx)
92*006c0e44SFlorian Westphal {
93*006c0e44SFlorian Westphal const struct nf_hook_state *state = ctx->state;
94*006c0e44SFlorian Westphal struct sk_buff *skb = ctx->skb;
95*006c0e44SFlorian Westphal const struct iphdr *iph;
96*006c0e44SFlorian Westphal const struct tcphdr *th;
97*006c0e44SFlorian Westphal u8 buffer_iph[20] = {};
98*006c0e44SFlorian Westphal u8 buffer_th[40] = {};
99*006c0e44SFlorian Westphal struct bpf_dynptr ptr;
100*006c0e44SFlorian Westphal uint8_t ihl;
101*006c0e44SFlorian Westphal
102*006c0e44SFlorian Westphal if (skb->len <= 20 || bpf_dynptr_from_skb(skb, 0, &ptr))
103*006c0e44SFlorian Westphal return NF_ACCEPT;
104*006c0e44SFlorian Westphal
105*006c0e44SFlorian Westphal iph = bpf_dynptr_slice(&ptr, 0, buffer_iph, sizeof(buffer_iph));
106*006c0e44SFlorian Westphal if (!iph)
107*006c0e44SFlorian Westphal return NF_ACCEPT;
108*006c0e44SFlorian Westphal
109*006c0e44SFlorian Westphal if (state->pf != 2)
110*006c0e44SFlorian Westphal return NF_ACCEPT;
111*006c0e44SFlorian Westphal
112*006c0e44SFlorian Westphal ihl = iph->ihl << 2;
113*006c0e44SFlorian Westphal
114*006c0e44SFlorian Westphal th = bpf_dynptr_slice(&ptr, ihl, buffer_th, sizeof(buffer_th));
115*006c0e44SFlorian Westphal if (!th)
116*006c0e44SFlorian Westphal return NF_ACCEPT;
117*006c0e44SFlorian Westphal
118*006c0e44SFlorian Westphal return th->dest == bpf_htons(22) ? NF_ACCEPT : NF_DROP;
119*006c0e44SFlorian Westphal }
120*006c0e44SFlorian Westphal
121*006c0e44SFlorian Westphal char _license[] SEC("license") = "GPL";
122