1*6b99fe48SEduard Zingerman // SPDX-License-Identifier: GPL-2.0
2*6b99fe48SEduard Zingerman 
3*6b99fe48SEduard Zingerman #include <linux/bpf.h>
4*6b99fe48SEduard Zingerman #include <bpf/bpf_helpers.h>
5*6b99fe48SEduard Zingerman #include "bpf_misc.h"
6*6b99fe48SEduard Zingerman 
7*6b99fe48SEduard Zingerman struct {
8*6b99fe48SEduard Zingerman 	__uint(type, BPF_MAP_TYPE_ARRAY);
9*6b99fe48SEduard Zingerman 	__uint(max_entries, 8);
10*6b99fe48SEduard Zingerman 	__type(key, __u32);
11*6b99fe48SEduard Zingerman 	__type(value, __u64);
12*6b99fe48SEduard Zingerman } map SEC(".maps");
13*6b99fe48SEduard Zingerman 
14*6b99fe48SEduard Zingerman struct {
15*6b99fe48SEduard Zingerman 	__uint(type, BPF_MAP_TYPE_USER_RINGBUF);
16*6b99fe48SEduard Zingerman 	__uint(max_entries, 8);
17*6b99fe48SEduard Zingerman } ringbuf SEC(".maps");
18*6b99fe48SEduard Zingerman 
19*6b99fe48SEduard Zingerman struct vm_area_struct;
20*6b99fe48SEduard Zingerman struct bpf_map;
21*6b99fe48SEduard Zingerman 
22*6b99fe48SEduard Zingerman struct buf_context {
23*6b99fe48SEduard Zingerman 	char *buf;
24*6b99fe48SEduard Zingerman };
25*6b99fe48SEduard Zingerman 
26*6b99fe48SEduard Zingerman struct num_context {
27*6b99fe48SEduard Zingerman 	__u64 i;
28*6b99fe48SEduard Zingerman };
29*6b99fe48SEduard Zingerman 
30*6b99fe48SEduard Zingerman __u8 choice_arr[2] = { 0, 1 };
31*6b99fe48SEduard Zingerman 
32*6b99fe48SEduard Zingerman static int unsafe_on_2nd_iter_cb(__u32 idx, struct buf_context *ctx)
33*6b99fe48SEduard Zingerman {
34*6b99fe48SEduard Zingerman 	if (idx == 0) {
35*6b99fe48SEduard Zingerman 		ctx->buf = (char *)(0xDEAD);
36*6b99fe48SEduard Zingerman 		return 0;
37*6b99fe48SEduard Zingerman 	}
38*6b99fe48SEduard Zingerman 
39*6b99fe48SEduard Zingerman 	if (bpf_probe_read_user(ctx->buf, 8, (void *)(0xBADC0FFEE)))
40*6b99fe48SEduard Zingerman 		return 1;
41*6b99fe48SEduard Zingerman 
42*6b99fe48SEduard Zingerman 	return 0;
43*6b99fe48SEduard Zingerman }
44*6b99fe48SEduard Zingerman 
45*6b99fe48SEduard Zingerman SEC("?raw_tp")
46*6b99fe48SEduard Zingerman __failure __msg("R1 type=scalar expected=fp")
47*6b99fe48SEduard Zingerman int unsafe_on_2nd_iter(void *unused)
48*6b99fe48SEduard Zingerman {
49*6b99fe48SEduard Zingerman 	char buf[4];
50*6b99fe48SEduard Zingerman 	struct buf_context loop_ctx = { .buf = buf };
51*6b99fe48SEduard Zingerman 
52*6b99fe48SEduard Zingerman 	bpf_loop(100, unsafe_on_2nd_iter_cb, &loop_ctx, 0);
53*6b99fe48SEduard Zingerman 	return 0;
54*6b99fe48SEduard Zingerman }
55*6b99fe48SEduard Zingerman 
56*6b99fe48SEduard Zingerman static int unsafe_on_zero_iter_cb(__u32 idx, struct num_context *ctx)
57*6b99fe48SEduard Zingerman {
58*6b99fe48SEduard Zingerman 	ctx->i = 0;
59*6b99fe48SEduard Zingerman 	return 0;
60*6b99fe48SEduard Zingerman }
61*6b99fe48SEduard Zingerman 
62*6b99fe48SEduard Zingerman SEC("?raw_tp")
63*6b99fe48SEduard Zingerman __failure __msg("invalid access to map value, value_size=2 off=32 size=1")
64*6b99fe48SEduard Zingerman int unsafe_on_zero_iter(void *unused)
65*6b99fe48SEduard Zingerman {
66*6b99fe48SEduard Zingerman 	struct num_context loop_ctx = { .i = 32 };
67*6b99fe48SEduard Zingerman 
68*6b99fe48SEduard Zingerman 	bpf_loop(100, unsafe_on_zero_iter_cb, &loop_ctx, 0);
69*6b99fe48SEduard Zingerman 	return choice_arr[loop_ctx.i];
70*6b99fe48SEduard Zingerman }
71*6b99fe48SEduard Zingerman 
72*6b99fe48SEduard Zingerman static int loop_detection_cb(__u32 idx, struct num_context *ctx)
73*6b99fe48SEduard Zingerman {
74*6b99fe48SEduard Zingerman 	for (;;) {}
75*6b99fe48SEduard Zingerman 	return 0;
76*6b99fe48SEduard Zingerman }
77*6b99fe48SEduard Zingerman 
78*6b99fe48SEduard Zingerman SEC("?raw_tp")
79*6b99fe48SEduard Zingerman __failure __msg("infinite loop detected")
80*6b99fe48SEduard Zingerman int loop_detection(void *unused)
81*6b99fe48SEduard Zingerman {
82*6b99fe48SEduard Zingerman 	struct num_context loop_ctx = { .i = 0 };
83*6b99fe48SEduard Zingerman 
84*6b99fe48SEduard Zingerman 	bpf_loop(100, loop_detection_cb, &loop_ctx, 0);
85*6b99fe48SEduard Zingerman 	return 0;
86*6b99fe48SEduard Zingerman }
87*6b99fe48SEduard Zingerman 
88*6b99fe48SEduard Zingerman static __always_inline __u64 oob_state_machine(struct num_context *ctx)
89*6b99fe48SEduard Zingerman {
90*6b99fe48SEduard Zingerman 	switch (ctx->i) {
91*6b99fe48SEduard Zingerman 	case 0:
92*6b99fe48SEduard Zingerman 		ctx->i = 1;
93*6b99fe48SEduard Zingerman 		break;
94*6b99fe48SEduard Zingerman 	case 1:
95*6b99fe48SEduard Zingerman 		ctx->i = 32;
96*6b99fe48SEduard Zingerman 		break;
97*6b99fe48SEduard Zingerman 	}
98*6b99fe48SEduard Zingerman 	return 0;
99*6b99fe48SEduard Zingerman }
100*6b99fe48SEduard Zingerman 
101*6b99fe48SEduard Zingerman static __u64 for_each_map_elem_cb(struct bpf_map *map, __u32 *key, __u64 *val, void *data)
102*6b99fe48SEduard Zingerman {
103*6b99fe48SEduard Zingerman 	return oob_state_machine(data);
104*6b99fe48SEduard Zingerman }
105*6b99fe48SEduard Zingerman 
106*6b99fe48SEduard Zingerman SEC("?raw_tp")
107*6b99fe48SEduard Zingerman __failure __msg("invalid access to map value, value_size=2 off=32 size=1")
108*6b99fe48SEduard Zingerman int unsafe_for_each_map_elem(void *unused)
109*6b99fe48SEduard Zingerman {
110*6b99fe48SEduard Zingerman 	struct num_context loop_ctx = { .i = 0 };
111*6b99fe48SEduard Zingerman 
112*6b99fe48SEduard Zingerman 	bpf_for_each_map_elem(&map, for_each_map_elem_cb, &loop_ctx, 0);
113*6b99fe48SEduard Zingerman 	return choice_arr[loop_ctx.i];
114*6b99fe48SEduard Zingerman }
115*6b99fe48SEduard Zingerman 
116*6b99fe48SEduard Zingerman static __u64 ringbuf_drain_cb(struct bpf_dynptr *dynptr, void *data)
117*6b99fe48SEduard Zingerman {
118*6b99fe48SEduard Zingerman 	return oob_state_machine(data);
119*6b99fe48SEduard Zingerman }
120*6b99fe48SEduard Zingerman 
121*6b99fe48SEduard Zingerman SEC("?raw_tp")
122*6b99fe48SEduard Zingerman __failure __msg("invalid access to map value, value_size=2 off=32 size=1")
123*6b99fe48SEduard Zingerman int unsafe_ringbuf_drain(void *unused)
124*6b99fe48SEduard Zingerman {
125*6b99fe48SEduard Zingerman 	struct num_context loop_ctx = { .i = 0 };
126*6b99fe48SEduard Zingerman 
127*6b99fe48SEduard Zingerman 	bpf_user_ringbuf_drain(&ringbuf, ringbuf_drain_cb, &loop_ctx, 0);
128*6b99fe48SEduard Zingerman 	return choice_arr[loop_ctx.i];
129*6b99fe48SEduard Zingerman }
130*6b99fe48SEduard Zingerman 
131*6b99fe48SEduard Zingerman static __u64 find_vma_cb(struct task_struct *task, struct vm_area_struct *vma, void *data)
132*6b99fe48SEduard Zingerman {
133*6b99fe48SEduard Zingerman 	return oob_state_machine(data);
134*6b99fe48SEduard Zingerman }
135*6b99fe48SEduard Zingerman 
136*6b99fe48SEduard Zingerman SEC("?raw_tp")
137*6b99fe48SEduard Zingerman __failure __msg("invalid access to map value, value_size=2 off=32 size=1")
138*6b99fe48SEduard Zingerman int unsafe_find_vma(void *unused)
139*6b99fe48SEduard Zingerman {
140*6b99fe48SEduard Zingerman 	struct task_struct *task = bpf_get_current_task_btf();
141*6b99fe48SEduard Zingerman 	struct num_context loop_ctx = { .i = 0 };
142*6b99fe48SEduard Zingerman 
143*6b99fe48SEduard Zingerman 	bpf_find_vma(task, 0, find_vma_cb, &loop_ctx, 0);
144*6b99fe48SEduard Zingerman 	return choice_arr[loop_ctx.i];
145*6b99fe48SEduard Zingerman }
146*6b99fe48SEduard Zingerman 
147*6b99fe48SEduard Zingerman char _license[] SEC("license") = "GPL";
148