Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v6.4-rc2 390 lines 7.8 kB view raw
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 8struct 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 15struct 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 22extern struct prog_test_ref_kfunc *bpf_kfunc_call_test_acquire(unsigned long *sp) __ksym; 23extern void bpf_kfunc_call_test_release(struct prog_test_ref_kfunc *p) __ksym; 24 25SEC("?tc") 26__failure __msg("kptr access size must be BPF_DW") 27int 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 40SEC("?tc") 41__failure __msg("kptr access cannot have variable offset") 42int 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 59SEC("?tc") 60__failure __msg("R1 doesn't have constant offset. kptr has to be") 61int 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 78SEC("?tc") 79__failure __msg("kptr access misaligned expected=8 off=7") 80int 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 94SEC("?tc") 95__failure __msg("kptr access misaligned expected=8 off=1") 96int 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 108SEC("?tc") 109__failure __msg("variable untrusted_ptr_ access var_off=(0x0; 0x1e0)") 110int 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 132SEC("?tc") 133__failure __msg("invalid kptr access, R1 type=untrusted_ptr_prog_test_ref_kfunc") 134int 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 153SEC("?tc") 154__failure __msg("R1 type=untrusted_ptr_or_null_ expected=percpu_ptr_") 155int 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 168SEC("?tc") 169__failure __msg("access beyond struct prog_test_ref_kfunc at off 32 size 4") 170int 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 186SEC("?tc") 187__failure __msg("R1 type=untrusted_ptr_ expected=percpu_ptr_") 188int 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 206SEC("?tc") 207__failure __msg("off=8 kptr isn't referenced kptr") 208int 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 221SEC("?tc") 222__failure __msg("R1 type=rcu_ptr_or_null_ expected=percpu_ptr_") 223int 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 236SEC("?tc") 237__failure __msg("store to referenced kptr disallowed") 238int 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 256SEC("?tc") 257__failure __msg("R2 must be referenced") 258int 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 275SEC("?tc") 276__failure 277__msg("invalid kptr access, R2 type=ptr_prog_test_ref_kfunc expected=ptr_prog_test_member") 278int 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 295SEC("?tc") 296__failure __msg("invalid kptr access, R2 type=ptr_prog_test_ref_kfunc") 297int 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 314SEC("?syscall") 315__failure __msg("kptr cannot be accessed indirectly by helper") 316int 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 330int write_func(int *p) 331{ 332 return p ? *p = 42 : 0; 333} 334 335SEC("?tc") 336__failure __msg("kptr cannot be accessed indirectly by helper") 337int 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 349SEC("?tc") 350__failure __msg("Unreleased reference id=5 alloc_insn=") 351int 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 368SEC("?tc") 369__failure __msg("Possibly NULL pointer passed to helper arg2") 370int 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 390char _license[] SEC("license") = "GPL";