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