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 25 SEC("?tc") 26 __failure __msg("kptr access size must be BPF_DW") 27 int size_not_bpf_dw(struct __sk_buff *ctx) 28 { 29 struct map_value *v; 30 int key = 0; 31 32 v = bpf_map_lookup_elem(&array_map, &key); 33 if (!v) 34 return 0; 35 36 *(u32 *)&v->unref_ptr = 0; 37 return 0; 38 } 39 40 SEC("?tc") 41 __failure __msg("kptr access cannot have variable offset") 42 int non_const_var_off(struct __sk_buff *ctx) 43 { 44 struct map_value *v; 45 int key = 0, id; 46 47 v = bpf_map_lookup_elem(&array_map, &key); 48 if (!v) 49 return 0; 50 51 id = ctx->protocol; 52 if (id < 4 || id > 12) 53 return 0; 54 *(u64 *)((void *)v + id) = 0; 55 56 return 0; 57 } 58 59 SEC("?tc") 60 __failure __msg("R1 doesn't have constant offset. kptr has to be") 61 int non_const_var_off_kptr_xchg(struct __sk_buff *ctx) 62 { 63 struct map_value *v; 64 int key = 0, id; 65 66 v = bpf_map_lookup_elem(&array_map, &key); 67 if (!v) 68 return 0; 69 70 id = ctx->protocol; 71 if (id < 4 || id > 12) 72 return 0; 73 bpf_kptr_xchg((void *)v + id, NULL); 74 75 return 0; 76 } 77 78 SEC("?tc") 79 __failure __msg("kptr access misaligned expected=8 off=7") 80 int misaligned_access_write(struct __sk_buff *ctx) 81 { 82 struct map_value *v; 83 int key = 0; 84 85 v = bpf_map_lookup_elem(&array_map, &key); 86 if (!v) 87 return 0; 88 89 *(void **)((void *)v + 7) = NULL; 90 91 return 0; 92 } 93 94 SEC("?tc") 95 __failure __msg("kptr access misaligned expected=8 off=1") 96 int misaligned_access_read(struct __sk_buff *ctx) 97 { 98 struct map_value *v; 99 int key = 0; 100 101 v = bpf_map_lookup_elem(&array_map, &key); 102 if (!v) 103 return 0; 104 105 return *(u64 *)((void *)v + 1); 106 } 107 108 SEC("?tc") 109 __failure __msg("variable untrusted_ptr_ access var_off=(0x0; 0x1e0)") 110 int reject_var_off_store(struct __sk_buff *ctx) 111 { 112 struct prog_test_ref_kfunc *unref_ptr; 113 struct map_value *v; 114 int key = 0, id; 115 116 v = bpf_map_lookup_elem(&array_map, &key); 117 if (!v) 118 return 0; 119 120 unref_ptr = v->unref_ptr; 121 if (!unref_ptr) 122 return 0; 123 id = ctx->protocol; 124 if (id < 4 || id > 12) 125 return 0; 126 unref_ptr += id; 127 v->unref_ptr = unref_ptr; 128 129 return 0; 130 } 131 132 SEC("?tc") 133 __failure __msg("invalid kptr access, R1 type=untrusted_ptr_prog_test_ref_kfunc") 134 int reject_bad_type_match(struct __sk_buff *ctx) 135 { 136 struct prog_test_ref_kfunc *unref_ptr; 137 struct map_value *v; 138 int key = 0; 139 140 v = bpf_map_lookup_elem(&array_map, &key); 141 if (!v) 142 return 0; 143 144 unref_ptr = v->unref_ptr; 145 if (!unref_ptr) 146 return 0; 147 unref_ptr = (void *)unref_ptr + 4; 148 v->unref_ptr = unref_ptr; 149 150 return 0; 151 } 152 153 SEC("?tc") 154 __failure __msg("R1 type=untrusted_ptr_or_null_ expected=percpu_ptr_") 155 int marked_as_untrusted_or_null(struct __sk_buff *ctx) 156 { 157 struct map_value *v; 158 int key = 0; 159 160 v = bpf_map_lookup_elem(&array_map, &key); 161 if (!v) 162 return 0; 163 164 bpf_this_cpu_ptr(v->unref_ptr); 165 return 0; 166 } 167 168 SEC("?tc") 169 __failure __msg("access beyond struct prog_test_ref_kfunc at off 32 size 4") 170 int correct_btf_id_check_size(struct __sk_buff *ctx) 171 { 172 struct prog_test_ref_kfunc *p; 173 struct map_value *v; 174 int key = 0; 175 176 v = bpf_map_lookup_elem(&array_map, &key); 177 if (!v) 178 return 0; 179 180 p = v->unref_ptr; 181 if (!p) 182 return 0; 183 return *(int *)((void *)p + bpf_core_type_size(struct prog_test_ref_kfunc)); 184 } 185 186 SEC("?tc") 187 __failure __msg("R1 type=untrusted_ptr_ expected=percpu_ptr_") 188 int inherit_untrusted_on_walk(struct __sk_buff *ctx) 189 { 190 struct prog_test_ref_kfunc *unref_ptr; 191 struct map_value *v; 192 int key = 0; 193 194 v = bpf_map_lookup_elem(&array_map, &key); 195 if (!v) 196 return 0; 197 198 unref_ptr = v->unref_ptr; 199 if (!unref_ptr) 200 return 0; 201 unref_ptr = unref_ptr->next; 202 bpf_this_cpu_ptr(unref_ptr); 203 return 0; 204 } 205 206 SEC("?tc") 207 __failure __msg("off=8 kptr isn't referenced kptr") 208 int reject_kptr_xchg_on_unref(struct __sk_buff *ctx) 209 { 210 struct map_value *v; 211 int key = 0; 212 213 v = bpf_map_lookup_elem(&array_map, &key); 214 if (!v) 215 return 0; 216 217 bpf_kptr_xchg(&v->unref_ptr, NULL); 218 return 0; 219 } 220 221 SEC("?tc") 222 __failure __msg("R1 type=rcu_ptr_or_null_ expected=percpu_ptr_") 223 int mark_ref_as_untrusted_or_null(struct __sk_buff *ctx) 224 { 225 struct map_value *v; 226 int key = 0; 227 228 v = bpf_map_lookup_elem(&array_map, &key); 229 if (!v) 230 return 0; 231 232 bpf_this_cpu_ptr(v->ref_ptr); 233 return 0; 234 } 235 236 SEC("?tc") 237 __failure __msg("store to referenced kptr disallowed") 238 int reject_untrusted_store_to_ref(struct __sk_buff *ctx) 239 { 240 struct prog_test_ref_kfunc *p; 241 struct map_value *v; 242 int key = 0; 243 244 v = bpf_map_lookup_elem(&array_map, &key); 245 if (!v) 246 return 0; 247 248 p = v->ref_ptr; 249 if (!p) 250 return 0; 251 /* Checkmate, clang */ 252 *(struct prog_test_ref_kfunc * volatile *)&v->ref_ptr = p; 253 return 0; 254 } 255 256 SEC("?tc") 257 __failure __msg("R2 must be referenced") 258 int reject_untrusted_xchg(struct __sk_buff *ctx) 259 { 260 struct prog_test_ref_kfunc *p; 261 struct map_value *v; 262 int key = 0; 263 264 v = bpf_map_lookup_elem(&array_map, &key); 265 if (!v) 266 return 0; 267 268 p = v->ref_ptr; 269 if (!p) 270 return 0; 271 bpf_kptr_xchg(&v->ref_ptr, p); 272 return 0; 273 } 274 275 SEC("?tc") 276 __failure 277 __msg("invalid kptr access, R2 type=ptr_prog_test_ref_kfunc expected=ptr_prog_test_member") 278 int reject_bad_type_xchg(struct __sk_buff *ctx) 279 { 280 struct prog_test_ref_kfunc *ref_ptr; 281 struct map_value *v; 282 int key = 0; 283 284 v = bpf_map_lookup_elem(&array_map, &key); 285 if (!v) 286 return 0; 287 288 ref_ptr = bpf_kfunc_call_test_acquire(&(unsigned long){0}); 289 if (!ref_ptr) 290 return 0; 291 bpf_kptr_xchg(&v->ref_memb_ptr, ref_ptr); 292 return 0; 293 } 294 295 SEC("?tc") 296 __failure __msg("invalid kptr access, R2 type=ptr_prog_test_ref_kfunc") 297 int reject_member_of_ref_xchg(struct __sk_buff *ctx) 298 { 299 struct prog_test_ref_kfunc *ref_ptr; 300 struct map_value *v; 301 int key = 0; 302 303 v = bpf_map_lookup_elem(&array_map, &key); 304 if (!v) 305 return 0; 306 307 ref_ptr = bpf_kfunc_call_test_acquire(&(unsigned long){0}); 308 if (!ref_ptr) 309 return 0; 310 bpf_kptr_xchg(&v->ref_memb_ptr, &ref_ptr->memb); 311 return 0; 312 } 313 314 SEC("?syscall") 315 __failure __msg("kptr cannot be accessed indirectly by helper") 316 int reject_indirect_helper_access(struct __sk_buff *ctx) 317 { 318 struct map_value *v; 319 int key = 0; 320 321 v = bpf_map_lookup_elem(&array_map, &key); 322 if (!v) 323 return 0; 324 325 bpf_get_current_comm(v, sizeof(v->buf) + 1); 326 return 0; 327 } 328 329 __noinline 330 int write_func(int *p) 331 { 332 return p ? *p = 42 : 0; 333 } 334 335 SEC("?tc") 336 __failure __msg("kptr cannot be accessed indirectly by helper") 337 int reject_indirect_global_func_access(struct __sk_buff *ctx) 338 { 339 struct map_value *v; 340 int key = 0; 341 342 v = bpf_map_lookup_elem(&array_map, &key); 343 if (!v) 344 return 0; 345 346 return write_func((void *)v + 5); 347 } 348 349 SEC("?tc") 350 __failure __msg("Unreleased reference id=5 alloc_insn=") 351 int kptr_xchg_ref_state(struct __sk_buff *ctx) 352 { 353 struct prog_test_ref_kfunc *p; 354 struct map_value *v; 355 int key = 0; 356 357 v = bpf_map_lookup_elem(&array_map, &key); 358 if (!v) 359 return 0; 360 361 p = bpf_kfunc_call_test_acquire(&(unsigned long){0}); 362 if (!p) 363 return 0; 364 bpf_kptr_xchg(&v->ref_ptr, p); 365 return 0; 366 } 367 368 SEC("?tc") 369 __failure __msg("Possibly NULL pointer passed to helper arg2") 370 int kptr_xchg_possibly_null(struct __sk_buff *ctx) 371 { 372 struct prog_test_ref_kfunc *p; 373 struct map_value *v; 374 int key = 0; 375 376 v = bpf_map_lookup_elem(&array_map, &key); 377 if (!v) 378 return 0; 379 380 p = bpf_kfunc_call_test_acquire(&(unsigned long){0}); 381 382 /* PTR_TO_BTF_ID | PTR_MAYBE_NULL passed to bpf_kptr_xchg() */ 383 p = bpf_kptr_xchg(&v->ref_ptr, p); 384 if (p) 385 bpf_kfunc_call_test_release(p); 386 387 return 0; 388 } 389 390 char _license[] SEC("license") = "GPL"; 391