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