1 // SPDX-License-Identifier: GPL-2.0 2 3 #include <linux/bpf.h> 4 #include <bpf/bpf_helpers.h> 5 #include "bpf_misc.h" 6 7 struct { 8 __uint(type, BPF_MAP_TYPE_ARRAY); 9 __uint(max_entries, 8); 10 __type(key, __u32); 11 __type(value, __u64); 12 } map SEC(".maps"); 13 14 struct { 15 __uint(type, BPF_MAP_TYPE_USER_RINGBUF); 16 __uint(max_entries, 8); 17 } ringbuf SEC(".maps"); 18 19 struct vm_area_struct; 20 struct bpf_map; 21 22 struct buf_context { 23 char *buf; 24 }; 25 26 struct num_context { 27 __u64 i; 28 __u64 j; 29 }; 30 31 __u8 choice_arr[2] = { 0, 1 }; 32 33 static int unsafe_on_2nd_iter_cb(__u32 idx, struct buf_context *ctx) 34 { 35 if (idx == 0) { 36 ctx->buf = (char *)(0xDEAD); 37 return 0; 38 } 39 40 if (bpf_probe_read_user(ctx->buf, 8, (void *)(0xBADC0FFEE))) 41 return 1; 42 43 return 0; 44 } 45 46 SEC("?raw_tp") 47 __failure __msg("R1 type=scalar expected=fp") 48 int unsafe_on_2nd_iter(void *unused) 49 { 50 char buf[4]; 51 struct buf_context loop_ctx = { .buf = buf }; 52 53 bpf_loop(100, unsafe_on_2nd_iter_cb, &loop_ctx, 0); 54 return 0; 55 } 56 57 static int unsafe_on_zero_iter_cb(__u32 idx, struct num_context *ctx) 58 { 59 ctx->i = 0; 60 return 0; 61 } 62 63 SEC("?raw_tp") 64 __failure __msg("invalid access to map value, value_size=2 off=32 size=1") 65 int unsafe_on_zero_iter(void *unused) 66 { 67 struct num_context loop_ctx = { .i = 32 }; 68 69 bpf_loop(100, unsafe_on_zero_iter_cb, &loop_ctx, 0); 70 return choice_arr[loop_ctx.i]; 71 } 72 73 static int widening_cb(__u32 idx, struct num_context *ctx) 74 { 75 ++ctx->i; 76 return 0; 77 } 78 79 SEC("?raw_tp") 80 __success 81 int widening(void *unused) 82 { 83 struct num_context loop_ctx = { .i = 0, .j = 1 }; 84 85 bpf_loop(100, widening_cb, &loop_ctx, 0); 86 /* loop_ctx.j is not changed during callback iteration, 87 * verifier should not apply widening to it. 88 */ 89 return choice_arr[loop_ctx.j]; 90 } 91 92 static int loop_detection_cb(__u32 idx, struct num_context *ctx) 93 { 94 for (;;) {} 95 return 0; 96 } 97 98 SEC("?raw_tp") 99 __failure __msg("infinite loop detected") 100 int loop_detection(void *unused) 101 { 102 struct num_context loop_ctx = { .i = 0 }; 103 104 bpf_loop(100, loop_detection_cb, &loop_ctx, 0); 105 return 0; 106 } 107 108 static __always_inline __u64 oob_state_machine(struct num_context *ctx) 109 { 110 switch (ctx->i) { 111 case 0: 112 ctx->i = 1; 113 break; 114 case 1: 115 ctx->i = 32; 116 break; 117 } 118 return 0; 119 } 120 121 static __u64 for_each_map_elem_cb(struct bpf_map *map, __u32 *key, __u64 *val, void *data) 122 { 123 return oob_state_machine(data); 124 } 125 126 SEC("?raw_tp") 127 __failure __msg("invalid access to map value, value_size=2 off=32 size=1") 128 int unsafe_for_each_map_elem(void *unused) 129 { 130 struct num_context loop_ctx = { .i = 0 }; 131 132 bpf_for_each_map_elem(&map, for_each_map_elem_cb, &loop_ctx, 0); 133 return choice_arr[loop_ctx.i]; 134 } 135 136 static __u64 ringbuf_drain_cb(struct bpf_dynptr *dynptr, void *data) 137 { 138 return oob_state_machine(data); 139 } 140 141 SEC("?raw_tp") 142 __failure __msg("invalid access to map value, value_size=2 off=32 size=1") 143 int unsafe_ringbuf_drain(void *unused) 144 { 145 struct num_context loop_ctx = { .i = 0 }; 146 147 bpf_user_ringbuf_drain(&ringbuf, ringbuf_drain_cb, &loop_ctx, 0); 148 return choice_arr[loop_ctx.i]; 149 } 150 151 static __u64 find_vma_cb(struct task_struct *task, struct vm_area_struct *vma, void *data) 152 { 153 return oob_state_machine(data); 154 } 155 156 SEC("?raw_tp") 157 __failure __msg("invalid access to map value, value_size=2 off=32 size=1") 158 int unsafe_find_vma(void *unused) 159 { 160 struct task_struct *task = bpf_get_current_task_btf(); 161 struct num_context loop_ctx = { .i = 0 }; 162 163 bpf_find_vma(task, 0, find_vma_cb, &loop_ctx, 0); 164 return choice_arr[loop_ctx.i]; 165 } 166 167 static int iter_limit_cb(__u32 idx, struct num_context *ctx) 168 { 169 ctx->i++; 170 return 0; 171 } 172 173 SEC("?raw_tp") 174 __success 175 int bpf_loop_iter_limit_ok(void *unused) 176 { 177 struct num_context ctx = { .i = 0 }; 178 179 bpf_loop(1, iter_limit_cb, &ctx, 0); 180 return choice_arr[ctx.i]; 181 } 182 183 SEC("?raw_tp") 184 __failure __msg("invalid access to map value, value_size=2 off=2 size=1") 185 int bpf_loop_iter_limit_overflow(void *unused) 186 { 187 struct num_context ctx = { .i = 0 }; 188 189 bpf_loop(2, iter_limit_cb, &ctx, 0); 190 return choice_arr[ctx.i]; 191 } 192 193 static int iter_limit_level2a_cb(__u32 idx, struct num_context *ctx) 194 { 195 ctx->i += 100; 196 return 0; 197 } 198 199 static int iter_limit_level2b_cb(__u32 idx, struct num_context *ctx) 200 { 201 ctx->i += 10; 202 return 0; 203 } 204 205 static int iter_limit_level1_cb(__u32 idx, struct num_context *ctx) 206 { 207 ctx->i += 1; 208 bpf_loop(1, iter_limit_level2a_cb, ctx, 0); 209 bpf_loop(1, iter_limit_level2b_cb, ctx, 0); 210 return 0; 211 } 212 213 /* Check that path visiting every callback function once had been 214 * reached by verifier. Variables 'ctx{1,2}i' below serve as flags, 215 * with each decimal digit corresponding to a callback visit marker. 216 */ 217 SEC("socket") 218 __success __retval(111111) 219 int bpf_loop_iter_limit_nested(void *unused) 220 { 221 struct num_context ctx1 = { .i = 0 }; 222 struct num_context ctx2 = { .i = 0 }; 223 __u64 a, b, c; 224 225 bpf_loop(1, iter_limit_level1_cb, &ctx1, 0); 226 bpf_loop(1, iter_limit_level1_cb, &ctx2, 0); 227 a = ctx1.i; 228 b = ctx2.i; 229 /* Force 'ctx1.i' and 'ctx2.i' precise. */ 230 c = choice_arr[(a + b) % 2]; 231 /* This makes 'c' zero, but neither clang nor verifier know it. */ 232 c /= 10; 233 /* Make sure that verifier does not visit 'impossible' states: 234 * enumerate all possible callback visit masks. 235 */ 236 if (a != 0 && a != 1 && a != 11 && a != 101 && a != 111 && 237 b != 0 && b != 1 && b != 11 && b != 101 && b != 111) 238 asm volatile ("r0 /= 0;" ::: "r0"); 239 return 1000 * a + b + c; 240 } 241 242 char _license[] SEC("license") = "GPL"; 243