1 // SPDX-License-Identifier: GPL-2.0 2 #include <vmlinux.h> 3 #include <bpf/bpf_tracing.h> 4 #include <bpf/bpf_helpers.h> 5 #include <bpf/bpf_core_read.h> 6 #include "bpf_misc.h" 7 8 struct map_value { 9 char buf[8]; 10 struct prog_test_ref_kfunc __kptr_untrusted *unref_ptr; 11 struct prog_test_ref_kfunc __kptr *ref_ptr; 12 struct prog_test_member __kptr *ref_memb_ptr; 13 }; 14 15 struct array_map { 16 __uint(type, BPF_MAP_TYPE_ARRAY); 17 __type(key, int); 18 __type(value, struct map_value); 19 __uint(max_entries, 1); 20 } array_map SEC(".maps"); 21 22 extern struct prog_test_ref_kfunc *bpf_kfunc_call_test_acquire(unsigned long *sp) __ksym; 23 extern void bpf_kfunc_call_test_release(struct prog_test_ref_kfunc *p) __ksym; 24 extern struct prog_test_ref_kfunc * 25 bpf_kfunc_call_test_kptr_get(struct prog_test_ref_kfunc **p, int a, int b) __ksym; 26 27 SEC("?tc") 28 __failure __msg("kptr access size must be BPF_DW") 29 int size_not_bpf_dw(struct __sk_buff *ctx) 30 { 31 struct map_value *v; 32 int key = 0; 33 34 v = bpf_map_lookup_elem(&array_map, &key); 35 if (!v) 36 return 0; 37 38 *(u32 *)&v->unref_ptr = 0; 39 return 0; 40 } 41 42 SEC("?tc") 43 __failure __msg("kptr access cannot have variable offset") 44 int non_const_var_off(struct __sk_buff *ctx) 45 { 46 struct map_value *v; 47 int key = 0, id; 48 49 v = bpf_map_lookup_elem(&array_map, &key); 50 if (!v) 51 return 0; 52 53 id = ctx->protocol; 54 if (id < 4 || id > 12) 55 return 0; 56 *(u64 *)((void *)v + id) = 0; 57 58 return 0; 59 } 60 61 SEC("?tc") 62 __failure __msg("R1 doesn't have constant offset. kptr has to be") 63 int non_const_var_off_kptr_xchg(struct __sk_buff *ctx) 64 { 65 struct map_value *v; 66 int key = 0, id; 67 68 v = bpf_map_lookup_elem(&array_map, &key); 69 if (!v) 70 return 0; 71 72 id = ctx->protocol; 73 if (id < 4 || id > 12) 74 return 0; 75 bpf_kptr_xchg((void *)v + id, NULL); 76 77 return 0; 78 } 79 80 SEC("?tc") 81 __failure __msg("kptr access misaligned expected=8 off=7") 82 int misaligned_access_write(struct __sk_buff *ctx) 83 { 84 struct map_value *v; 85 int key = 0; 86 87 v = bpf_map_lookup_elem(&array_map, &key); 88 if (!v) 89 return 0; 90 91 *(void **)((void *)v + 7) = NULL; 92 93 return 0; 94 } 95 96 SEC("?tc") 97 __failure __msg("kptr access misaligned expected=8 off=1") 98 int misaligned_access_read(struct __sk_buff *ctx) 99 { 100 struct map_value *v; 101 int key = 0; 102 103 v = bpf_map_lookup_elem(&array_map, &key); 104 if (!v) 105 return 0; 106 107 return *(u64 *)((void *)v + 1); 108 } 109 110 SEC("?tc") 111 __failure __msg("variable untrusted_ptr_ access var_off=(0x0; 0x1e0)") 112 int reject_var_off_store(struct __sk_buff *ctx) 113 { 114 struct prog_test_ref_kfunc *unref_ptr; 115 struct map_value *v; 116 int key = 0, id; 117 118 v = bpf_map_lookup_elem(&array_map, &key); 119 if (!v) 120 return 0; 121 122 unref_ptr = v->unref_ptr; 123 if (!unref_ptr) 124 return 0; 125 id = ctx->protocol; 126 if (id < 4 || id > 12) 127 return 0; 128 unref_ptr += id; 129 v->unref_ptr = unref_ptr; 130 131 return 0; 132 } 133 134 SEC("?tc") 135 __failure __msg("invalid kptr access, R1 type=untrusted_ptr_prog_test_ref_kfunc") 136 int reject_bad_type_match(struct __sk_buff *ctx) 137 { 138 struct prog_test_ref_kfunc *unref_ptr; 139 struct map_value *v; 140 int key = 0; 141 142 v = bpf_map_lookup_elem(&array_map, &key); 143 if (!v) 144 return 0; 145 146 unref_ptr = v->unref_ptr; 147 if (!unref_ptr) 148 return 0; 149 unref_ptr = (void *)unref_ptr + 4; 150 v->unref_ptr = unref_ptr; 151 152 return 0; 153 } 154 155 SEC("?tc") 156 __failure __msg("R1 type=untrusted_ptr_or_null_ expected=percpu_ptr_") 157 int marked_as_untrusted_or_null(struct __sk_buff *ctx) 158 { 159 struct map_value *v; 160 int key = 0; 161 162 v = bpf_map_lookup_elem(&array_map, &key); 163 if (!v) 164 return 0; 165 166 bpf_this_cpu_ptr(v->unref_ptr); 167 return 0; 168 } 169 170 SEC("?tc") 171 __failure __msg("access beyond struct prog_test_ref_kfunc at off 32 size 4") 172 int correct_btf_id_check_size(struct __sk_buff *ctx) 173 { 174 struct prog_test_ref_kfunc *p; 175 struct map_value *v; 176 int key = 0; 177 178 v = bpf_map_lookup_elem(&array_map, &key); 179 if (!v) 180 return 0; 181 182 p = v->unref_ptr; 183 if (!p) 184 return 0; 185 return *(int *)((void *)p + bpf_core_type_size(struct prog_test_ref_kfunc)); 186 } 187 188 SEC("?tc") 189 __failure __msg("R1 type=untrusted_ptr_ expected=percpu_ptr_") 190 int inherit_untrusted_on_walk(struct __sk_buff *ctx) 191 { 192 struct prog_test_ref_kfunc *unref_ptr; 193 struct map_value *v; 194 int key = 0; 195 196 v = bpf_map_lookup_elem(&array_map, &key); 197 if (!v) 198 return 0; 199 200 unref_ptr = v->unref_ptr; 201 if (!unref_ptr) 202 return 0; 203 unref_ptr = unref_ptr->next; 204 bpf_this_cpu_ptr(unref_ptr); 205 return 0; 206 } 207 208 SEC("?tc") 209 __failure __msg("off=8 kptr isn't referenced kptr") 210 int reject_kptr_xchg_on_unref(struct __sk_buff *ctx) 211 { 212 struct map_value *v; 213 int key = 0; 214 215 v = bpf_map_lookup_elem(&array_map, &key); 216 if (!v) 217 return 0; 218 219 bpf_kptr_xchg(&v->unref_ptr, NULL); 220 return 0; 221 } 222 223 SEC("?tc") 224 __failure __msg("arg#0 expected pointer to map value") 225 int reject_kptr_get_no_map_val(struct __sk_buff *ctx) 226 { 227 bpf_kfunc_call_test_kptr_get((void *)&ctx, 0, 0); 228 return 0; 229 } 230 231 SEC("?tc") 232 __failure __msg("arg#0 expected pointer to map value") 233 int reject_kptr_get_no_null_map_val(struct __sk_buff *ctx) 234 { 235 bpf_kfunc_call_test_kptr_get(bpf_map_lookup_elem(&array_map, &(int){0}), 0, 0); 236 return 0; 237 } 238 239 SEC("?tc") 240 __failure __msg("arg#0 no referenced kptr at map value offset=0") 241 int reject_kptr_get_no_kptr(struct __sk_buff *ctx) 242 { 243 struct map_value *v; 244 int key = 0; 245 246 v = bpf_map_lookup_elem(&array_map, &key); 247 if (!v) 248 return 0; 249 250 bpf_kfunc_call_test_kptr_get((void *)v, 0, 0); 251 return 0; 252 } 253 254 SEC("?tc") 255 __failure __msg("arg#0 no referenced kptr at map value offset=8") 256 int reject_kptr_get_on_unref(struct __sk_buff *ctx) 257 { 258 struct map_value *v; 259 int key = 0; 260 261 v = bpf_map_lookup_elem(&array_map, &key); 262 if (!v) 263 return 0; 264 265 bpf_kfunc_call_test_kptr_get(&v->unref_ptr, 0, 0); 266 return 0; 267 } 268 269 SEC("?tc") 270 __failure __msg("kernel function bpf_kfunc_call_test_kptr_get args#0") 271 int reject_kptr_get_bad_type_match(struct __sk_buff *ctx) 272 { 273 struct map_value *v; 274 int key = 0; 275 276 v = bpf_map_lookup_elem(&array_map, &key); 277 if (!v) 278 return 0; 279 280 bpf_kfunc_call_test_kptr_get((void *)&v->ref_memb_ptr, 0, 0); 281 return 0; 282 } 283 284 SEC("?tc") 285 __failure __msg("R1 type=rcu_ptr_or_null_ expected=percpu_ptr_") 286 int mark_ref_as_untrusted_or_null(struct __sk_buff *ctx) 287 { 288 struct map_value *v; 289 int key = 0; 290 291 v = bpf_map_lookup_elem(&array_map, &key); 292 if (!v) 293 return 0; 294 295 bpf_this_cpu_ptr(v->ref_ptr); 296 return 0; 297 } 298 299 SEC("?tc") 300 __failure __msg("store to referenced kptr disallowed") 301 int reject_untrusted_store_to_ref(struct __sk_buff *ctx) 302 { 303 struct prog_test_ref_kfunc *p; 304 struct map_value *v; 305 int key = 0; 306 307 v = bpf_map_lookup_elem(&array_map, &key); 308 if (!v) 309 return 0; 310 311 p = v->ref_ptr; 312 if (!p) 313 return 0; 314 /* Checkmate, clang */ 315 *(struct prog_test_ref_kfunc * volatile *)&v->ref_ptr = p; 316 return 0; 317 } 318 319 SEC("?tc") 320 __failure __msg("R2 must be referenced") 321 int reject_untrusted_xchg(struct __sk_buff *ctx) 322 { 323 struct prog_test_ref_kfunc *p; 324 struct map_value *v; 325 int key = 0; 326 327 v = bpf_map_lookup_elem(&array_map, &key); 328 if (!v) 329 return 0; 330 331 p = v->ref_ptr; 332 if (!p) 333 return 0; 334 bpf_kptr_xchg(&v->ref_ptr, p); 335 return 0; 336 } 337 338 SEC("?tc") 339 __failure 340 __msg("invalid kptr access, R2 type=ptr_prog_test_ref_kfunc expected=ptr_prog_test_member") 341 int reject_bad_type_xchg(struct __sk_buff *ctx) 342 { 343 struct prog_test_ref_kfunc *ref_ptr; 344 struct map_value *v; 345 int key = 0; 346 347 v = bpf_map_lookup_elem(&array_map, &key); 348 if (!v) 349 return 0; 350 351 ref_ptr = bpf_kfunc_call_test_acquire(&(unsigned long){0}); 352 if (!ref_ptr) 353 return 0; 354 bpf_kptr_xchg(&v->ref_memb_ptr, ref_ptr); 355 return 0; 356 } 357 358 SEC("?tc") 359 __failure __msg("invalid kptr access, R2 type=ptr_prog_test_ref_kfunc") 360 int reject_member_of_ref_xchg(struct __sk_buff *ctx) 361 { 362 struct prog_test_ref_kfunc *ref_ptr; 363 struct map_value *v; 364 int key = 0; 365 366 v = bpf_map_lookup_elem(&array_map, &key); 367 if (!v) 368 return 0; 369 370 ref_ptr = bpf_kfunc_call_test_acquire(&(unsigned long){0}); 371 if (!ref_ptr) 372 return 0; 373 bpf_kptr_xchg(&v->ref_memb_ptr, &ref_ptr->memb); 374 return 0; 375 } 376 377 SEC("?syscall") 378 __failure __msg("kptr cannot be accessed indirectly by helper") 379 int reject_indirect_helper_access(struct __sk_buff *ctx) 380 { 381 struct map_value *v; 382 int key = 0; 383 384 v = bpf_map_lookup_elem(&array_map, &key); 385 if (!v) 386 return 0; 387 388 bpf_get_current_comm(v, sizeof(v->buf) + 1); 389 return 0; 390 } 391 392 __noinline 393 int write_func(int *p) 394 { 395 return p ? *p = 42 : 0; 396 } 397 398 SEC("?tc") 399 __failure __msg("kptr cannot be accessed indirectly by helper") 400 int reject_indirect_global_func_access(struct __sk_buff *ctx) 401 { 402 struct map_value *v; 403 int key = 0; 404 405 v = bpf_map_lookup_elem(&array_map, &key); 406 if (!v) 407 return 0; 408 409 return write_func((void *)v + 5); 410 } 411 412 SEC("?tc") 413 __failure __msg("Unreleased reference id=5 alloc_insn=") 414 int kptr_xchg_ref_state(struct __sk_buff *ctx) 415 { 416 struct prog_test_ref_kfunc *p; 417 struct map_value *v; 418 int key = 0; 419 420 v = bpf_map_lookup_elem(&array_map, &key); 421 if (!v) 422 return 0; 423 424 p = bpf_kfunc_call_test_acquire(&(unsigned long){0}); 425 if (!p) 426 return 0; 427 bpf_kptr_xchg(&v->ref_ptr, p); 428 return 0; 429 } 430 431 SEC("?tc") 432 __failure __msg("Unreleased reference id=3 alloc_insn=") 433 int kptr_get_ref_state(struct __sk_buff *ctx) 434 { 435 struct map_value *v; 436 int key = 0; 437 438 v = bpf_map_lookup_elem(&array_map, &key); 439 if (!v) 440 return 0; 441 442 bpf_kfunc_call_test_kptr_get(&v->ref_ptr, 0, 0); 443 return 0; 444 } 445 446 SEC("?tc") 447 __failure __msg("Possibly NULL pointer passed to helper arg2") 448 int kptr_xchg_possibly_null(struct __sk_buff *ctx) 449 { 450 struct prog_test_ref_kfunc *p; 451 struct map_value *v; 452 int key = 0; 453 454 v = bpf_map_lookup_elem(&array_map, &key); 455 if (!v) 456 return 0; 457 458 p = bpf_kfunc_call_test_acquire(&(unsigned long){0}); 459 460 /* PTR_TO_BTF_ID | PTR_MAYBE_NULL passed to bpf_kptr_xchg() */ 461 p = bpf_kptr_xchg(&v->ref_ptr, p); 462 if (p) 463 bpf_kfunc_call_test_release(p); 464 465 return 0; 466 } 467 468 char _license[] SEC("license") = "GPL"; 469