Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'Allocated objects, BPF linked lists'

Kumar Kartikeya Dwivedi says:

====================

This series introduces user defined BPF objects of a type in program
BTF. This allows BPF programs to allocate their own objects, build their
own object hierarchies, and use the basic building blocks provided by
BPF runtime to build their own data structures flexibly.

Then, we introduce the support for single ownership BPF linked lists,
which can be put inside BPF maps, or allocated objects, and hold such
allocated objects as elements. It works as an instrusive collection,
which is done to allow making allocated objects part of multiple data
structures at the same time in the future.

The eventual goal of this and future patches is to allow one to do some
limited form of kernel style programming in BPF C, and allow programmers
to build their own complex data structures flexibly out of basic
building blocks.

The key difference will be that such programs are verified to be safe,
preserve runtime integrity of the system, and are proven to be bug free
as far as the invariants of BPF specific APIs are concerned.

One immediate use case that will be using the entire infrastructure this
series is introducing will be managing percpu NMI safe linked lists
inside BPF programs.

The other use case this will serve in the near future will be linking
kernel structures like XDP frame and sk_buff directly into user data
structures (rbtree, pifomap, etc.) for packet queueing. This will follow
single ownership concept included in this series.

The user has complete control of the internal locking, and hence also
the batching of operations for each critical section.

The features are:
- Allocated objects.
- bpf_obj_new, bpf_obj_drop to allocate and free them.
- Single ownership BPF linked lists.
- Support for them in BPF maps.
- Support for them in allocated objects.
- Global spin locks.
- Spin locks inside allocated objects.

Some other notable things:
- Completely static verification of locking.
- Kfunc argument handling has been completely reworked.
- Argument rewriting support for kfuncs.
- A new bpf_experimental.h header as a dumping ground for these APIs.

Any functionality exposed in this series is NOT part of UAPI. It is only
available through use of kfuncs, and structs that can be added to map
value may also change their size or name in the future. Hence, every
feature in this series must be considered experimental.

Follow-ups:
-----------
* Support for kptrs (local and kernel) in local storage and percpu maps + kptr tests
* Fixes for helper access checks rebasing on top of this series

Next steps:
-----------
* NMI safe percpu single ownership linked lists (using local_t protection).
* Lockless linked lists.
* Allow RCU protected BPF allocated objects. This then allows RCU
protected list lookups, since spinlock protection for readers does
not scale.
* Introduce bpf_refcount for local kptrs, shared ownership.
* Introduce shared ownership linked lists.
* Documentation.

Changelog:
----------
v9 -> v10
v9: https://lore.kernel.org/bpf/20221117225510.1676785-1-memxor@gmail.com

* Deduplicate code to find btf_record of reg (Alexei)
* Add linked_list test to DENYLIST.aarch64 (Alexei)
* Disable some linked list tests for now so that they compile with
clang nightly (Alexei)

v8 -> v9
v8: https://lore.kernel.org/bpf/20221117162430.1213770-1-memxor@gmail.com

* Fix up commit log of patch 2, Simplify patch 3
* Explain the implicit requirement of bpf_list_head requiring map BTF
to match in btf_record_equal in a separate patch.

v7 -> v8
v7: https://lore.kernel.org/bpf/20221114191547.1694267-1-memxor@gmail.com

* Fix early return in map_check_btf (Dan Carpenter)
* Fix two memory leak bugs in local storage maps, outer maps
* Address comments from Alexei and Dave
* More local kptr -> allocated object renaming
* Use krealloc with NULL instead kmalloc + krealloc
* Drop WARN_ON_ONCE for field_offs parsing
* Combine kfunc add + remove patches into one
* Drop STRONG suffix from KF_ARG_PTR_TO_KPTR
* Rename is_kfunc_arg_ret_buf_size to is_kfunc_arg_scalar_with_name
* Remove redundant check for reg->type and arg type in it
* Drop void * ret type check
* Remove code duplication in checks for NULL pointer with offset != 0
* Fix two bpf_list_node typos
* Improve log message for bpf_list_head operations
* Improve comments for active_lock struct
* Improve comments for Implementation details of process_spin_lock
* Add Dave's acks

v6 -> v7
v6: https://lore.kernel.org/bpf/20221111193224.876706-1-memxor@gmail.com

* Fix uninitialized variable warning (Dan Carpenter, Kernel Test Robot)
* One more local_kptr renaming

v5 -> v6
v5: https://lore.kernel.org/bpf/20221107230950.7117-1-memxor@gmail.com

* Replace (i && !off) check with next_off, include test (Andrii)
* Drop local kptrs naming (Andrii, Alexei)
* Drop reg->precise == EXACT patch (Andrii)
* Add comment about ptr member of struct active_lock (Andrii)
* Use btf__new_empty + btf__add_xxx APIs (Andrii)
* Address other misc nits from Andrii

v4 -> v5
v4: https://lore.kernel.org/bpf/20221103191013.1236066-1-memxor@gmail.com

* Add a lot more selftests (failure, success, runtime, BTF)
* Make sure series is bisect friendly
* Move list draining out of spin lock
* This exposed an issue where bpf_mem_free can now be called in
map_free path without migrate_disable, also fixed that.
* Rename MEM_ALLOC -> MEM_RINGBUF, MEM_TYPE_LOCAL -> MEM_ALLOC (Alexei)
* Group lock identity into a struct active_lock { ptr, id } (Dave)
* Split set_release_on_unlock logic into separate patch (Alexei)

v3 -> v4
v3: https://lore.kernel.org/bpf/20221102202658.963008-1-memxor@gmail.com

* Fix compiler error for !CONFIG_BPF_SYSCALL (Kernel Test Robot)
* Fix error due to BUILD_BUG_ON on 32-bit platforms (Kernel Test Robot)

v2 -> v3
v2: https://lore.kernel.org/bpf/20221013062303.896469-1-memxor@gmail.com

* Add ack from Dave for patch 5
* Rename btf_type_fields -> btf_record, btf_type_fields_off ->
btf_field_offs, rename functions similarly (Alexei)
* Remove 'kind' component from contains declaration tag (Alexei)
* Move bpf_list_head, bpf_list_node definitions to UAPI bpf.h (Alexei)
* Add note in commit log about modifying btf_struct_access API (Dave)
* Downgrade WARN_ON_ONCE to verbose(env, "...") and return -EFAULT (Dave)
* Add type_is_local_kptr wrapper to avoid noisy checks (Dave)
* Remove unused flags parameter from bpf_kptr_new (Alexei)
* Rename bpf_kptr_new -> bpf_obj_new, bpf_kptr_drop -> bpf_obj_drop (Alexei)
* Reword comment in ref_obj_id_set_release_on_unlock (Dave)
* Fix return type of ref_obj_id_set_release_on_unlock (Dave)
* Introduce is_bpf_list_api_kfunc to dedup checks (Dave)
* Disallow BPF_WRITE to untrusted local kptrs
* Add details about soundness of check_reg_allocation_locked logic
* List untrusted local kptrs for PROBE_MEM handling

v1 -> v2
v1: https://lore.kernel.org/bpf/20221011012240.3149-1-memxor@gmail.com

* Rebase on bpf-next to resolve merge conflict in DENYLIST.s390x
* Fix a couple of mental lapses in bpf_list_head_free

RFC v1 -> v1
RFC v1: https://lore.kernel.org/bpf/20220904204145.3089-1-memxor@gmail.com

* Mostly a complete rewrite of BTF parsing, refactor existing code (Kartikeya)
* Rebase kfunc rewrite for bpf-next, add support for more changes
* Cache type metadata in BTF to avoid recomputation inside verifier (Kartikeya)
* Remove __kernel tag, make things similar to map values, reserve bpf_ prefix
* bpf_kptr_new, bpf_kptr_drop
* Rename precision state enum values (Alexei)
* Drop explicit constructor/destructor support (Alexei)
* Rewrite code for constructing/destructing objects and offload to runtime
* Minimize duplication in bpf_map_value_off_desc handling (Alexei)
* Expose global memory allocator (Alexei)
* Address other nits from Alexei
* Split out local kptrs in maps, more kptrs in maps support into a follow up

Links:
------
* Dave's BPF RB-Tree RFC series
v1 (Discussion thread)
https://lore.kernel.org/bpf/20220722183438.3319790-1-davemarchevsky@fb.com
v2 (With support for static locks)
https://lore.kernel.org/bpf/20220830172759.4069786-1-davemarchevsky@fb.com
* BPF Linked Lists Discussion
https://lore.kernel.org/bpf/CAP01T74U30+yeBHEgmgzTJ-XYxZ0zj71kqCDJtTH9YQNfTK+Xw@mail.gmail.com
* BPF Memory Allocator from Alexei
https://lore.kernel.org/bpf/20220902211058.60789-1-alexei.starovoitov@gmail.com
* BPF Memory Allocator UAPI Discussion
https://lore.kernel.org/bpf/d3f76b27f4e55ec9e400ae8dcaecbb702a4932e8.camel@fb.com
====================

Signed-off-by: Alexei Starovoitov <ast@kernel.org>

+3931 -567
+24
Documentation/bpf/kfuncs.rst
··· 72 72 of the pointer is used. Without __sz annotation, a kfunc cannot accept a void 73 73 pointer. 74 74 75 + 2.2.2 __k Annotation 76 + -------------------- 77 + 78 + This annotation is only understood for scalar arguments, where it indicates that 79 + the verifier must check the scalar argument to be a known constant, which does 80 + not indicate a size parameter, and the value of the constant is relevant to the 81 + safety of the program. 82 + 83 + An example is given below:: 84 + 85 + void *bpf_obj_new(u32 local_type_id__k, ...) 86 + { 87 + ... 88 + } 89 + 90 + Here, bpf_obj_new uses local_type_id argument to find out the size of that type 91 + ID in program's BTF and return a sized pointer to it. Each type ID will have a 92 + distinct size, hence it is crucial to treat each such call as distinct when 93 + values don't match during verifier state pruning checks. 94 + 95 + Hence, whenever a constant scalar argument is accepted by a kfunc which is not a 96 + size parameter, and the value of the constant matters for program safety, __k 97 + suffix should be used. 98 + 75 99 .. _BPF_kfunc_nodef: 76 100 77 101 2.3 Using an existing kernel function
+32 -19
include/linux/bpf.h
··· 54 54 extern struct idr btf_idr; 55 55 extern spinlock_t btf_idr_lock; 56 56 extern struct kobject *btf_kobj; 57 + extern struct bpf_mem_alloc bpf_global_ma; 58 + extern bool bpf_global_ma_set; 57 59 58 60 typedef u64 (*bpf_callback_t)(u64, u64, u64, u64, u64); 59 61 typedef int (*bpf_iter_init_seq_priv_t)(void *private_data, ··· 179 177 BPF_KPTR_REF = (1 << 3), 180 178 BPF_KPTR = BPF_KPTR_UNREF | BPF_KPTR_REF, 181 179 BPF_LIST_HEAD = (1 << 4), 180 + BPF_LIST_NODE = (1 << 5), 182 181 }; 183 182 184 183 struct btf_field_kptr { ··· 193 190 struct btf *btf; 194 191 u32 value_btf_id; 195 192 u32 node_offset; 193 + struct btf_record *value_rec; 196 194 }; 197 195 198 196 struct btf_field { ··· 281 277 return "kptr"; 282 278 case BPF_LIST_HEAD: 283 279 return "bpf_list_head"; 280 + case BPF_LIST_NODE: 281 + return "bpf_list_node"; 284 282 default: 285 283 WARN_ON_ONCE(1); 286 284 return "unknown"; ··· 301 295 return sizeof(u64); 302 296 case BPF_LIST_HEAD: 303 297 return sizeof(struct bpf_list_head); 298 + case BPF_LIST_NODE: 299 + return sizeof(struct bpf_list_node); 304 300 default: 305 301 WARN_ON_ONCE(1); 306 302 return 0; ··· 321 313 return __alignof__(u64); 322 314 case BPF_LIST_HEAD: 323 315 return __alignof__(struct bpf_list_head); 316 + case BPF_LIST_NODE: 317 + return __alignof__(struct bpf_list_node); 324 318 default: 325 319 WARN_ON_ONCE(1); 326 320 return 0; ··· 336 326 return rec->field_mask & type; 337 327 } 338 328 329 + static inline void bpf_obj_init(const struct btf_field_offs *foffs, void *obj) 330 + { 331 + int i; 332 + 333 + if (!foffs) 334 + return; 335 + for (i = 0; i < foffs->cnt; i++) 336 + memset(obj + foffs->field_off[i], 0, foffs->field_sz[i]); 337 + } 338 + 339 339 static inline void check_and_init_map_value(struct bpf_map *map, void *dst) 340 340 { 341 - if (!IS_ERR_OR_NULL(map->record)) { 342 - struct btf_field *fields = map->record->fields; 343 - u32 cnt = map->record->cnt; 344 - int i; 345 - 346 - for (i = 0; i < cnt; i++) 347 - memset(dst + fields[i].offset, 0, btf_field_type_size(fields[i].type)); 348 - } 341 + bpf_obj_init(map->field_offs, dst); 349 342 } 350 343 351 344 /* memcpy that is used with 8-byte aligned pointers, power-of-8 size and ··· 537 524 538 525 /* Size is known at compile time. */ 539 526 MEM_FIXED_SIZE = BIT(10 + BPF_BASE_TYPE_BITS), 527 + 528 + /* MEM is of an allocated object of type in program BTF. This is used to 529 + * tag PTR_TO_BTF_ID allocated using bpf_obj_new. 530 + */ 531 + MEM_ALLOC = BIT(11 + BPF_BASE_TYPE_BITS), 540 532 541 533 __BPF_TYPE_FLAG_MAX, 542 534 __BPF_TYPE_LAST_FLAG = __BPF_TYPE_FLAG_MAX - 1, ··· 2114 2096 const char *func_name, 2115 2097 struct btf_func_model *m); 2116 2098 2117 - struct bpf_kfunc_arg_meta { 2118 - u64 r0_size; 2119 - bool r0_rdonly; 2120 - int ref_obj_id; 2121 - u32 flags; 2122 - }; 2123 - 2124 2099 struct bpf_reg_state; 2125 2100 int btf_check_subprog_arg_match(struct bpf_verifier_env *env, int subprog, 2126 2101 struct bpf_reg_state *regs); 2127 2102 int btf_check_subprog_call(struct bpf_verifier_env *env, int subprog, 2128 2103 struct bpf_reg_state *regs); 2129 - int btf_check_kfunc_arg_match(struct bpf_verifier_env *env, 2130 - const struct btf *btf, u32 func_id, 2131 - struct bpf_reg_state *regs, 2132 - struct bpf_kfunc_arg_meta *meta); 2133 2104 int btf_prepare_func_args(struct bpf_verifier_env *env, int subprog, 2134 2105 struct bpf_reg_state *reg); 2135 2106 int btf_check_type_match(struct bpf_verifier_log *log, const struct bpf_prog *prog, ··· 2799 2792 bool has_ref; 2800 2793 }; 2801 2794 #endif /* CONFIG_KEYS */ 2795 + 2796 + static inline bool type_is_alloc(u32 type) 2797 + { 2798 + return type & MEM_ALLOC; 2799 + } 2800 + 2802 2801 #endif /* _LINUX_BPF_H */
+22 -3
include/linux/bpf_verifier.h
··· 223 223 * exiting a callback function. 224 224 */ 225 225 int callback_ref; 226 + /* Mark the reference state to release the registers sharing the same id 227 + * on bpf_spin_unlock (for nodes that we will lose ownership to but are 228 + * safe to access inside the critical section). 229 + */ 230 + bool release_on_unlock; 226 231 }; 227 232 228 233 /* state of the program: ··· 328 323 u32 branches; 329 324 u32 insn_idx; 330 325 u32 curframe; 331 - u32 active_spin_lock; 326 + /* For every reg representing a map value or allocated object pointer, 327 + * we consider the tuple of (ptr, id) for them to be unique in verifier 328 + * context and conside them to not alias each other for the purposes of 329 + * tracking lock state. 330 + */ 331 + struct { 332 + /* This can either be reg->map_ptr or reg->btf. If ptr is NULL, 333 + * there's no active lock held, and other fields have no 334 + * meaning. If non-NULL, it indicates that a lock is held and 335 + * id member has the reg->id of the register which can be >= 0. 336 + */ 337 + void *ptr; 338 + /* This will be reg->id */ 339 + u32 id; 340 + } active_lock; 332 341 bool speculative; 333 342 334 343 /* first and last insn idx of this verifier state */ ··· 438 419 */ 439 420 struct bpf_loop_inline_state loop_inline_state; 440 421 }; 422 + u64 obj_new_size; /* remember the size of type passed to bpf_obj_new to rewrite R1 */ 423 + struct btf_struct_meta *kptr_struct_meta; 441 424 u64 map_key_state; /* constant (32 bit) key tracking for maps */ 442 425 int ctx_field_size; /* the ctx field size for load insn, maybe 0 */ 443 426 u32 seen; /* this insn was processed by the verifier at env->pass_cnt */ ··· 610 589 int check_func_arg_reg_off(struct bpf_verifier_env *env, 611 590 const struct bpf_reg_state *reg, int regno, 612 591 enum bpf_arg_type arg_type); 613 - int check_kfunc_mem_size_reg(struct bpf_verifier_env *env, struct bpf_reg_state *reg, 614 - u32 regno); 615 592 int check_mem_reg(struct bpf_verifier_env *env, struct bpf_reg_state *reg, 616 593 u32 regno, u32 mem_size); 617 594 bool is_dynptr_reg_valid_init(struct bpf_verifier_env *env,
+67 -2
include/linux/btf.h
··· 6 6 7 7 #include <linux/types.h> 8 8 #include <linux/bpfptr.h> 9 + #include <linux/bsearch.h> 10 + #include <linux/btf_ids.h> 9 11 #include <uapi/linux/btf.h> 10 12 #include <uapi/linux/bpf.h> 11 13 ··· 78 76 struct btf_id_dtor_kfunc { 79 77 u32 btf_id; 80 78 u32 kfunc_btf_id; 79 + }; 80 + 81 + struct btf_struct_meta { 82 + u32 btf_id; 83 + struct btf_record *record; 84 + struct btf_field_offs *field_offs; 85 + }; 86 + 87 + struct btf_struct_metas { 88 + u32 cnt; 89 + struct btf_struct_meta types[]; 81 90 }; 82 91 83 92 typedef void (*btf_dtor_kfunc_t)(void *); ··· 178 165 int btf_find_timer(const struct btf *btf, const struct btf_type *t); 179 166 struct btf_record *btf_parse_fields(const struct btf *btf, const struct btf_type *t, 180 167 u32 field_mask, u32 value_size); 168 + int btf_check_and_fixup_fields(const struct btf *btf, struct btf_record *rec); 181 169 struct btf_field_offs *btf_parse_field_offs(struct btf_record *rec); 182 170 bool btf_type_is_void(const struct btf_type *t); 183 171 s32 btf_find_by_name_kind(const struct btf *btf, const char *name, u8 kind); ··· 338 324 return kind == BTF_KIND_STRUCT || kind == BTF_KIND_UNION; 339 325 } 340 326 327 + static inline bool __btf_type_is_struct(const struct btf_type *t) 328 + { 329 + return BTF_INFO_KIND(t->info) == BTF_KIND_STRUCT; 330 + } 331 + 332 + static inline bool btf_type_is_array(const struct btf_type *t) 333 + { 334 + return BTF_INFO_KIND(t->info) == BTF_KIND_ARRAY; 335 + } 336 + 341 337 static inline u16 btf_type_vlen(const struct btf_type *t) 342 338 { 343 339 return BTF_INFO_VLEN(t->info); ··· 432 408 return (struct btf_param *)(t + 1); 433 409 } 434 410 435 - #ifdef CONFIG_BPF_SYSCALL 436 - struct bpf_prog; 411 + static inline int btf_id_cmp_func(const void *a, const void *b) 412 + { 413 + const int *pa = a, *pb = b; 437 414 415 + return *pa - *pb; 416 + } 417 + 418 + static inline bool btf_id_set_contains(const struct btf_id_set *set, u32 id) 419 + { 420 + return bsearch(&id, set->ids, set->cnt, sizeof(u32), btf_id_cmp_func) != NULL; 421 + } 422 + 423 + static inline void *btf_id_set8_contains(const struct btf_id_set8 *set, u32 id) 424 + { 425 + return bsearch(&id, set->pairs, set->cnt, sizeof(set->pairs[0]), btf_id_cmp_func); 426 + } 427 + 428 + struct bpf_prog; 429 + struct bpf_verifier_log; 430 + 431 + #ifdef CONFIG_BPF_SYSCALL 438 432 const struct btf_type *btf_type_by_id(const struct btf *btf, u32 type_id); 439 433 const char *btf_name_by_offset(const struct btf *btf, u32 offset); 440 434 struct btf *btf_parse_vmlinux(void); ··· 465 423 s32 btf_find_dtor_kfunc(struct btf *btf, u32 btf_id); 466 424 int register_btf_id_dtor_kfuncs(const struct btf_id_dtor_kfunc *dtors, u32 add_cnt, 467 425 struct module *owner); 426 + struct btf_struct_meta *btf_find_struct_meta(const struct btf *btf, u32 btf_id); 427 + const struct btf_member * 428 + btf_get_prog_ctx_type(struct bpf_verifier_log *log, const struct btf *btf, 429 + const struct btf_type *t, enum bpf_prog_type prog_type, 430 + int arg); 431 + bool btf_types_are_same(const struct btf *btf1, u32 id1, 432 + const struct btf *btf2, u32 id2); 468 433 #else 469 434 static inline const struct btf_type *btf_type_by_id(const struct btf *btf, 470 435 u32 type_id) ··· 502 453 u32 add_cnt, struct module *owner) 503 454 { 504 455 return 0; 456 + } 457 + static inline struct btf_struct_meta *btf_find_struct_meta(const struct btf *btf, u32 btf_id) 458 + { 459 + return NULL; 460 + } 461 + static inline const struct btf_member * 462 + btf_get_prog_ctx_type(struct bpf_verifier_log *log, const struct btf *btf, 463 + const struct btf_type *t, enum bpf_prog_type prog_type, 464 + int arg) 465 + { 466 + return NULL; 467 + } 468 + static inline bool btf_types_are_same(const struct btf *btf1, u32 id1, 469 + const struct btf *btf2, u32 id2) 470 + { 471 + return false; 505 472 } 506 473 #endif 507 474
-1
kernel/bpf/arraymap.c
··· 430 430 for (i = 0; i < array->map.max_entries; i++) 431 431 bpf_obj_free_fields(map->record, array_map_elem_ptr(array, i)); 432 432 } 433 - bpf_map_free_record(map); 434 433 } 435 434 436 435 if (array->map.map_type == BPF_MAP_TYPE_PERCPU_ARRAY)
+269 -387
kernel/bpf/btf.c
··· 237 237 struct rcu_head rcu; 238 238 struct btf_kfunc_set_tab *kfunc_set_tab; 239 239 struct btf_id_dtor_kfunc_tab *dtor_kfunc_tab; 240 + struct btf_struct_metas *struct_meta_tab; 240 241 241 242 /* split BTF support */ 242 243 struct btf *base_btf; ··· 476 475 static bool btf_type_nosize_or_null(const struct btf_type *t) 477 476 { 478 477 return !t || btf_type_nosize(t); 479 - } 480 - 481 - static bool __btf_type_is_struct(const struct btf_type *t) 482 - { 483 - return BTF_INFO_KIND(t->info) == BTF_KIND_STRUCT; 484 - } 485 - 486 - static bool btf_type_is_array(const struct btf_type *t) 487 - { 488 - return BTF_INFO_KIND(t->info) == BTF_KIND_ARRAY; 489 478 } 490 479 491 480 static bool btf_type_is_datasec(const struct btf_type *t) ··· 1633 1642 btf->dtor_kfunc_tab = NULL; 1634 1643 } 1635 1644 1645 + static void btf_struct_metas_free(struct btf_struct_metas *tab) 1646 + { 1647 + int i; 1648 + 1649 + if (!tab) 1650 + return; 1651 + for (i = 0; i < tab->cnt; i++) { 1652 + btf_record_free(tab->types[i].record); 1653 + kfree(tab->types[i].field_offs); 1654 + } 1655 + kfree(tab); 1656 + } 1657 + 1658 + static void btf_free_struct_meta_tab(struct btf *btf) 1659 + { 1660 + struct btf_struct_metas *tab = btf->struct_meta_tab; 1661 + 1662 + btf_struct_metas_free(tab); 1663 + btf->struct_meta_tab = NULL; 1664 + } 1665 + 1636 1666 static void btf_free(struct btf *btf) 1637 1667 { 1668 + btf_free_struct_meta_tab(btf); 1638 1669 btf_free_dtor_kfunc_tab(btf); 1639 1670 btf_free_kfunc_set_tab(btf); 1640 1671 kvfree(btf->types); ··· 3366 3353 goto end; 3367 3354 } 3368 3355 } 3356 + if (field_mask & BPF_LIST_NODE) { 3357 + if (!strcmp(name, "bpf_list_node")) { 3358 + type = BPF_LIST_NODE; 3359 + goto end; 3360 + } 3361 + } 3369 3362 /* Only return BPF_KPTR when all other types with matchable names fail */ 3370 3363 if (field_mask & BPF_KPTR) { 3371 3364 type = BPF_KPTR_REF; ··· 3415 3396 switch (field_type) { 3416 3397 case BPF_SPIN_LOCK: 3417 3398 case BPF_TIMER: 3399 + case BPF_LIST_NODE: 3418 3400 ret = btf_find_struct(btf, member_type, off, sz, field_type, 3419 3401 idx < info_cnt ? &info[idx] : &tmp); 3420 3402 if (ret < 0) ··· 3476 3456 switch (field_type) { 3477 3457 case BPF_SPIN_LOCK: 3478 3458 case BPF_TIMER: 3459 + case BPF_LIST_NODE: 3479 3460 ret = btf_find_struct(btf, var_type, off, sz, field_type, 3480 3461 idx < info_cnt ? &info[idx] : &tmp); 3481 3462 if (ret < 0) ··· 3648 3627 return NULL; 3649 3628 3650 3629 cnt = ret; 3630 + /* This needs to be kzalloc to zero out padding and unused fields, see 3631 + * comment in btf_record_equal. 3632 + */ 3651 3633 rec = kzalloc(offsetof(struct btf_record, fields[cnt]), GFP_KERNEL | __GFP_NOWARN); 3652 3634 if (!rec) 3653 3635 return ERR_PTR(-ENOMEM); ··· 3695 3671 if (ret < 0) 3696 3672 goto end; 3697 3673 break; 3674 + case BPF_LIST_NODE: 3675 + break; 3698 3676 default: 3699 3677 ret = -EFAULT; 3700 3678 goto end; ··· 3714 3688 end: 3715 3689 btf_record_free(rec); 3716 3690 return ERR_PTR(ret); 3691 + } 3692 + 3693 + int btf_check_and_fixup_fields(const struct btf *btf, struct btf_record *rec) 3694 + { 3695 + int i; 3696 + 3697 + /* There are two owning types, kptr_ref and bpf_list_head. The former 3698 + * only supports storing kernel types, which can never store references 3699 + * to program allocated local types, atleast not yet. Hence we only need 3700 + * to ensure that bpf_list_head ownership does not form cycles. 3701 + */ 3702 + if (IS_ERR_OR_NULL(rec) || !(rec->field_mask & BPF_LIST_HEAD)) 3703 + return 0; 3704 + for (i = 0; i < rec->cnt; i++) { 3705 + struct btf_struct_meta *meta; 3706 + u32 btf_id; 3707 + 3708 + if (!(rec->fields[i].type & BPF_LIST_HEAD)) 3709 + continue; 3710 + btf_id = rec->fields[i].list_head.value_btf_id; 3711 + meta = btf_find_struct_meta(btf, btf_id); 3712 + if (!meta) 3713 + return -EFAULT; 3714 + rec->fields[i].list_head.value_rec = meta->record; 3715 + 3716 + if (!(rec->field_mask & BPF_LIST_NODE)) 3717 + continue; 3718 + 3719 + /* We need to ensure ownership acyclicity among all types. The 3720 + * proper way to do it would be to topologically sort all BTF 3721 + * IDs based on the ownership edges, since there can be multiple 3722 + * bpf_list_head in a type. Instead, we use the following 3723 + * reasoning: 3724 + * 3725 + * - A type can only be owned by another type in user BTF if it 3726 + * has a bpf_list_node. 3727 + * - A type can only _own_ another type in user BTF if it has a 3728 + * bpf_list_head. 3729 + * 3730 + * We ensure that if a type has both bpf_list_head and 3731 + * bpf_list_node, its element types cannot be owning types. 3732 + * 3733 + * To ensure acyclicity: 3734 + * 3735 + * When A only has bpf_list_head, ownership chain can be: 3736 + * A -> B -> C 3737 + * Where: 3738 + * - B has both bpf_list_head and bpf_list_node. 3739 + * - C only has bpf_list_node. 3740 + * 3741 + * When A has both bpf_list_head and bpf_list_node, some other 3742 + * type already owns it in the BTF domain, hence it can not own 3743 + * another owning type through any of the bpf_list_head edges. 3744 + * A -> B 3745 + * Where: 3746 + * - B only has bpf_list_node. 3747 + */ 3748 + if (meta->record->field_mask & BPF_LIST_HEAD) 3749 + return -ELOOP; 3750 + } 3751 + return 0; 3717 3752 } 3718 3753 3719 3754 static int btf_field_offs_cmp(const void *_a, const void *_b, const void *priv) ··· 5228 5141 return btf_check_sec_info(env, btf_data_size); 5229 5142 } 5230 5143 5144 + static const char *alloc_obj_fields[] = { 5145 + "bpf_spin_lock", 5146 + "bpf_list_head", 5147 + "bpf_list_node", 5148 + }; 5149 + 5150 + static struct btf_struct_metas * 5151 + btf_parse_struct_metas(struct bpf_verifier_log *log, struct btf *btf) 5152 + { 5153 + union { 5154 + struct btf_id_set set; 5155 + struct { 5156 + u32 _cnt; 5157 + u32 _ids[ARRAY_SIZE(alloc_obj_fields)]; 5158 + } _arr; 5159 + } aof; 5160 + struct btf_struct_metas *tab = NULL; 5161 + int i, n, id, ret; 5162 + 5163 + BUILD_BUG_ON(offsetof(struct btf_id_set, cnt) != 0); 5164 + BUILD_BUG_ON(sizeof(struct btf_id_set) != sizeof(u32)); 5165 + 5166 + memset(&aof, 0, sizeof(aof)); 5167 + for (i = 0; i < ARRAY_SIZE(alloc_obj_fields); i++) { 5168 + /* Try to find whether this special type exists in user BTF, and 5169 + * if so remember its ID so we can easily find it among members 5170 + * of structs that we iterate in the next loop. 5171 + */ 5172 + id = btf_find_by_name_kind(btf, alloc_obj_fields[i], BTF_KIND_STRUCT); 5173 + if (id < 0) 5174 + continue; 5175 + aof.set.ids[aof.set.cnt++] = id; 5176 + } 5177 + 5178 + if (!aof.set.cnt) 5179 + return NULL; 5180 + sort(&aof.set.ids, aof.set.cnt, sizeof(aof.set.ids[0]), btf_id_cmp_func, NULL); 5181 + 5182 + n = btf_nr_types(btf); 5183 + for (i = 1; i < n; i++) { 5184 + struct btf_struct_metas *new_tab; 5185 + const struct btf_member *member; 5186 + struct btf_field_offs *foffs; 5187 + struct btf_struct_meta *type; 5188 + struct btf_record *record; 5189 + const struct btf_type *t; 5190 + int j, tab_cnt; 5191 + 5192 + t = btf_type_by_id(btf, i); 5193 + if (!t) { 5194 + ret = -EINVAL; 5195 + goto free; 5196 + } 5197 + if (!__btf_type_is_struct(t)) 5198 + continue; 5199 + 5200 + cond_resched(); 5201 + 5202 + for_each_member(j, t, member) { 5203 + if (btf_id_set_contains(&aof.set, member->type)) 5204 + goto parse; 5205 + } 5206 + continue; 5207 + parse: 5208 + tab_cnt = tab ? tab->cnt : 0; 5209 + new_tab = krealloc(tab, offsetof(struct btf_struct_metas, types[tab_cnt + 1]), 5210 + GFP_KERNEL | __GFP_NOWARN); 5211 + if (!new_tab) { 5212 + ret = -ENOMEM; 5213 + goto free; 5214 + } 5215 + if (!tab) 5216 + new_tab->cnt = 0; 5217 + tab = new_tab; 5218 + 5219 + type = &tab->types[tab->cnt]; 5220 + type->btf_id = i; 5221 + record = btf_parse_fields(btf, t, BPF_SPIN_LOCK | BPF_LIST_HEAD | BPF_LIST_NODE, t->size); 5222 + /* The record cannot be unset, treat it as an error if so */ 5223 + if (IS_ERR_OR_NULL(record)) { 5224 + ret = PTR_ERR_OR_ZERO(record) ?: -EFAULT; 5225 + goto free; 5226 + } 5227 + foffs = btf_parse_field_offs(record); 5228 + /* We need the field_offs to be valid for a valid record, 5229 + * either both should be set or both should be unset. 5230 + */ 5231 + if (IS_ERR_OR_NULL(foffs)) { 5232 + btf_record_free(record); 5233 + ret = -EFAULT; 5234 + goto free; 5235 + } 5236 + type->record = record; 5237 + type->field_offs = foffs; 5238 + tab->cnt++; 5239 + } 5240 + return tab; 5241 + free: 5242 + btf_struct_metas_free(tab); 5243 + return ERR_PTR(ret); 5244 + } 5245 + 5246 + struct btf_struct_meta *btf_find_struct_meta(const struct btf *btf, u32 btf_id) 5247 + { 5248 + struct btf_struct_metas *tab; 5249 + 5250 + BUILD_BUG_ON(offsetof(struct btf_struct_meta, btf_id) != 0); 5251 + tab = btf->struct_meta_tab; 5252 + if (!tab) 5253 + return NULL; 5254 + return bsearch(&btf_id, tab->types, tab->cnt, sizeof(tab->types[0]), btf_id_cmp_func); 5255 + } 5256 + 5231 5257 static int btf_check_type_tags(struct btf_verifier_env *env, 5232 5258 struct btf *btf, int start_id) 5233 5259 { ··· 5391 5191 static struct btf *btf_parse(bpfptr_t btf_data, u32 btf_data_size, 5392 5192 u32 log_level, char __user *log_ubuf, u32 log_size) 5393 5193 { 5194 + struct btf_struct_metas *struct_meta_tab; 5394 5195 struct btf_verifier_env *env = NULL; 5395 5196 struct bpf_verifier_log *log; 5396 5197 struct btf *btf = NULL; ··· 5460 5259 if (err) 5461 5260 goto errout; 5462 5261 5262 + struct_meta_tab = btf_parse_struct_metas(log, btf); 5263 + if (IS_ERR(struct_meta_tab)) { 5264 + err = PTR_ERR(struct_meta_tab); 5265 + goto errout; 5266 + } 5267 + btf->struct_meta_tab = struct_meta_tab; 5268 + 5269 + if (struct_meta_tab) { 5270 + int i; 5271 + 5272 + for (i = 0; i < struct_meta_tab->cnt; i++) { 5273 + err = btf_check_and_fixup_fields(btf, struct_meta_tab->types[i].record); 5274 + if (err < 0) 5275 + goto errout_meta; 5276 + } 5277 + } 5278 + 5463 5279 if (log->level && bpf_verifier_log_full(log)) { 5464 5280 err = -ENOSPC; 5465 - goto errout; 5281 + goto errout_meta; 5466 5282 } 5467 5283 5468 5284 btf_verifier_env_free(env); 5469 5285 refcount_set(&btf->refcnt, 1); 5470 5286 return btf; 5471 5287 5288 + errout_meta: 5289 + btf_free_struct_meta_tab(btf); 5472 5290 errout: 5473 5291 btf_verifier_env_free(env); 5474 5292 if (btf) ··· 5529 5309 #undef BPF_MAP_TYPE 5530 5310 #undef BPF_LINK_TYPE 5531 5311 5532 - static const struct btf_member * 5312 + const struct btf_member * 5533 5313 btf_get_prog_ctx_type(struct bpf_verifier_log *log, const struct btf *btf, 5534 5314 const struct btf_type *t, enum bpf_prog_type prog_type, 5535 5315 int arg) ··· 6248 6028 u32 id = reg->btf_id; 6249 6029 int err; 6250 6030 6031 + while (type_is_alloc(reg->type)) { 6032 + struct btf_struct_meta *meta; 6033 + struct btf_record *rec; 6034 + int i; 6035 + 6036 + meta = btf_find_struct_meta(btf, id); 6037 + if (!meta) 6038 + break; 6039 + rec = meta->record; 6040 + for (i = 0; i < rec->cnt; i++) { 6041 + struct btf_field *field = &rec->fields[i]; 6042 + u32 offset = field->offset; 6043 + if (off < offset + btf_field_type_size(field->type) && offset < off + size) { 6044 + bpf_log(log, 6045 + "direct access to %s is disallowed\n", 6046 + btf_field_type_name(field->type)); 6047 + return -EACCES; 6048 + } 6049 + } 6050 + break; 6051 + } 6052 + 6251 6053 t = btf_type_by_id(btf, id); 6252 6054 do { 6253 6055 err = btf_struct_walk(log, btf, t, off, size, &id, &tmp_flag); 6254 6056 6255 6057 switch (err) { 6256 6058 case WALK_PTR: 6059 + /* For local types, the destination register cannot 6060 + * become a pointer again. 6061 + */ 6062 + if (type_is_alloc(reg->type)) 6063 + return SCALAR_VALUE; 6257 6064 /* If we found the pointer or scalar on t+off, 6258 6065 * we're done. 6259 6066 */ ··· 6315 6068 * end up with two different module BTFs, but IDs point to the common type in 6316 6069 * vmlinux BTF. 6317 6070 */ 6318 - static bool btf_types_are_same(const struct btf *btf1, u32 id1, 6319 - const struct btf *btf2, u32 id2) 6071 + bool btf_types_are_same(const struct btf *btf1, u32 id1, 6072 + const struct btf *btf2, u32 id2) 6320 6073 { 6321 6074 if (id1 != id2) 6322 6075 return false; ··· 6598 6351 return btf_check_func_type_match(log, btf1, t1, btf2, t2); 6599 6352 } 6600 6353 6601 - static u32 *reg2btf_ids[__BPF_REG_TYPE_MAX] = { 6602 - #ifdef CONFIG_NET 6603 - [PTR_TO_SOCKET] = &btf_sock_ids[BTF_SOCK_TYPE_SOCK], 6604 - [PTR_TO_SOCK_COMMON] = &btf_sock_ids[BTF_SOCK_TYPE_SOCK_COMMON], 6605 - [PTR_TO_TCP_SOCK] = &btf_sock_ids[BTF_SOCK_TYPE_TCP], 6606 - #endif 6607 - }; 6608 - 6609 - /* Returns true if struct is composed of scalars, 4 levels of nesting allowed */ 6610 - static bool __btf_type_is_scalar_struct(struct bpf_verifier_log *log, 6611 - const struct btf *btf, 6612 - const struct btf_type *t, int rec) 6613 - { 6614 - const struct btf_type *member_type; 6615 - const struct btf_member *member; 6616 - u32 i; 6617 - 6618 - if (!btf_type_is_struct(t)) 6619 - return false; 6620 - 6621 - for_each_member(i, t, member) { 6622 - const struct btf_array *array; 6623 - 6624 - member_type = btf_type_skip_modifiers(btf, member->type, NULL); 6625 - if (btf_type_is_struct(member_type)) { 6626 - if (rec >= 3) { 6627 - bpf_log(log, "max struct nesting depth exceeded\n"); 6628 - return false; 6629 - } 6630 - if (!__btf_type_is_scalar_struct(log, btf, member_type, rec + 1)) 6631 - return false; 6632 - continue; 6633 - } 6634 - if (btf_type_is_array(member_type)) { 6635 - array = btf_type_array(member_type); 6636 - if (!array->nelems) 6637 - return false; 6638 - member_type = btf_type_skip_modifiers(btf, array->type, NULL); 6639 - if (!btf_type_is_scalar(member_type)) 6640 - return false; 6641 - continue; 6642 - } 6643 - if (!btf_type_is_scalar(member_type)) 6644 - return false; 6645 - } 6646 - return true; 6647 - } 6648 - 6649 - static bool is_kfunc_arg_mem_size(const struct btf *btf, 6650 - const struct btf_param *arg, 6651 - const struct bpf_reg_state *reg) 6652 - { 6653 - int len, sfx_len = sizeof("__sz") - 1; 6654 - const struct btf_type *t; 6655 - const char *param_name; 6656 - 6657 - t = btf_type_skip_modifiers(btf, arg->type, NULL); 6658 - if (!btf_type_is_scalar(t) || reg->type != SCALAR_VALUE) 6659 - return false; 6660 - 6661 - /* In the future, this can be ported to use BTF tagging */ 6662 - param_name = btf_name_by_offset(btf, arg->name_off); 6663 - if (str_is_empty(param_name)) 6664 - return false; 6665 - len = strlen(param_name); 6666 - if (len < sfx_len) 6667 - return false; 6668 - param_name += len - sfx_len; 6669 - if (strncmp(param_name, "__sz", sfx_len)) 6670 - return false; 6671 - 6672 - return true; 6673 - } 6674 - 6675 - static bool btf_is_kfunc_arg_mem_size(const struct btf *btf, 6676 - const struct btf_param *arg, 6677 - const struct bpf_reg_state *reg, 6678 - const char *name) 6679 - { 6680 - int len, target_len = strlen(name); 6681 - const struct btf_type *t; 6682 - const char *param_name; 6683 - 6684 - t = btf_type_skip_modifiers(btf, arg->type, NULL); 6685 - if (!btf_type_is_scalar(t) || reg->type != SCALAR_VALUE) 6686 - return false; 6687 - 6688 - param_name = btf_name_by_offset(btf, arg->name_off); 6689 - if (str_is_empty(param_name)) 6690 - return false; 6691 - len = strlen(param_name); 6692 - if (len != target_len) 6693 - return false; 6694 - if (strcmp(param_name, name)) 6695 - return false; 6696 - 6697 - return true; 6698 - } 6699 - 6700 6354 static int btf_check_func_arg_match(struct bpf_verifier_env *env, 6701 6355 const struct btf *btf, u32 func_id, 6702 6356 struct bpf_reg_state *regs, 6703 6357 bool ptr_to_mem_ok, 6704 - struct bpf_kfunc_arg_meta *kfunc_meta, 6705 6358 bool processing_call) 6706 6359 { 6707 6360 enum bpf_prog_type prog_type = resolve_prog_type(env->prog); 6708 - bool rel = false, kptr_get = false, trusted_args = false; 6709 - bool sleepable = false; 6710 6361 struct bpf_verifier_log *log = &env->log; 6711 - u32 i, nargs, ref_id, ref_obj_id = 0; 6712 - bool is_kfunc = btf_is_kernel(btf); 6713 6362 const char *func_name, *ref_tname; 6714 6363 const struct btf_type *t, *ref_t; 6715 6364 const struct btf_param *args; 6716 - int ref_regno = 0, ret; 6365 + u32 i, nargs, ref_id; 6366 + int ret; 6717 6367 6718 6368 t = btf_type_by_id(btf, func_id); 6719 6369 if (!t || !btf_type_is_func(t)) { ··· 6636 6492 return -EINVAL; 6637 6493 } 6638 6494 6639 - if (is_kfunc && kfunc_meta) { 6640 - /* Only kfunc can be release func */ 6641 - rel = kfunc_meta->flags & KF_RELEASE; 6642 - kptr_get = kfunc_meta->flags & KF_KPTR_GET; 6643 - trusted_args = kfunc_meta->flags & KF_TRUSTED_ARGS; 6644 - sleepable = kfunc_meta->flags & KF_SLEEPABLE; 6645 - } 6646 - 6647 6495 /* check that BTF function arguments match actual types that the 6648 6496 * verifier sees. 6649 6497 */ ··· 6643 6507 enum bpf_arg_type arg_type = ARG_DONTCARE; 6644 6508 u32 regno = i + 1; 6645 6509 struct bpf_reg_state *reg = &regs[regno]; 6646 - bool obj_ptr = false; 6647 6510 6648 6511 t = btf_type_skip_modifiers(btf, args[i].type, NULL); 6649 6512 if (btf_type_is_scalar(t)) { 6650 - if (is_kfunc && kfunc_meta) { 6651 - bool is_buf_size = false; 6652 - 6653 - /* check for any const scalar parameter of name "rdonly_buf_size" 6654 - * or "rdwr_buf_size" 6655 - */ 6656 - if (btf_is_kfunc_arg_mem_size(btf, &args[i], reg, 6657 - "rdonly_buf_size")) { 6658 - kfunc_meta->r0_rdonly = true; 6659 - is_buf_size = true; 6660 - } else if (btf_is_kfunc_arg_mem_size(btf, &args[i], reg, 6661 - "rdwr_buf_size")) 6662 - is_buf_size = true; 6663 - 6664 - if (is_buf_size) { 6665 - if (kfunc_meta->r0_size) { 6666 - bpf_log(log, "2 or more rdonly/rdwr_buf_size parameters for kfunc"); 6667 - return -EINVAL; 6668 - } 6669 - 6670 - if (!tnum_is_const(reg->var_off)) { 6671 - bpf_log(log, "R%d is not a const\n", regno); 6672 - return -EINVAL; 6673 - } 6674 - 6675 - kfunc_meta->r0_size = reg->var_off.value; 6676 - ret = mark_chain_precision(env, regno); 6677 - if (ret) 6678 - return ret; 6679 - } 6680 - } 6681 - 6682 6513 if (reg->type == SCALAR_VALUE) 6683 6514 continue; 6684 6515 bpf_log(log, "R%d is not a scalar\n", regno); ··· 6658 6555 return -EINVAL; 6659 6556 } 6660 6557 6661 - /* These register types have special constraints wrt ref_obj_id 6662 - * and offset checks. The rest of trusted args don't. 6663 - */ 6664 - obj_ptr = reg->type == PTR_TO_CTX || reg->type == PTR_TO_BTF_ID || 6665 - reg2btf_ids[base_type(reg->type)]; 6666 - 6667 - /* Check if argument must be a referenced pointer, args + i has 6668 - * been verified to be a pointer (after skipping modifiers). 6669 - * PTR_TO_CTX is ok without having non-zero ref_obj_id. 6670 - */ 6671 - if (is_kfunc && trusted_args && (obj_ptr && reg->type != PTR_TO_CTX) && !reg->ref_obj_id) { 6672 - bpf_log(log, "R%d must be referenced\n", regno); 6673 - return -EINVAL; 6674 - } 6675 - 6676 6558 ref_t = btf_type_skip_modifiers(btf, t->type, &ref_id); 6677 6559 ref_tname = btf_name_by_offset(btf, ref_t->name_off); 6678 6560 6679 - /* Trusted args have the same offset checks as release arguments */ 6680 - if ((trusted_args && obj_ptr) || (rel && reg->ref_obj_id)) 6681 - arg_type |= OBJ_RELEASE; 6682 6561 ret = check_func_arg_reg_off(env, reg, regno, arg_type); 6683 6562 if (ret < 0) 6684 6563 return ret; 6685 6564 6686 - if (is_kfunc && reg->ref_obj_id) { 6687 - /* Ensure only one argument is referenced PTR_TO_BTF_ID */ 6688 - if (ref_obj_id) { 6689 - bpf_log(log, "verifier internal error: more than one arg with ref_obj_id R%d %u %u\n", 6690 - regno, reg->ref_obj_id, ref_obj_id); 6691 - return -EFAULT; 6692 - } 6693 - ref_regno = regno; 6694 - ref_obj_id = reg->ref_obj_id; 6695 - } 6696 - 6697 - /* kptr_get is only true for kfunc */ 6698 - if (i == 0 && kptr_get) { 6699 - struct btf_field *kptr_field; 6700 - 6701 - if (reg->type != PTR_TO_MAP_VALUE) { 6702 - bpf_log(log, "arg#0 expected pointer to map value\n"); 6703 - return -EINVAL; 6704 - } 6705 - 6706 - /* check_func_arg_reg_off allows var_off for 6707 - * PTR_TO_MAP_VALUE, but we need fixed offset to find 6708 - * off_desc. 6709 - */ 6710 - if (!tnum_is_const(reg->var_off)) { 6711 - bpf_log(log, "arg#0 must have constant offset\n"); 6712 - return -EINVAL; 6713 - } 6714 - 6715 - kptr_field = btf_record_find(reg->map_ptr->record, reg->off + reg->var_off.value, BPF_KPTR); 6716 - if (!kptr_field || kptr_field->type != BPF_KPTR_REF) { 6717 - bpf_log(log, "arg#0 no referenced kptr at map value offset=%llu\n", 6718 - reg->off + reg->var_off.value); 6719 - return -EINVAL; 6720 - } 6721 - 6722 - if (!btf_type_is_ptr(ref_t)) { 6723 - bpf_log(log, "arg#0 BTF type must be a double pointer\n"); 6724 - return -EINVAL; 6725 - } 6726 - 6727 - ref_t = btf_type_skip_modifiers(btf, ref_t->type, &ref_id); 6728 - ref_tname = btf_name_by_offset(btf, ref_t->name_off); 6729 - 6730 - if (!btf_type_is_struct(ref_t)) { 6731 - bpf_log(log, "kernel function %s args#%d pointer type %s %s is not supported\n", 6732 - func_name, i, btf_type_str(ref_t), ref_tname); 6733 - return -EINVAL; 6734 - } 6735 - if (!btf_struct_ids_match(log, btf, ref_id, 0, kptr_field->kptr.btf, 6736 - kptr_field->kptr.btf_id, true)) { 6737 - bpf_log(log, "kernel function %s args#%d expected pointer to %s %s\n", 6738 - func_name, i, btf_type_str(ref_t), ref_tname); 6739 - return -EINVAL; 6740 - } 6741 - /* rest of the arguments can be anything, like normal kfunc */ 6742 - } else if (btf_get_prog_ctx_type(log, btf, t, prog_type, i)) { 6565 + if (btf_get_prog_ctx_type(log, btf, t, prog_type, i)) { 6743 6566 /* If function expects ctx type in BTF check that caller 6744 6567 * is passing PTR_TO_CTX. 6745 6568 */ ··· 6675 6646 i, btf_type_str(t)); 6676 6647 return -EINVAL; 6677 6648 } 6678 - } else if (is_kfunc && (reg->type == PTR_TO_BTF_ID || 6679 - (reg2btf_ids[base_type(reg->type)] && !type_flag(reg->type)))) { 6680 - const struct btf_type *reg_ref_t; 6681 - const struct btf *reg_btf; 6682 - const char *reg_ref_tname; 6683 - u32 reg_ref_id; 6684 - 6685 - if (!btf_type_is_struct(ref_t)) { 6686 - bpf_log(log, "kernel function %s args#%d pointer type %s %s is not supported\n", 6687 - func_name, i, btf_type_str(ref_t), 6688 - ref_tname); 6689 - return -EINVAL; 6690 - } 6691 - 6692 - if (reg->type == PTR_TO_BTF_ID) { 6693 - reg_btf = reg->btf; 6694 - reg_ref_id = reg->btf_id; 6695 - } else { 6696 - reg_btf = btf_vmlinux; 6697 - reg_ref_id = *reg2btf_ids[base_type(reg->type)]; 6698 - } 6699 - 6700 - reg_ref_t = btf_type_skip_modifiers(reg_btf, reg_ref_id, 6701 - &reg_ref_id); 6702 - reg_ref_tname = btf_name_by_offset(reg_btf, 6703 - reg_ref_t->name_off); 6704 - if (!btf_struct_ids_match(log, reg_btf, reg_ref_id, 6705 - reg->off, btf, ref_id, 6706 - trusted_args || (rel && reg->ref_obj_id))) { 6707 - bpf_log(log, "kernel function %s args#%d expected pointer to %s %s but R%d has a pointer to %s %s\n", 6708 - func_name, i, 6709 - btf_type_str(ref_t), ref_tname, 6710 - regno, btf_type_str(reg_ref_t), 6711 - reg_ref_tname); 6712 - return -EINVAL; 6713 - } 6714 6649 } else if (ptr_to_mem_ok && processing_call) { 6715 6650 const struct btf_type *resolve_ret; 6716 6651 u32 type_size; 6717 - 6718 - if (is_kfunc) { 6719 - bool arg_mem_size = i + 1 < nargs && is_kfunc_arg_mem_size(btf, &args[i + 1], &regs[regno + 1]); 6720 - bool arg_dynptr = btf_type_is_struct(ref_t) && 6721 - !strcmp(ref_tname, 6722 - stringify_struct(bpf_dynptr_kern)); 6723 - 6724 - /* Permit pointer to mem, but only when argument 6725 - * type is pointer to scalar, or struct composed 6726 - * (recursively) of scalars. 6727 - * When arg_mem_size is true, the pointer can be 6728 - * void *. 6729 - * Also permit initialized local dynamic pointers. 6730 - */ 6731 - if (!btf_type_is_scalar(ref_t) && 6732 - !__btf_type_is_scalar_struct(log, btf, ref_t, 0) && 6733 - !arg_dynptr && 6734 - (arg_mem_size ? !btf_type_is_void(ref_t) : 1)) { 6735 - bpf_log(log, 6736 - "arg#%d pointer type %s %s must point to %sscalar, or struct with scalar\n", 6737 - i, btf_type_str(ref_t), ref_tname, arg_mem_size ? "void, " : ""); 6738 - return -EINVAL; 6739 - } 6740 - 6741 - if (arg_dynptr) { 6742 - if (reg->type != PTR_TO_STACK) { 6743 - bpf_log(log, "arg#%d pointer type %s %s not to stack\n", 6744 - i, btf_type_str(ref_t), 6745 - ref_tname); 6746 - return -EINVAL; 6747 - } 6748 - 6749 - if (!is_dynptr_reg_valid_init(env, reg)) { 6750 - bpf_log(log, 6751 - "arg#%d pointer type %s %s must be valid and initialized\n", 6752 - i, btf_type_str(ref_t), 6753 - ref_tname); 6754 - return -EINVAL; 6755 - } 6756 - 6757 - if (!is_dynptr_type_expected(env, reg, 6758 - ARG_PTR_TO_DYNPTR | DYNPTR_TYPE_LOCAL)) { 6759 - bpf_log(log, 6760 - "arg#%d pointer type %s %s points to unsupported dynamic pointer type\n", 6761 - i, btf_type_str(ref_t), 6762 - ref_tname); 6763 - return -EINVAL; 6764 - } 6765 - 6766 - continue; 6767 - } 6768 - 6769 - /* Check for mem, len pair */ 6770 - if (arg_mem_size) { 6771 - if (check_kfunc_mem_size_reg(env, &regs[regno + 1], regno + 1)) { 6772 - bpf_log(log, "arg#%d arg#%d memory, len pair leads to invalid memory access\n", 6773 - i, i + 1); 6774 - return -EINVAL; 6775 - } 6776 - i++; 6777 - continue; 6778 - } 6779 - } 6780 6652 6781 6653 resolve_ret = btf_resolve_size(btf, ref_t, &type_size); 6782 6654 if (IS_ERR(resolve_ret)) { ··· 6691 6761 if (check_mem_reg(env, reg, regno, type_size)) 6692 6762 return -EINVAL; 6693 6763 } else { 6694 - bpf_log(log, "reg type unsupported for arg#%d %sfunction %s#%d\n", i, 6695 - is_kfunc ? "kernel " : "", func_name, func_id); 6764 + bpf_log(log, "reg type unsupported for arg#%d function %s#%d\n", i, 6765 + func_name, func_id); 6696 6766 return -EINVAL; 6697 6767 } 6698 6768 } 6699 6769 6700 - /* Either both are set, or neither */ 6701 - WARN_ON_ONCE((ref_obj_id && !ref_regno) || (!ref_obj_id && ref_regno)); 6702 - /* We already made sure ref_obj_id is set only for one argument. We do 6703 - * allow (!rel && ref_obj_id), so that passing such referenced 6704 - * PTR_TO_BTF_ID to other kfuncs works. Note that rel is only true when 6705 - * is_kfunc is true. 6706 - */ 6707 - if (rel && !ref_obj_id) { 6708 - bpf_log(log, "release kernel function %s expects refcounted PTR_TO_BTF_ID\n", 6709 - func_name); 6710 - return -EINVAL; 6711 - } 6712 - 6713 - if (sleepable && !env->prog->aux->sleepable) { 6714 - bpf_log(log, "kernel function %s is sleepable but the program is not\n", 6715 - func_name); 6716 - return -EINVAL; 6717 - } 6718 - 6719 - if (kfunc_meta && ref_obj_id) 6720 - kfunc_meta->ref_obj_id = ref_obj_id; 6721 - 6722 - /* returns argument register number > 0 in case of reference release kfunc */ 6723 - return rel ? ref_regno : 0; 6770 + return 0; 6724 6771 } 6725 6772 6726 6773 /* Compare BTF of a function declaration with given bpf_reg_state. ··· 6727 6820 return -EINVAL; 6728 6821 6729 6822 is_global = prog->aux->func_info_aux[subprog].linkage == BTF_FUNC_GLOBAL; 6730 - err = btf_check_func_arg_match(env, btf, btf_id, regs, is_global, NULL, false); 6823 + err = btf_check_func_arg_match(env, btf, btf_id, regs, is_global, false); 6731 6824 6732 6825 /* Compiler optimizations can remove arguments from static functions 6733 6826 * or mismatched type can be passed into a global function. ··· 6770 6863 return -EINVAL; 6771 6864 6772 6865 is_global = prog->aux->func_info_aux[subprog].linkage == BTF_FUNC_GLOBAL; 6773 - err = btf_check_func_arg_match(env, btf, btf_id, regs, is_global, NULL, true); 6866 + err = btf_check_func_arg_match(env, btf, btf_id, regs, is_global, true); 6774 6867 6775 6868 /* Compiler optimizations can remove arguments from static functions 6776 6869 * or mismatched type can be passed into a global function. ··· 6779 6872 if (err) 6780 6873 prog->aux->func_info_aux[subprog].unreliable = true; 6781 6874 return err; 6782 - } 6783 - 6784 - int btf_check_kfunc_arg_match(struct bpf_verifier_env *env, 6785 - const struct btf *btf, u32 func_id, 6786 - struct bpf_reg_state *regs, 6787 - struct bpf_kfunc_arg_meta *meta) 6788 - { 6789 - return btf_check_func_arg_match(env, btf, func_id, regs, true, meta, true); 6790 6875 } 6791 6876 6792 6877 /* Convert BTF of a function into bpf_reg_state if possible ··· 7161 7262 bool btf_is_module(const struct btf *btf) 7162 7263 { 7163 7264 return btf->kernel_btf && strcmp(btf->name, "vmlinux") != 0; 7164 - } 7165 - 7166 - static int btf_id_cmp_func(const void *a, const void *b) 7167 - { 7168 - const int *pa = a, *pb = b; 7169 - 7170 - return *pa - *pb; 7171 - } 7172 - 7173 - bool btf_id_set_contains(const struct btf_id_set *set, u32 id) 7174 - { 7175 - return bsearch(&id, set->ids, set->cnt, sizeof(u32), btf_id_cmp_func) != NULL; 7176 - } 7177 - 7178 - static void *btf_id_set8_contains(const struct btf_id_set8 *set, u32 id) 7179 - { 7180 - return bsearch(&id, set->pairs, set->cnt, sizeof(set->pairs[0]), btf_id_cmp_func); 7181 7265 } 7182 7266 7183 7267 enum {
+16
kernel/bpf/core.c
··· 34 34 #include <linux/log2.h> 35 35 #include <linux/bpf_verifier.h> 36 36 #include <linux/nodemask.h> 37 + #include <linux/bpf_mem_alloc.h> 37 38 38 39 #include <asm/barrier.h> 39 40 #include <asm/unaligned.h> ··· 60 59 #define ARG1 regs[BPF_REG_ARG1] 61 60 #define CTX regs[BPF_REG_CTX] 62 61 #define IMM insn->imm 62 + 63 + struct bpf_mem_alloc bpf_global_ma; 64 + bool bpf_global_ma_set; 63 65 64 66 /* No hurry in this branch 65 67 * ··· 2749 2745 { 2750 2746 return -ENOTSUPP; 2751 2747 } 2748 + 2749 + #ifdef CONFIG_BPF_SYSCALL 2750 + static int __init bpf_global_ma_init(void) 2751 + { 2752 + int ret; 2753 + 2754 + ret = bpf_mem_alloc_init(&bpf_global_ma, 0, false); 2755 + bpf_global_ma_set = !ret; 2756 + return ret; 2757 + } 2758 + late_initcall(bpf_global_ma_init); 2759 + #endif 2752 2760 2753 2761 DEFINE_STATIC_KEY_FALSE(bpf_stats_enabled_key); 2754 2762 EXPORT_SYMBOL(bpf_stats_enabled_key);
-1
kernel/bpf/hashtab.c
··· 1511 1511 prealloc_destroy(htab); 1512 1512 } 1513 1513 1514 - bpf_map_free_record(map); 1515 1514 free_percpu(htab->extra_elems); 1516 1515 bpf_map_area_free(htab->buckets); 1517 1516 bpf_mem_alloc_destroy(&htab->pcpu_ma);
+106 -7
kernel/bpf/helpers.c
··· 19 19 #include <linux/proc_ns.h> 20 20 #include <linux/security.h> 21 21 #include <linux/btf_ids.h> 22 + #include <linux/bpf_mem_alloc.h> 22 23 23 24 #include "../../lib/kstrtox.h" 24 25 ··· 337 336 .gpl_only = false, 338 337 .ret_type = RET_VOID, 339 338 .arg1_type = ARG_PTR_TO_SPIN_LOCK, 339 + .arg1_btf_id = BPF_PTR_POISON, 340 340 }; 341 341 342 342 static inline void __bpf_spin_unlock_irqrestore(struct bpf_spin_lock *lock) ··· 360 358 .gpl_only = false, 361 359 .ret_type = RET_VOID, 362 360 .arg1_type = ARG_PTR_TO_SPIN_LOCK, 361 + .arg1_btf_id = BPF_PTR_POISON, 363 362 }; 364 363 365 364 void copy_map_value_locked(struct bpf_map *map, void *dst, void *src, ··· 1736 1733 1737 1734 obj -= field->list_head.node_offset; 1738 1735 head = head->next; 1739 - /* TODO: Rework later */ 1740 - kfree(obj); 1736 + /* The contained type can also have resources, including a 1737 + * bpf_list_head which needs to be freed. 1738 + */ 1739 + bpf_obj_free_fields(field->list_head.value_rec, obj); 1740 + /* bpf_mem_free requires migrate_disable(), since we can be 1741 + * called from map free path as well apart from BPF program (as 1742 + * part of map ops doing bpf_obj_free_fields). 1743 + */ 1744 + migrate_disable(); 1745 + bpf_mem_free(&bpf_global_ma, obj); 1746 + migrate_enable(); 1741 1747 } 1742 1748 } 1743 1749 1744 - BTF_SET8_START(tracing_btf_ids) 1750 + __diag_push(); 1751 + __diag_ignore_all("-Wmissing-prototypes", 1752 + "Global functions as their definitions will be in vmlinux BTF"); 1753 + 1754 + void *bpf_obj_new_impl(u64 local_type_id__k, void *meta__ign) 1755 + { 1756 + struct btf_struct_meta *meta = meta__ign; 1757 + u64 size = local_type_id__k; 1758 + void *p; 1759 + 1760 + if (unlikely(!bpf_global_ma_set)) 1761 + return NULL; 1762 + p = bpf_mem_alloc(&bpf_global_ma, size); 1763 + if (!p) 1764 + return NULL; 1765 + if (meta) 1766 + bpf_obj_init(meta->field_offs, p); 1767 + return p; 1768 + } 1769 + 1770 + void bpf_obj_drop_impl(void *p__alloc, void *meta__ign) 1771 + { 1772 + struct btf_struct_meta *meta = meta__ign; 1773 + void *p = p__alloc; 1774 + 1775 + if (meta) 1776 + bpf_obj_free_fields(meta->record, p); 1777 + bpf_mem_free(&bpf_global_ma, p); 1778 + } 1779 + 1780 + static void __bpf_list_add(struct bpf_list_node *node, struct bpf_list_head *head, bool tail) 1781 + { 1782 + struct list_head *n = (void *)node, *h = (void *)head; 1783 + 1784 + if (unlikely(!h->next)) 1785 + INIT_LIST_HEAD(h); 1786 + if (unlikely(!n->next)) 1787 + INIT_LIST_HEAD(n); 1788 + tail ? list_add_tail(n, h) : list_add(n, h); 1789 + } 1790 + 1791 + void bpf_list_push_front(struct bpf_list_head *head, struct bpf_list_node *node) 1792 + { 1793 + return __bpf_list_add(node, head, false); 1794 + } 1795 + 1796 + void bpf_list_push_back(struct bpf_list_head *head, struct bpf_list_node *node) 1797 + { 1798 + return __bpf_list_add(node, head, true); 1799 + } 1800 + 1801 + static struct bpf_list_node *__bpf_list_del(struct bpf_list_head *head, bool tail) 1802 + { 1803 + struct list_head *n, *h = (void *)head; 1804 + 1805 + if (unlikely(!h->next)) 1806 + INIT_LIST_HEAD(h); 1807 + if (list_empty(h)) 1808 + return NULL; 1809 + n = tail ? h->prev : h->next; 1810 + list_del_init(n); 1811 + return (struct bpf_list_node *)n; 1812 + } 1813 + 1814 + struct bpf_list_node *bpf_list_pop_front(struct bpf_list_head *head) 1815 + { 1816 + return __bpf_list_del(head, false); 1817 + } 1818 + 1819 + struct bpf_list_node *bpf_list_pop_back(struct bpf_list_head *head) 1820 + { 1821 + return __bpf_list_del(head, true); 1822 + } 1823 + 1824 + __diag_pop(); 1825 + 1826 + BTF_SET8_START(generic_btf_ids) 1745 1827 #ifdef CONFIG_KEXEC_CORE 1746 1828 BTF_ID_FLAGS(func, crash_kexec, KF_DESTRUCTIVE) 1747 1829 #endif 1748 - BTF_SET8_END(tracing_btf_ids) 1830 + BTF_ID_FLAGS(func, bpf_obj_new_impl, KF_ACQUIRE | KF_RET_NULL) 1831 + BTF_ID_FLAGS(func, bpf_obj_drop_impl, KF_RELEASE) 1832 + BTF_ID_FLAGS(func, bpf_list_push_front) 1833 + BTF_ID_FLAGS(func, bpf_list_push_back) 1834 + BTF_ID_FLAGS(func, bpf_list_pop_front, KF_ACQUIRE | KF_RET_NULL) 1835 + BTF_ID_FLAGS(func, bpf_list_pop_back, KF_ACQUIRE | KF_RET_NULL) 1836 + BTF_SET8_END(generic_btf_ids) 1749 1837 1750 - static const struct btf_kfunc_id_set tracing_kfunc_set = { 1838 + static const struct btf_kfunc_id_set generic_kfunc_set = { 1751 1839 .owner = THIS_MODULE, 1752 - .set = &tracing_btf_ids, 1840 + .set = &generic_btf_ids, 1753 1841 }; 1754 1842 1755 1843 static int __init kfunc_init(void) 1756 1844 { 1757 - return register_btf_kfunc_id_set(BPF_PROG_TYPE_TRACING, &tracing_kfunc_set); 1845 + int ret; 1846 + 1847 + ret = register_btf_kfunc_id_set(BPF_PROG_TYPE_TRACING, &generic_kfunc_set); 1848 + if (ret) 1849 + return ret; 1850 + return register_btf_kfunc_id_set(BPF_PROG_TYPE_SCHED_CLS, &generic_kfunc_set); 1758 1851 } 1759 1852 1760 1853 late_initcall(kfunc_init);
+35 -13
kernel/bpf/map_in_map.c
··· 12 12 struct bpf_map *inner_map, *inner_map_meta; 13 13 u32 inner_map_meta_size; 14 14 struct fd f; 15 + int ret; 15 16 16 17 f = fdget(inner_map_ufd); 17 18 inner_map = __bpf_map_get(f); ··· 21 20 22 21 /* Does not support >1 level map-in-map */ 23 22 if (inner_map->inner_map_meta) { 24 - fdput(f); 25 - return ERR_PTR(-EINVAL); 23 + ret = -EINVAL; 24 + goto put; 26 25 } 27 26 28 27 if (!inner_map->ops->map_meta_equal) { 29 - fdput(f); 30 - return ERR_PTR(-ENOTSUPP); 31 - } 32 - 33 - if (btf_record_has_field(inner_map->record, BPF_SPIN_LOCK)) { 34 - fdput(f); 35 - return ERR_PTR(-ENOTSUPP); 28 + ret = -ENOTSUPP; 29 + goto put; 36 30 } 37 31 38 32 inner_map_meta_size = sizeof(*inner_map_meta); ··· 37 41 38 42 inner_map_meta = kzalloc(inner_map_meta_size, GFP_USER); 39 43 if (!inner_map_meta) { 40 - fdput(f); 41 - return ERR_PTR(-ENOMEM); 44 + ret = -ENOMEM; 45 + goto put; 42 46 } 43 47 44 48 inner_map_meta->map_type = inner_map->map_type; ··· 46 50 inner_map_meta->value_size = inner_map->value_size; 47 51 inner_map_meta->map_flags = inner_map->map_flags; 48 52 inner_map_meta->max_entries = inner_map->max_entries; 53 + 49 54 inner_map_meta->record = btf_record_dup(inner_map->record); 50 55 if (IS_ERR(inner_map_meta->record)) { 51 56 /* btf_record_dup returns NULL or valid pointer in case of 52 57 * invalid/empty/valid, but ERR_PTR in case of errors. During 53 58 * equality NULL or IS_ERR is equivalent. 54 59 */ 55 - fdput(f); 56 - return ERR_CAST(inner_map_meta->record); 60 + ret = PTR_ERR(inner_map_meta->record); 61 + goto free; 57 62 } 63 + if (inner_map_meta->record) { 64 + struct btf_field_offs *field_offs; 65 + /* If btf_record is !IS_ERR_OR_NULL, then field_offs is always 66 + * valid. 67 + */ 68 + field_offs = kmemdup(inner_map->field_offs, sizeof(*inner_map->field_offs), GFP_KERNEL | __GFP_NOWARN); 69 + if (!field_offs) { 70 + ret = -ENOMEM; 71 + goto free_rec; 72 + } 73 + inner_map_meta->field_offs = field_offs; 74 + } 75 + /* Note: We must use the same BTF, as we also used btf_record_dup above 76 + * which relies on BTF being same for both maps, as some members like 77 + * record->fields.list_head have pointers like value_rec pointing into 78 + * inner_map->btf. 79 + */ 58 80 if (inner_map->btf) { 59 81 btf_get(inner_map->btf); 60 82 inner_map_meta->btf = inner_map->btf; ··· 88 74 89 75 fdput(f); 90 76 return inner_map_meta; 77 + free_rec: 78 + btf_record_free(inner_map_meta->record); 79 + free: 80 + kfree(inner_map_meta); 81 + put: 82 + fdput(f); 83 + return ERR_PTR(ret); 91 84 } 92 85 93 86 void bpf_map_meta_free(struct bpf_map *map_meta) 94 87 { 88 + kfree(map_meta->field_offs); 95 89 bpf_map_free_record(map_meta); 96 90 btf_put(map_meta->btf); 97 91 kfree(map_meta);
+37 -5
kernel/bpf/syscall.c
··· 537 537 btf_put(rec->fields[i].kptr.btf); 538 538 break; 539 539 case BPF_LIST_HEAD: 540 + case BPF_LIST_NODE: 540 541 /* Nothing to release for bpf_list_head */ 541 542 break; 542 543 default: ··· 583 582 } 584 583 break; 585 584 case BPF_LIST_HEAD: 585 + case BPF_LIST_NODE: 586 586 /* Nothing to acquire for bpf_list_head */ 587 587 break; 588 588 default: ··· 611 609 if (rec_a->cnt != rec_b->cnt) 612 610 return false; 613 611 size = offsetof(struct btf_record, fields[rec_a->cnt]); 612 + /* btf_parse_fields uses kzalloc to allocate a btf_record, so unused 613 + * members are zeroed out. So memcmp is safe to do without worrying 614 + * about padding/unused fields. 615 + * 616 + * While spin_lock, timer, and kptr have no relation to map BTF, 617 + * list_head metadata is specific to map BTF, the btf and value_rec 618 + * members in particular. btf is the map BTF, while value_rec points to 619 + * btf_record in that map BTF. 620 + * 621 + * So while by default, we don't rely on the map BTF (which the records 622 + * were parsed from) matching for both records, which is not backwards 623 + * compatible, in case list_head is part of it, we implicitly rely on 624 + * that by way of depending on memcmp succeeding for it. 625 + */ 614 626 return !memcmp(rec_a, rec_b, size); 615 627 } 616 628 ··· 664 648 continue; 665 649 bpf_list_head_free(field, field_ptr, obj + rec->spin_lock_off); 666 650 break; 651 + case BPF_LIST_NODE: 652 + break; 667 653 default: 668 654 WARN_ON_ONCE(1); 669 655 continue; ··· 677 659 static void bpf_map_free_deferred(struct work_struct *work) 678 660 { 679 661 struct bpf_map *map = container_of(work, struct bpf_map, work); 662 + struct btf_field_offs *foffs = map->field_offs; 663 + struct btf_record *rec = map->record; 680 664 681 665 security_bpf_map_free(map); 682 - kfree(map->field_offs); 683 666 bpf_map_release_memcg(map); 684 - /* implementation dependent freeing, map_free callback also does 685 - * bpf_map_free_record, if needed. 686 - */ 667 + /* implementation dependent freeing */ 687 668 map->ops->map_free(map); 669 + /* Delay freeing of field_offs and btf_record for maps, as map_free 670 + * callback usually needs access to them. It is better to do it here 671 + * than require each callback to do the free itself manually. 672 + * 673 + * Note that the btf_record stashed in map->inner_map_meta->record was 674 + * already freed using the map_free callback for map in map case which 675 + * eventually calls bpf_map_free_meta, since inner_map_meta is only a 676 + * template bpf_map struct used during verification. 677 + */ 678 + kfree(foffs); 679 + btf_record_free(rec); 688 680 } 689 681 690 682 static void bpf_map_put_uref(struct bpf_map *map) ··· 1038 1010 if (map->map_type != BPF_MAP_TYPE_HASH && 1039 1011 map->map_type != BPF_MAP_TYPE_LRU_HASH && 1040 1012 map->map_type != BPF_MAP_TYPE_ARRAY) { 1041 - return -EOPNOTSUPP; 1013 + ret = -EOPNOTSUPP; 1042 1014 goto free_map_tab; 1043 1015 } 1044 1016 break; ··· 1067 1039 } 1068 1040 } 1069 1041 } 1042 + 1043 + ret = btf_check_and_fixup_fields(btf, map->record); 1044 + if (ret < 0) 1045 + goto free_map_tab; 1070 1046 1071 1047 if (map->ops->map_check_btf) { 1072 1048 ret = map->ops->map_check_btf(map, btf, key_type, value_type);
+1142 -78
kernel/bpf/verifier.c
··· 451 451 type == PTR_TO_SOCK_COMMON; 452 452 } 453 453 454 + static struct btf_record *reg_btf_record(const struct bpf_reg_state *reg) 455 + { 456 + struct btf_record *rec = NULL; 457 + struct btf_struct_meta *meta; 458 + 459 + if (reg->type == PTR_TO_MAP_VALUE) { 460 + rec = reg->map_ptr->record; 461 + } else if (reg->type == (PTR_TO_BTF_ID | MEM_ALLOC)) { 462 + meta = btf_find_struct_meta(reg->btf, reg->btf_id); 463 + if (meta) 464 + rec = meta->record; 465 + } 466 + return rec; 467 + } 468 + 454 469 static bool reg_may_point_to_spin_lock(const struct bpf_reg_state *reg) 455 470 { 456 - return reg->type == PTR_TO_MAP_VALUE && 457 - btf_record_has_field(reg->map_ptr->record, BPF_SPIN_LOCK); 471 + return btf_record_has_field(reg_btf_record(reg), BPF_SPIN_LOCK); 458 472 } 459 473 460 474 static bool type_is_rdonly_mem(u32 type) ··· 1221 1207 } 1222 1208 dst_state->speculative = src->speculative; 1223 1209 dst_state->curframe = src->curframe; 1224 - dst_state->active_spin_lock = src->active_spin_lock; 1210 + dst_state->active_lock.ptr = src->active_lock.ptr; 1211 + dst_state->active_lock.id = src->active_lock.id; 1225 1212 dst_state->branches = src->branches; 1226 1213 dst_state->parent = src->parent; 1227 1214 dst_state->first_insn_idx = src->first_insn_idx; ··· 4702 4687 return -EACCES; 4703 4688 } 4704 4689 4705 - if (env->ops->btf_struct_access) { 4690 + if (env->ops->btf_struct_access && !type_is_alloc(reg->type)) { 4691 + if (!btf_is_kernel(reg->btf)) { 4692 + verbose(env, "verifier internal error: reg->btf must be kernel btf\n"); 4693 + return -EFAULT; 4694 + } 4706 4695 ret = env->ops->btf_struct_access(&env->log, reg, off, size, atype, &btf_id, &flag); 4707 4696 } else { 4708 - if (atype != BPF_READ) { 4697 + /* Writes are permitted with default btf_struct_access for 4698 + * program allocated objects (which always have ref_obj_id > 0), 4699 + * but not for untrusted PTR_TO_BTF_ID | MEM_ALLOC. 4700 + */ 4701 + if (atype != BPF_READ && reg->type != (PTR_TO_BTF_ID | MEM_ALLOC)) { 4709 4702 verbose(env, "only read is supported\n"); 4710 4703 return -EACCES; 4704 + } 4705 + 4706 + if (type_is_alloc(reg->type) && !reg->ref_obj_id) { 4707 + verbose(env, "verifier internal error: ref_obj_id for allocated object must be non-zero\n"); 4708 + return -EFAULT; 4711 4709 } 4712 4710 4713 4711 ret = btf_struct_access(&env->log, reg, off, size, atype, &btf_id, &flag); ··· 5550 5522 return err; 5551 5523 } 5552 5524 5553 - int check_kfunc_mem_size_reg(struct bpf_verifier_env *env, struct bpf_reg_state *reg, 5554 - u32 regno) 5525 + static int check_kfunc_mem_size_reg(struct bpf_verifier_env *env, struct bpf_reg_state *reg, 5526 + u32 regno) 5555 5527 { 5556 5528 struct bpf_reg_state *mem_reg = &cur_regs(env)[regno - 1]; 5557 5529 bool may_be_null = type_may_be_null(mem_reg->type); ··· 5579 5551 } 5580 5552 5581 5553 /* Implementation details: 5582 - * bpf_map_lookup returns PTR_TO_MAP_VALUE_OR_NULL 5554 + * bpf_map_lookup returns PTR_TO_MAP_VALUE_OR_NULL. 5555 + * bpf_obj_new returns PTR_TO_BTF_ID | MEM_ALLOC | PTR_MAYBE_NULL. 5583 5556 * Two bpf_map_lookups (even with the same key) will have different reg->id. 5584 - * For traditional PTR_TO_MAP_VALUE the verifier clears reg->id after 5585 - * value_or_null->value transition, since the verifier only cares about 5586 - * the range of access to valid map value pointer and doesn't care about actual 5587 - * address of the map element. 5557 + * Two separate bpf_obj_new will also have different reg->id. 5558 + * For traditional PTR_TO_MAP_VALUE or PTR_TO_BTF_ID | MEM_ALLOC, the verifier 5559 + * clears reg->id after value_or_null->value transition, since the verifier only 5560 + * cares about the range of access to valid map value pointer and doesn't care 5561 + * about actual address of the map element. 5588 5562 * For maps with 'struct bpf_spin_lock' inside map value the verifier keeps 5589 5563 * reg->id > 0 after value_or_null->value transition. By doing so 5590 5564 * two bpf_map_lookups will be considered two different pointers that 5591 - * point to different bpf_spin_locks. 5565 + * point to different bpf_spin_locks. Likewise for pointers to allocated objects 5566 + * returned from bpf_obj_new. 5592 5567 * The verifier allows taking only one bpf_spin_lock at a time to avoid 5593 5568 * dead-locks. 5594 5569 * Since only one bpf_spin_lock is allowed the checks are simpler than 5595 5570 * reg_is_refcounted() logic. The verifier needs to remember only 5596 5571 * one spin_lock instead of array of acquired_refs. 5597 - * cur_state->active_spin_lock remembers which map value element got locked 5598 - * and clears it after bpf_spin_unlock. 5572 + * cur_state->active_lock remembers which map value element or allocated 5573 + * object got locked and clears it after bpf_spin_unlock. 5599 5574 */ 5600 5575 static int process_spin_lock(struct bpf_verifier_env *env, int regno, 5601 5576 bool is_lock) ··· 5606 5575 struct bpf_reg_state *regs = cur_regs(env), *reg = &regs[regno]; 5607 5576 struct bpf_verifier_state *cur = env->cur_state; 5608 5577 bool is_const = tnum_is_const(reg->var_off); 5609 - struct bpf_map *map = reg->map_ptr; 5610 5578 u64 val = reg->var_off.value; 5579 + struct bpf_map *map = NULL; 5580 + struct btf *btf = NULL; 5581 + struct btf_record *rec; 5611 5582 5612 5583 if (!is_const) { 5613 5584 verbose(env, ··· 5617 5584 regno); 5618 5585 return -EINVAL; 5619 5586 } 5620 - if (!map->btf) { 5621 - verbose(env, 5622 - "map '%s' has to have BTF in order to use bpf_spin_lock\n", 5623 - map->name); 5587 + if (reg->type == PTR_TO_MAP_VALUE) { 5588 + map = reg->map_ptr; 5589 + if (!map->btf) { 5590 + verbose(env, 5591 + "map '%s' has to have BTF in order to use bpf_spin_lock\n", 5592 + map->name); 5593 + return -EINVAL; 5594 + } 5595 + } else { 5596 + btf = reg->btf; 5597 + } 5598 + 5599 + rec = reg_btf_record(reg); 5600 + if (!btf_record_has_field(rec, BPF_SPIN_LOCK)) { 5601 + verbose(env, "%s '%s' has no valid bpf_spin_lock\n", map ? "map" : "local", 5602 + map ? map->name : "kptr"); 5624 5603 return -EINVAL; 5625 5604 } 5626 - if (!btf_record_has_field(map->record, BPF_SPIN_LOCK)) { 5627 - verbose(env, "map '%s' has no valid bpf_spin_lock\n", map->name); 5628 - return -EINVAL; 5629 - } 5630 - if (map->record->spin_lock_off != val + reg->off) { 5605 + if (rec->spin_lock_off != val + reg->off) { 5631 5606 verbose(env, "off %lld doesn't point to 'struct bpf_spin_lock' that is at %d\n", 5632 - val + reg->off, map->record->spin_lock_off); 5607 + val + reg->off, rec->spin_lock_off); 5633 5608 return -EINVAL; 5634 5609 } 5635 5610 if (is_lock) { 5636 - if (cur->active_spin_lock) { 5611 + if (cur->active_lock.ptr) { 5637 5612 verbose(env, 5638 5613 "Locking two bpf_spin_locks are not allowed\n"); 5639 5614 return -EINVAL; 5640 5615 } 5641 - cur->active_spin_lock = reg->id; 5616 + if (map) 5617 + cur->active_lock.ptr = map; 5618 + else 5619 + cur->active_lock.ptr = btf; 5620 + cur->active_lock.id = reg->id; 5642 5621 } else { 5643 - if (!cur->active_spin_lock) { 5622 + struct bpf_func_state *fstate = cur_func(env); 5623 + void *ptr; 5624 + int i; 5625 + 5626 + if (map) 5627 + ptr = map; 5628 + else 5629 + ptr = btf; 5630 + 5631 + if (!cur->active_lock.ptr) { 5644 5632 verbose(env, "bpf_spin_unlock without taking a lock\n"); 5645 5633 return -EINVAL; 5646 5634 } 5647 - if (cur->active_spin_lock != reg->id) { 5635 + if (cur->active_lock.ptr != ptr || 5636 + cur->active_lock.id != reg->id) { 5648 5637 verbose(env, "bpf_spin_unlock of different lock\n"); 5649 5638 return -EINVAL; 5650 5639 } 5651 - cur->active_spin_lock = 0; 5640 + cur->active_lock.ptr = NULL; 5641 + cur->active_lock.id = 0; 5642 + 5643 + for (i = 0; i < fstate->acquired_refs; i++) { 5644 + int err; 5645 + 5646 + /* Complain on error because this reference state cannot 5647 + * be freed before this point, as bpf_spin_lock critical 5648 + * section does not allow functions that release the 5649 + * allocated object immediately. 5650 + */ 5651 + if (!fstate->refs[i].release_on_unlock) 5652 + continue; 5653 + err = release_reference(env, fstate->refs[i].id); 5654 + if (err) { 5655 + verbose(env, "failed to release release_on_unlock reference"); 5656 + return err; 5657 + } 5658 + } 5652 5659 } 5653 5660 return 0; 5654 5661 } ··· 5875 5802 }, 5876 5803 }; 5877 5804 5805 + static const struct bpf_reg_types spin_lock_types = { 5806 + .types = { 5807 + PTR_TO_MAP_VALUE, 5808 + PTR_TO_BTF_ID | MEM_ALLOC, 5809 + } 5810 + }; 5811 + 5878 5812 static const struct bpf_reg_types fullsock_types = { .types = { PTR_TO_SOCKET } }; 5879 5813 static const struct bpf_reg_types scalar_types = { .types = { SCALAR_VALUE } }; 5880 5814 static const struct bpf_reg_types context_types = { .types = { PTR_TO_CTX } }; 5881 5815 static const struct bpf_reg_types ringbuf_mem_types = { .types = { PTR_TO_MEM | MEM_RINGBUF } }; 5882 5816 static const struct bpf_reg_types const_map_ptr_types = { .types = { CONST_PTR_TO_MAP } }; 5883 5817 static const struct bpf_reg_types btf_ptr_types = { .types = { PTR_TO_BTF_ID } }; 5884 - static const struct bpf_reg_types spin_lock_types = { .types = { PTR_TO_MAP_VALUE } }; 5885 5818 static const struct bpf_reg_types percpu_btf_ptr_types = { .types = { PTR_TO_BTF_ID | MEM_PERCPU } }; 5886 5819 static const struct bpf_reg_types func_ptr_types = { .types = { PTR_TO_FUNC } }; 5887 5820 static const struct bpf_reg_types stack_ptr_types = { .types = { PTR_TO_STACK } }; ··· 6012 5933 return -EACCES; 6013 5934 } 6014 5935 } 5936 + } else if (type_is_alloc(reg->type)) { 5937 + if (meta->func_id != BPF_FUNC_spin_lock && meta->func_id != BPF_FUNC_spin_unlock) { 5938 + verbose(env, "verifier internal error: unimplemented handling of MEM_ALLOC\n"); 5939 + return -EFAULT; 5940 + } 6015 5941 } 6016 5942 6017 5943 return 0; ··· 6057 5973 * fixed offset. 6058 5974 */ 6059 5975 case PTR_TO_BTF_ID: 5976 + case PTR_TO_BTF_ID | MEM_ALLOC: 6060 5977 /* When referenced PTR_TO_BTF_ID is passed to release function, 6061 5978 * it's fixed offset must be 0. In the other cases, fixed offset 6062 5979 * can be non-zero. ··· 6133 6048 goto skip_type_check; 6134 6049 6135 6050 /* arg_btf_id and arg_size are in a union. */ 6136 - if (base_type(arg_type) == ARG_PTR_TO_BTF_ID) 6051 + if (base_type(arg_type) == ARG_PTR_TO_BTF_ID || 6052 + base_type(arg_type) == ARG_PTR_TO_SPIN_LOCK) 6137 6053 arg_btf_id = fn->arg_btf_id[arg]; 6138 6054 6139 6055 err = check_reg_type(env, regno, arg_type, arg_btf_id, meta); ··· 6752 6666 int i; 6753 6667 6754 6668 for (i = 0; i < ARRAY_SIZE(fn->arg_type); i++) { 6755 - if (base_type(fn->arg_type[i]) == ARG_PTR_TO_BTF_ID && !fn->arg_btf_id[i]) 6756 - return false; 6757 - 6669 + if (base_type(fn->arg_type[i]) == ARG_PTR_TO_BTF_ID) 6670 + return !!fn->arg_btf_id[i]; 6671 + if (base_type(fn->arg_type[i]) == ARG_PTR_TO_SPIN_LOCK) 6672 + return fn->arg_btf_id[i] == BPF_PTR_POISON; 6758 6673 if (base_type(fn->arg_type[i]) != ARG_PTR_TO_BTF_ID && fn->arg_btf_id[i] && 6759 6674 /* arg_btf_id and arg_size are in a union. */ 6760 6675 (base_type(fn->arg_type[i]) != ARG_PTR_TO_MEM || ··· 7882 7795 } 7883 7796 } 7884 7797 7798 + struct bpf_kfunc_call_arg_meta { 7799 + /* In parameters */ 7800 + struct btf *btf; 7801 + u32 func_id; 7802 + u32 kfunc_flags; 7803 + const struct btf_type *func_proto; 7804 + const char *func_name; 7805 + /* Out parameters */ 7806 + u32 ref_obj_id; 7807 + u8 release_regno; 7808 + bool r0_rdonly; 7809 + u64 r0_size; 7810 + struct { 7811 + u64 value; 7812 + bool found; 7813 + } arg_constant; 7814 + struct { 7815 + struct btf *btf; 7816 + u32 btf_id; 7817 + } arg_obj_drop; 7818 + struct { 7819 + struct btf_field *field; 7820 + } arg_list_head; 7821 + }; 7822 + 7823 + static bool is_kfunc_acquire(struct bpf_kfunc_call_arg_meta *meta) 7824 + { 7825 + return meta->kfunc_flags & KF_ACQUIRE; 7826 + } 7827 + 7828 + static bool is_kfunc_ret_null(struct bpf_kfunc_call_arg_meta *meta) 7829 + { 7830 + return meta->kfunc_flags & KF_RET_NULL; 7831 + } 7832 + 7833 + static bool is_kfunc_release(struct bpf_kfunc_call_arg_meta *meta) 7834 + { 7835 + return meta->kfunc_flags & KF_RELEASE; 7836 + } 7837 + 7838 + static bool is_kfunc_trusted_args(struct bpf_kfunc_call_arg_meta *meta) 7839 + { 7840 + return meta->kfunc_flags & KF_TRUSTED_ARGS; 7841 + } 7842 + 7843 + static bool is_kfunc_sleepable(struct bpf_kfunc_call_arg_meta *meta) 7844 + { 7845 + return meta->kfunc_flags & KF_SLEEPABLE; 7846 + } 7847 + 7848 + static bool is_kfunc_destructive(struct bpf_kfunc_call_arg_meta *meta) 7849 + { 7850 + return meta->kfunc_flags & KF_DESTRUCTIVE; 7851 + } 7852 + 7853 + static bool is_kfunc_arg_kptr_get(struct bpf_kfunc_call_arg_meta *meta, int arg) 7854 + { 7855 + return arg == 0 && (meta->kfunc_flags & KF_KPTR_GET); 7856 + } 7857 + 7858 + static bool __kfunc_param_match_suffix(const struct btf *btf, 7859 + const struct btf_param *arg, 7860 + const char *suffix) 7861 + { 7862 + int suffix_len = strlen(suffix), len; 7863 + const char *param_name; 7864 + 7865 + /* In the future, this can be ported to use BTF tagging */ 7866 + param_name = btf_name_by_offset(btf, arg->name_off); 7867 + if (str_is_empty(param_name)) 7868 + return false; 7869 + len = strlen(param_name); 7870 + if (len < suffix_len) 7871 + return false; 7872 + param_name += len - suffix_len; 7873 + return !strncmp(param_name, suffix, suffix_len); 7874 + } 7875 + 7876 + static bool is_kfunc_arg_mem_size(const struct btf *btf, 7877 + const struct btf_param *arg, 7878 + const struct bpf_reg_state *reg) 7879 + { 7880 + const struct btf_type *t; 7881 + 7882 + t = btf_type_skip_modifiers(btf, arg->type, NULL); 7883 + if (!btf_type_is_scalar(t) || reg->type != SCALAR_VALUE) 7884 + return false; 7885 + 7886 + return __kfunc_param_match_suffix(btf, arg, "__sz"); 7887 + } 7888 + 7889 + static bool is_kfunc_arg_constant(const struct btf *btf, const struct btf_param *arg) 7890 + { 7891 + return __kfunc_param_match_suffix(btf, arg, "__k"); 7892 + } 7893 + 7894 + static bool is_kfunc_arg_ignore(const struct btf *btf, const struct btf_param *arg) 7895 + { 7896 + return __kfunc_param_match_suffix(btf, arg, "__ign"); 7897 + } 7898 + 7899 + static bool is_kfunc_arg_alloc_obj(const struct btf *btf, const struct btf_param *arg) 7900 + { 7901 + return __kfunc_param_match_suffix(btf, arg, "__alloc"); 7902 + } 7903 + 7904 + static bool is_kfunc_arg_scalar_with_name(const struct btf *btf, 7905 + const struct btf_param *arg, 7906 + const char *name) 7907 + { 7908 + int len, target_len = strlen(name); 7909 + const char *param_name; 7910 + 7911 + param_name = btf_name_by_offset(btf, arg->name_off); 7912 + if (str_is_empty(param_name)) 7913 + return false; 7914 + len = strlen(param_name); 7915 + if (len != target_len) 7916 + return false; 7917 + if (strcmp(param_name, name)) 7918 + return false; 7919 + 7920 + return true; 7921 + } 7922 + 7923 + enum { 7924 + KF_ARG_DYNPTR_ID, 7925 + KF_ARG_LIST_HEAD_ID, 7926 + KF_ARG_LIST_NODE_ID, 7927 + }; 7928 + 7929 + BTF_ID_LIST(kf_arg_btf_ids) 7930 + BTF_ID(struct, bpf_dynptr_kern) 7931 + BTF_ID(struct, bpf_list_head) 7932 + BTF_ID(struct, bpf_list_node) 7933 + 7934 + static bool __is_kfunc_ptr_arg_type(const struct btf *btf, 7935 + const struct btf_param *arg, int type) 7936 + { 7937 + const struct btf_type *t; 7938 + u32 res_id; 7939 + 7940 + t = btf_type_skip_modifiers(btf, arg->type, NULL); 7941 + if (!t) 7942 + return false; 7943 + if (!btf_type_is_ptr(t)) 7944 + return false; 7945 + t = btf_type_skip_modifiers(btf, t->type, &res_id); 7946 + if (!t) 7947 + return false; 7948 + return btf_types_are_same(btf, res_id, btf_vmlinux, kf_arg_btf_ids[type]); 7949 + } 7950 + 7951 + static bool is_kfunc_arg_dynptr(const struct btf *btf, const struct btf_param *arg) 7952 + { 7953 + return __is_kfunc_ptr_arg_type(btf, arg, KF_ARG_DYNPTR_ID); 7954 + } 7955 + 7956 + static bool is_kfunc_arg_list_head(const struct btf *btf, const struct btf_param *arg) 7957 + { 7958 + return __is_kfunc_ptr_arg_type(btf, arg, KF_ARG_LIST_HEAD_ID); 7959 + } 7960 + 7961 + static bool is_kfunc_arg_list_node(const struct btf *btf, const struct btf_param *arg) 7962 + { 7963 + return __is_kfunc_ptr_arg_type(btf, arg, KF_ARG_LIST_NODE_ID); 7964 + } 7965 + 7966 + /* Returns true if struct is composed of scalars, 4 levels of nesting allowed */ 7967 + static bool __btf_type_is_scalar_struct(struct bpf_verifier_env *env, 7968 + const struct btf *btf, 7969 + const struct btf_type *t, int rec) 7970 + { 7971 + const struct btf_type *member_type; 7972 + const struct btf_member *member; 7973 + u32 i; 7974 + 7975 + if (!btf_type_is_struct(t)) 7976 + return false; 7977 + 7978 + for_each_member(i, t, member) { 7979 + const struct btf_array *array; 7980 + 7981 + member_type = btf_type_skip_modifiers(btf, member->type, NULL); 7982 + if (btf_type_is_struct(member_type)) { 7983 + if (rec >= 3) { 7984 + verbose(env, "max struct nesting depth exceeded\n"); 7985 + return false; 7986 + } 7987 + if (!__btf_type_is_scalar_struct(env, btf, member_type, rec + 1)) 7988 + return false; 7989 + continue; 7990 + } 7991 + if (btf_type_is_array(member_type)) { 7992 + array = btf_array(member_type); 7993 + if (!array->nelems) 7994 + return false; 7995 + member_type = btf_type_skip_modifiers(btf, array->type, NULL); 7996 + if (!btf_type_is_scalar(member_type)) 7997 + return false; 7998 + continue; 7999 + } 8000 + if (!btf_type_is_scalar(member_type)) 8001 + return false; 8002 + } 8003 + return true; 8004 + } 8005 + 8006 + 8007 + static u32 *reg2btf_ids[__BPF_REG_TYPE_MAX] = { 8008 + #ifdef CONFIG_NET 8009 + [PTR_TO_SOCKET] = &btf_sock_ids[BTF_SOCK_TYPE_SOCK], 8010 + [PTR_TO_SOCK_COMMON] = &btf_sock_ids[BTF_SOCK_TYPE_SOCK_COMMON], 8011 + [PTR_TO_TCP_SOCK] = &btf_sock_ids[BTF_SOCK_TYPE_TCP], 8012 + #endif 8013 + }; 8014 + 8015 + enum kfunc_ptr_arg_type { 8016 + KF_ARG_PTR_TO_CTX, 8017 + KF_ARG_PTR_TO_ALLOC_BTF_ID, /* Allocated object */ 8018 + KF_ARG_PTR_TO_KPTR, /* PTR_TO_KPTR but type specific */ 8019 + KF_ARG_PTR_TO_DYNPTR, 8020 + KF_ARG_PTR_TO_LIST_HEAD, 8021 + KF_ARG_PTR_TO_LIST_NODE, 8022 + KF_ARG_PTR_TO_BTF_ID, /* Also covers reg2btf_ids conversions */ 8023 + KF_ARG_PTR_TO_MEM, 8024 + KF_ARG_PTR_TO_MEM_SIZE, /* Size derived from next argument, skip it */ 8025 + }; 8026 + 8027 + enum special_kfunc_type { 8028 + KF_bpf_obj_new_impl, 8029 + KF_bpf_obj_drop_impl, 8030 + KF_bpf_list_push_front, 8031 + KF_bpf_list_push_back, 8032 + KF_bpf_list_pop_front, 8033 + KF_bpf_list_pop_back, 8034 + }; 8035 + 8036 + BTF_SET_START(special_kfunc_set) 8037 + BTF_ID(func, bpf_obj_new_impl) 8038 + BTF_ID(func, bpf_obj_drop_impl) 8039 + BTF_ID(func, bpf_list_push_front) 8040 + BTF_ID(func, bpf_list_push_back) 8041 + BTF_ID(func, bpf_list_pop_front) 8042 + BTF_ID(func, bpf_list_pop_back) 8043 + BTF_SET_END(special_kfunc_set) 8044 + 8045 + BTF_ID_LIST(special_kfunc_list) 8046 + BTF_ID(func, bpf_obj_new_impl) 8047 + BTF_ID(func, bpf_obj_drop_impl) 8048 + BTF_ID(func, bpf_list_push_front) 8049 + BTF_ID(func, bpf_list_push_back) 8050 + BTF_ID(func, bpf_list_pop_front) 8051 + BTF_ID(func, bpf_list_pop_back) 8052 + 8053 + static enum kfunc_ptr_arg_type 8054 + get_kfunc_ptr_arg_type(struct bpf_verifier_env *env, 8055 + struct bpf_kfunc_call_arg_meta *meta, 8056 + const struct btf_type *t, const struct btf_type *ref_t, 8057 + const char *ref_tname, const struct btf_param *args, 8058 + int argno, int nargs) 8059 + { 8060 + u32 regno = argno + 1; 8061 + struct bpf_reg_state *regs = cur_regs(env); 8062 + struct bpf_reg_state *reg = &regs[regno]; 8063 + bool arg_mem_size = false; 8064 + 8065 + /* In this function, we verify the kfunc's BTF as per the argument type, 8066 + * leaving the rest of the verification with respect to the register 8067 + * type to our caller. When a set of conditions hold in the BTF type of 8068 + * arguments, we resolve it to a known kfunc_ptr_arg_type. 8069 + */ 8070 + if (btf_get_prog_ctx_type(&env->log, meta->btf, t, resolve_prog_type(env->prog), argno)) 8071 + return KF_ARG_PTR_TO_CTX; 8072 + 8073 + if (is_kfunc_arg_alloc_obj(meta->btf, &args[argno])) 8074 + return KF_ARG_PTR_TO_ALLOC_BTF_ID; 8075 + 8076 + if (is_kfunc_arg_kptr_get(meta, argno)) { 8077 + if (!btf_type_is_ptr(ref_t)) { 8078 + verbose(env, "arg#0 BTF type must be a double pointer for kptr_get kfunc\n"); 8079 + return -EINVAL; 8080 + } 8081 + ref_t = btf_type_by_id(meta->btf, ref_t->type); 8082 + ref_tname = btf_name_by_offset(meta->btf, ref_t->name_off); 8083 + if (!btf_type_is_struct(ref_t)) { 8084 + verbose(env, "kernel function %s args#0 pointer type %s %s is not supported\n", 8085 + meta->func_name, btf_type_str(ref_t), ref_tname); 8086 + return -EINVAL; 8087 + } 8088 + return KF_ARG_PTR_TO_KPTR; 8089 + } 8090 + 8091 + if (is_kfunc_arg_dynptr(meta->btf, &args[argno])) 8092 + return KF_ARG_PTR_TO_DYNPTR; 8093 + 8094 + if (is_kfunc_arg_list_head(meta->btf, &args[argno])) 8095 + return KF_ARG_PTR_TO_LIST_HEAD; 8096 + 8097 + if (is_kfunc_arg_list_node(meta->btf, &args[argno])) 8098 + return KF_ARG_PTR_TO_LIST_NODE; 8099 + 8100 + if ((base_type(reg->type) == PTR_TO_BTF_ID || reg2btf_ids[base_type(reg->type)])) { 8101 + if (!btf_type_is_struct(ref_t)) { 8102 + verbose(env, "kernel function %s args#%d pointer type %s %s is not supported\n", 8103 + meta->func_name, argno, btf_type_str(ref_t), ref_tname); 8104 + return -EINVAL; 8105 + } 8106 + return KF_ARG_PTR_TO_BTF_ID; 8107 + } 8108 + 8109 + if (argno + 1 < nargs && is_kfunc_arg_mem_size(meta->btf, &args[argno + 1], &regs[regno + 1])) 8110 + arg_mem_size = true; 8111 + 8112 + /* This is the catch all argument type of register types supported by 8113 + * check_helper_mem_access. However, we only allow when argument type is 8114 + * pointer to scalar, or struct composed (recursively) of scalars. When 8115 + * arg_mem_size is true, the pointer can be void *. 8116 + */ 8117 + if (!btf_type_is_scalar(ref_t) && !__btf_type_is_scalar_struct(env, meta->btf, ref_t, 0) && 8118 + (arg_mem_size ? !btf_type_is_void(ref_t) : 1)) { 8119 + verbose(env, "arg#%d pointer type %s %s must point to %sscalar, or struct with scalar\n", 8120 + argno, btf_type_str(ref_t), ref_tname, arg_mem_size ? "void, " : ""); 8121 + return -EINVAL; 8122 + } 8123 + return arg_mem_size ? KF_ARG_PTR_TO_MEM_SIZE : KF_ARG_PTR_TO_MEM; 8124 + } 8125 + 8126 + static int process_kf_arg_ptr_to_btf_id(struct bpf_verifier_env *env, 8127 + struct bpf_reg_state *reg, 8128 + const struct btf_type *ref_t, 8129 + const char *ref_tname, u32 ref_id, 8130 + struct bpf_kfunc_call_arg_meta *meta, 8131 + int argno) 8132 + { 8133 + const struct btf_type *reg_ref_t; 8134 + bool strict_type_match = false; 8135 + const struct btf *reg_btf; 8136 + const char *reg_ref_tname; 8137 + u32 reg_ref_id; 8138 + 8139 + if (reg->type == PTR_TO_BTF_ID) { 8140 + reg_btf = reg->btf; 8141 + reg_ref_id = reg->btf_id; 8142 + } else { 8143 + reg_btf = btf_vmlinux; 8144 + reg_ref_id = *reg2btf_ids[base_type(reg->type)]; 8145 + } 8146 + 8147 + if (is_kfunc_trusted_args(meta) || (is_kfunc_release(meta) && reg->ref_obj_id)) 8148 + strict_type_match = true; 8149 + 8150 + reg_ref_t = btf_type_skip_modifiers(reg_btf, reg_ref_id, &reg_ref_id); 8151 + reg_ref_tname = btf_name_by_offset(reg_btf, reg_ref_t->name_off); 8152 + if (!btf_struct_ids_match(&env->log, reg_btf, reg_ref_id, reg->off, meta->btf, ref_id, strict_type_match)) { 8153 + verbose(env, "kernel function %s args#%d expected pointer to %s %s but R%d has a pointer to %s %s\n", 8154 + meta->func_name, argno, btf_type_str(ref_t), ref_tname, argno + 1, 8155 + btf_type_str(reg_ref_t), reg_ref_tname); 8156 + return -EINVAL; 8157 + } 8158 + return 0; 8159 + } 8160 + 8161 + static int process_kf_arg_ptr_to_kptr(struct bpf_verifier_env *env, 8162 + struct bpf_reg_state *reg, 8163 + const struct btf_type *ref_t, 8164 + const char *ref_tname, 8165 + struct bpf_kfunc_call_arg_meta *meta, 8166 + int argno) 8167 + { 8168 + struct btf_field *kptr_field; 8169 + 8170 + /* check_func_arg_reg_off allows var_off for 8171 + * PTR_TO_MAP_VALUE, but we need fixed offset to find 8172 + * off_desc. 8173 + */ 8174 + if (!tnum_is_const(reg->var_off)) { 8175 + verbose(env, "arg#0 must have constant offset\n"); 8176 + return -EINVAL; 8177 + } 8178 + 8179 + kptr_field = btf_record_find(reg->map_ptr->record, reg->off + reg->var_off.value, BPF_KPTR); 8180 + if (!kptr_field || kptr_field->type != BPF_KPTR_REF) { 8181 + verbose(env, "arg#0 no referenced kptr at map value offset=%llu\n", 8182 + reg->off + reg->var_off.value); 8183 + return -EINVAL; 8184 + } 8185 + 8186 + if (!btf_struct_ids_match(&env->log, meta->btf, ref_t->type, 0, kptr_field->kptr.btf, 8187 + kptr_field->kptr.btf_id, true)) { 8188 + verbose(env, "kernel function %s args#%d expected pointer to %s %s\n", 8189 + meta->func_name, argno, btf_type_str(ref_t), ref_tname); 8190 + return -EINVAL; 8191 + } 8192 + return 0; 8193 + } 8194 + 8195 + static int ref_set_release_on_unlock(struct bpf_verifier_env *env, u32 ref_obj_id) 8196 + { 8197 + struct bpf_func_state *state = cur_func(env); 8198 + struct bpf_reg_state *reg; 8199 + int i; 8200 + 8201 + /* bpf_spin_lock only allows calling list_push and list_pop, no BPF 8202 + * subprogs, no global functions. This means that the references would 8203 + * not be released inside the critical section but they may be added to 8204 + * the reference state, and the acquired_refs are never copied out for a 8205 + * different frame as BPF to BPF calls don't work in bpf_spin_lock 8206 + * critical sections. 8207 + */ 8208 + if (!ref_obj_id) { 8209 + verbose(env, "verifier internal error: ref_obj_id is zero for release_on_unlock\n"); 8210 + return -EFAULT; 8211 + } 8212 + for (i = 0; i < state->acquired_refs; i++) { 8213 + if (state->refs[i].id == ref_obj_id) { 8214 + if (state->refs[i].release_on_unlock) { 8215 + verbose(env, "verifier internal error: expected false release_on_unlock"); 8216 + return -EFAULT; 8217 + } 8218 + state->refs[i].release_on_unlock = true; 8219 + /* Now mark everyone sharing same ref_obj_id as untrusted */ 8220 + bpf_for_each_reg_in_vstate(env->cur_state, state, reg, ({ 8221 + if (reg->ref_obj_id == ref_obj_id) 8222 + reg->type |= PTR_UNTRUSTED; 8223 + })); 8224 + return 0; 8225 + } 8226 + } 8227 + verbose(env, "verifier internal error: ref state missing for ref_obj_id\n"); 8228 + return -EFAULT; 8229 + } 8230 + 8231 + /* Implementation details: 8232 + * 8233 + * Each register points to some region of memory, which we define as an 8234 + * allocation. Each allocation may embed a bpf_spin_lock which protects any 8235 + * special BPF objects (bpf_list_head, bpf_rb_root, etc.) part of the same 8236 + * allocation. The lock and the data it protects are colocated in the same 8237 + * memory region. 8238 + * 8239 + * Hence, everytime a register holds a pointer value pointing to such 8240 + * allocation, the verifier preserves a unique reg->id for it. 8241 + * 8242 + * The verifier remembers the lock 'ptr' and the lock 'id' whenever 8243 + * bpf_spin_lock is called. 8244 + * 8245 + * To enable this, lock state in the verifier captures two values: 8246 + * active_lock.ptr = Register's type specific pointer 8247 + * active_lock.id = A unique ID for each register pointer value 8248 + * 8249 + * Currently, PTR_TO_MAP_VALUE and PTR_TO_BTF_ID | MEM_ALLOC are the two 8250 + * supported register types. 8251 + * 8252 + * The active_lock.ptr in case of map values is the reg->map_ptr, and in case of 8253 + * allocated objects is the reg->btf pointer. 8254 + * 8255 + * The active_lock.id is non-unique for maps supporting direct_value_addr, as we 8256 + * can establish the provenance of the map value statically for each distinct 8257 + * lookup into such maps. They always contain a single map value hence unique 8258 + * IDs for each pseudo load pessimizes the algorithm and rejects valid programs. 8259 + * 8260 + * So, in case of global variables, they use array maps with max_entries = 1, 8261 + * hence their active_lock.ptr becomes map_ptr and id = 0 (since they all point 8262 + * into the same map value as max_entries is 1, as described above). 8263 + * 8264 + * In case of inner map lookups, the inner map pointer has same map_ptr as the 8265 + * outer map pointer (in verifier context), but each lookup into an inner map 8266 + * assigns a fresh reg->id to the lookup, so while lookups into distinct inner 8267 + * maps from the same outer map share the same map_ptr as active_lock.ptr, they 8268 + * will get different reg->id assigned to each lookup, hence different 8269 + * active_lock.id. 8270 + * 8271 + * In case of allocated objects, active_lock.ptr is the reg->btf, and the 8272 + * reg->id is a unique ID preserved after the NULL pointer check on the pointer 8273 + * returned from bpf_obj_new. Each allocation receives a new reg->id. 8274 + */ 8275 + static int check_reg_allocation_locked(struct bpf_verifier_env *env, struct bpf_reg_state *reg) 8276 + { 8277 + void *ptr; 8278 + u32 id; 8279 + 8280 + switch ((int)reg->type) { 8281 + case PTR_TO_MAP_VALUE: 8282 + ptr = reg->map_ptr; 8283 + break; 8284 + case PTR_TO_BTF_ID | MEM_ALLOC: 8285 + ptr = reg->btf; 8286 + break; 8287 + default: 8288 + verbose(env, "verifier internal error: unknown reg type for lock check\n"); 8289 + return -EFAULT; 8290 + } 8291 + id = reg->id; 8292 + 8293 + if (!env->cur_state->active_lock.ptr) 8294 + return -EINVAL; 8295 + if (env->cur_state->active_lock.ptr != ptr || 8296 + env->cur_state->active_lock.id != id) { 8297 + verbose(env, "held lock and object are not in the same allocation\n"); 8298 + return -EINVAL; 8299 + } 8300 + return 0; 8301 + } 8302 + 8303 + static bool is_bpf_list_api_kfunc(u32 btf_id) 8304 + { 8305 + return btf_id == special_kfunc_list[KF_bpf_list_push_front] || 8306 + btf_id == special_kfunc_list[KF_bpf_list_push_back] || 8307 + btf_id == special_kfunc_list[KF_bpf_list_pop_front] || 8308 + btf_id == special_kfunc_list[KF_bpf_list_pop_back]; 8309 + } 8310 + 8311 + static int process_kf_arg_ptr_to_list_head(struct bpf_verifier_env *env, 8312 + struct bpf_reg_state *reg, u32 regno, 8313 + struct bpf_kfunc_call_arg_meta *meta) 8314 + { 8315 + struct btf_field *field; 8316 + struct btf_record *rec; 8317 + u32 list_head_off; 8318 + 8319 + if (meta->btf != btf_vmlinux || !is_bpf_list_api_kfunc(meta->func_id)) { 8320 + verbose(env, "verifier internal error: bpf_list_head argument for unknown kfunc\n"); 8321 + return -EFAULT; 8322 + } 8323 + 8324 + if (!tnum_is_const(reg->var_off)) { 8325 + verbose(env, 8326 + "R%d doesn't have constant offset. bpf_list_head has to be at the constant offset\n", 8327 + regno); 8328 + return -EINVAL; 8329 + } 8330 + 8331 + rec = reg_btf_record(reg); 8332 + list_head_off = reg->off + reg->var_off.value; 8333 + field = btf_record_find(rec, list_head_off, BPF_LIST_HEAD); 8334 + if (!field) { 8335 + verbose(env, "bpf_list_head not found at offset=%u\n", list_head_off); 8336 + return -EINVAL; 8337 + } 8338 + 8339 + /* All functions require bpf_list_head to be protected using a bpf_spin_lock */ 8340 + if (check_reg_allocation_locked(env, reg)) { 8341 + verbose(env, "bpf_spin_lock at off=%d must be held for bpf_list_head\n", 8342 + rec->spin_lock_off); 8343 + return -EINVAL; 8344 + } 8345 + 8346 + if (meta->arg_list_head.field) { 8347 + verbose(env, "verifier internal error: repeating bpf_list_head arg\n"); 8348 + return -EFAULT; 8349 + } 8350 + meta->arg_list_head.field = field; 8351 + return 0; 8352 + } 8353 + 8354 + static int process_kf_arg_ptr_to_list_node(struct bpf_verifier_env *env, 8355 + struct bpf_reg_state *reg, u32 regno, 8356 + struct bpf_kfunc_call_arg_meta *meta) 8357 + { 8358 + const struct btf_type *et, *t; 8359 + struct btf_field *field; 8360 + struct btf_record *rec; 8361 + u32 list_node_off; 8362 + 8363 + if (meta->btf != btf_vmlinux || 8364 + (meta->func_id != special_kfunc_list[KF_bpf_list_push_front] && 8365 + meta->func_id != special_kfunc_list[KF_bpf_list_push_back])) { 8366 + verbose(env, "verifier internal error: bpf_list_node argument for unknown kfunc\n"); 8367 + return -EFAULT; 8368 + } 8369 + 8370 + if (!tnum_is_const(reg->var_off)) { 8371 + verbose(env, 8372 + "R%d doesn't have constant offset. bpf_list_node has to be at the constant offset\n", 8373 + regno); 8374 + return -EINVAL; 8375 + } 8376 + 8377 + rec = reg_btf_record(reg); 8378 + list_node_off = reg->off + reg->var_off.value; 8379 + field = btf_record_find(rec, list_node_off, BPF_LIST_NODE); 8380 + if (!field || field->offset != list_node_off) { 8381 + verbose(env, "bpf_list_node not found at offset=%u\n", list_node_off); 8382 + return -EINVAL; 8383 + } 8384 + 8385 + field = meta->arg_list_head.field; 8386 + 8387 + et = btf_type_by_id(field->list_head.btf, field->list_head.value_btf_id); 8388 + t = btf_type_by_id(reg->btf, reg->btf_id); 8389 + if (!btf_struct_ids_match(&env->log, reg->btf, reg->btf_id, 0, field->list_head.btf, 8390 + field->list_head.value_btf_id, true)) { 8391 + verbose(env, "operation on bpf_list_head expects arg#1 bpf_list_node at offset=%d " 8392 + "in struct %s, but arg is at offset=%d in struct %s\n", 8393 + field->list_head.node_offset, btf_name_by_offset(field->list_head.btf, et->name_off), 8394 + list_node_off, btf_name_by_offset(reg->btf, t->name_off)); 8395 + return -EINVAL; 8396 + } 8397 + 8398 + if (list_node_off != field->list_head.node_offset) { 8399 + verbose(env, "arg#1 offset=%d, but expected bpf_list_node at offset=%d in struct %s\n", 8400 + list_node_off, field->list_head.node_offset, 8401 + btf_name_by_offset(field->list_head.btf, et->name_off)); 8402 + return -EINVAL; 8403 + } 8404 + /* Set arg#1 for expiration after unlock */ 8405 + return ref_set_release_on_unlock(env, reg->ref_obj_id); 8406 + } 8407 + 8408 + static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_arg_meta *meta) 8409 + { 8410 + const char *func_name = meta->func_name, *ref_tname; 8411 + const struct btf *btf = meta->btf; 8412 + const struct btf_param *args; 8413 + u32 i, nargs; 8414 + int ret; 8415 + 8416 + args = (const struct btf_param *)(meta->func_proto + 1); 8417 + nargs = btf_type_vlen(meta->func_proto); 8418 + if (nargs > MAX_BPF_FUNC_REG_ARGS) { 8419 + verbose(env, "Function %s has %d > %d args\n", func_name, nargs, 8420 + MAX_BPF_FUNC_REG_ARGS); 8421 + return -EINVAL; 8422 + } 8423 + 8424 + /* Check that BTF function arguments match actual types that the 8425 + * verifier sees. 8426 + */ 8427 + for (i = 0; i < nargs; i++) { 8428 + struct bpf_reg_state *regs = cur_regs(env), *reg = &regs[i + 1]; 8429 + const struct btf_type *t, *ref_t, *resolve_ret; 8430 + enum bpf_arg_type arg_type = ARG_DONTCARE; 8431 + u32 regno = i + 1, ref_id, type_size; 8432 + bool is_ret_buf_sz = false; 8433 + int kf_arg_type; 8434 + 8435 + t = btf_type_skip_modifiers(btf, args[i].type, NULL); 8436 + 8437 + if (is_kfunc_arg_ignore(btf, &args[i])) 8438 + continue; 8439 + 8440 + if (btf_type_is_scalar(t)) { 8441 + if (reg->type != SCALAR_VALUE) { 8442 + verbose(env, "R%d is not a scalar\n", regno); 8443 + return -EINVAL; 8444 + } 8445 + 8446 + if (is_kfunc_arg_constant(meta->btf, &args[i])) { 8447 + if (meta->arg_constant.found) { 8448 + verbose(env, "verifier internal error: only one constant argument permitted\n"); 8449 + return -EFAULT; 8450 + } 8451 + if (!tnum_is_const(reg->var_off)) { 8452 + verbose(env, "R%d must be a known constant\n", regno); 8453 + return -EINVAL; 8454 + } 8455 + ret = mark_chain_precision(env, regno); 8456 + if (ret < 0) 8457 + return ret; 8458 + meta->arg_constant.found = true; 8459 + meta->arg_constant.value = reg->var_off.value; 8460 + } else if (is_kfunc_arg_scalar_with_name(btf, &args[i], "rdonly_buf_size")) { 8461 + meta->r0_rdonly = true; 8462 + is_ret_buf_sz = true; 8463 + } else if (is_kfunc_arg_scalar_with_name(btf, &args[i], "rdwr_buf_size")) { 8464 + is_ret_buf_sz = true; 8465 + } 8466 + 8467 + if (is_ret_buf_sz) { 8468 + if (meta->r0_size) { 8469 + verbose(env, "2 or more rdonly/rdwr_buf_size parameters for kfunc"); 8470 + return -EINVAL; 8471 + } 8472 + 8473 + if (!tnum_is_const(reg->var_off)) { 8474 + verbose(env, "R%d is not a const\n", regno); 8475 + return -EINVAL; 8476 + } 8477 + 8478 + meta->r0_size = reg->var_off.value; 8479 + ret = mark_chain_precision(env, regno); 8480 + if (ret) 8481 + return ret; 8482 + } 8483 + continue; 8484 + } 8485 + 8486 + if (!btf_type_is_ptr(t)) { 8487 + verbose(env, "Unrecognized arg#%d type %s\n", i, btf_type_str(t)); 8488 + return -EINVAL; 8489 + } 8490 + 8491 + if (reg->ref_obj_id) { 8492 + if (is_kfunc_release(meta) && meta->ref_obj_id) { 8493 + verbose(env, "verifier internal error: more than one arg with ref_obj_id R%d %u %u\n", 8494 + regno, reg->ref_obj_id, 8495 + meta->ref_obj_id); 8496 + return -EFAULT; 8497 + } 8498 + meta->ref_obj_id = reg->ref_obj_id; 8499 + if (is_kfunc_release(meta)) 8500 + meta->release_regno = regno; 8501 + } 8502 + 8503 + ref_t = btf_type_skip_modifiers(btf, t->type, &ref_id); 8504 + ref_tname = btf_name_by_offset(btf, ref_t->name_off); 8505 + 8506 + kf_arg_type = get_kfunc_ptr_arg_type(env, meta, t, ref_t, ref_tname, args, i, nargs); 8507 + if (kf_arg_type < 0) 8508 + return kf_arg_type; 8509 + 8510 + switch (kf_arg_type) { 8511 + case KF_ARG_PTR_TO_ALLOC_BTF_ID: 8512 + case KF_ARG_PTR_TO_BTF_ID: 8513 + if (!is_kfunc_trusted_args(meta)) 8514 + break; 8515 + if (!reg->ref_obj_id) { 8516 + verbose(env, "R%d must be referenced\n", regno); 8517 + return -EINVAL; 8518 + } 8519 + fallthrough; 8520 + case KF_ARG_PTR_TO_CTX: 8521 + /* Trusted arguments have the same offset checks as release arguments */ 8522 + arg_type |= OBJ_RELEASE; 8523 + break; 8524 + case KF_ARG_PTR_TO_KPTR: 8525 + case KF_ARG_PTR_TO_DYNPTR: 8526 + case KF_ARG_PTR_TO_LIST_HEAD: 8527 + case KF_ARG_PTR_TO_LIST_NODE: 8528 + case KF_ARG_PTR_TO_MEM: 8529 + case KF_ARG_PTR_TO_MEM_SIZE: 8530 + /* Trusted by default */ 8531 + break; 8532 + default: 8533 + WARN_ON_ONCE(1); 8534 + return -EFAULT; 8535 + } 8536 + 8537 + if (is_kfunc_release(meta) && reg->ref_obj_id) 8538 + arg_type |= OBJ_RELEASE; 8539 + ret = check_func_arg_reg_off(env, reg, regno, arg_type); 8540 + if (ret < 0) 8541 + return ret; 8542 + 8543 + switch (kf_arg_type) { 8544 + case KF_ARG_PTR_TO_CTX: 8545 + if (reg->type != PTR_TO_CTX) { 8546 + verbose(env, "arg#%d expected pointer to ctx, but got %s\n", i, btf_type_str(t)); 8547 + return -EINVAL; 8548 + } 8549 + break; 8550 + case KF_ARG_PTR_TO_ALLOC_BTF_ID: 8551 + if (reg->type != (PTR_TO_BTF_ID | MEM_ALLOC)) { 8552 + verbose(env, "arg#%d expected pointer to allocated object\n", i); 8553 + return -EINVAL; 8554 + } 8555 + if (!reg->ref_obj_id) { 8556 + verbose(env, "allocated object must be referenced\n"); 8557 + return -EINVAL; 8558 + } 8559 + if (meta->btf == btf_vmlinux && 8560 + meta->func_id == special_kfunc_list[KF_bpf_obj_drop_impl]) { 8561 + meta->arg_obj_drop.btf = reg->btf; 8562 + meta->arg_obj_drop.btf_id = reg->btf_id; 8563 + } 8564 + break; 8565 + case KF_ARG_PTR_TO_KPTR: 8566 + if (reg->type != PTR_TO_MAP_VALUE) { 8567 + verbose(env, "arg#0 expected pointer to map value\n"); 8568 + return -EINVAL; 8569 + } 8570 + ret = process_kf_arg_ptr_to_kptr(env, reg, ref_t, ref_tname, meta, i); 8571 + if (ret < 0) 8572 + return ret; 8573 + break; 8574 + case KF_ARG_PTR_TO_DYNPTR: 8575 + if (reg->type != PTR_TO_STACK) { 8576 + verbose(env, "arg#%d expected pointer to stack\n", i); 8577 + return -EINVAL; 8578 + } 8579 + 8580 + if (!is_dynptr_reg_valid_init(env, reg)) { 8581 + verbose(env, "arg#%d pointer type %s %s must be valid and initialized\n", 8582 + i, btf_type_str(ref_t), ref_tname); 8583 + return -EINVAL; 8584 + } 8585 + 8586 + if (!is_dynptr_type_expected(env, reg, ARG_PTR_TO_DYNPTR | DYNPTR_TYPE_LOCAL)) { 8587 + verbose(env, "arg#%d pointer type %s %s points to unsupported dynamic pointer type\n", 8588 + i, btf_type_str(ref_t), ref_tname); 8589 + return -EINVAL; 8590 + } 8591 + break; 8592 + case KF_ARG_PTR_TO_LIST_HEAD: 8593 + if (reg->type != PTR_TO_MAP_VALUE && 8594 + reg->type != (PTR_TO_BTF_ID | MEM_ALLOC)) { 8595 + verbose(env, "arg#%d expected pointer to map value or allocated object\n", i); 8596 + return -EINVAL; 8597 + } 8598 + if (reg->type == (PTR_TO_BTF_ID | MEM_ALLOC) && !reg->ref_obj_id) { 8599 + verbose(env, "allocated object must be referenced\n"); 8600 + return -EINVAL; 8601 + } 8602 + ret = process_kf_arg_ptr_to_list_head(env, reg, regno, meta); 8603 + if (ret < 0) 8604 + return ret; 8605 + break; 8606 + case KF_ARG_PTR_TO_LIST_NODE: 8607 + if (reg->type != (PTR_TO_BTF_ID | MEM_ALLOC)) { 8608 + verbose(env, "arg#%d expected pointer to allocated object\n", i); 8609 + return -EINVAL; 8610 + } 8611 + if (!reg->ref_obj_id) { 8612 + verbose(env, "allocated object must be referenced\n"); 8613 + return -EINVAL; 8614 + } 8615 + ret = process_kf_arg_ptr_to_list_node(env, reg, regno, meta); 8616 + if (ret < 0) 8617 + return ret; 8618 + break; 8619 + case KF_ARG_PTR_TO_BTF_ID: 8620 + /* Only base_type is checked, further checks are done here */ 8621 + if (reg->type != PTR_TO_BTF_ID && 8622 + (!reg2btf_ids[base_type(reg->type)] || type_flag(reg->type))) { 8623 + verbose(env, "arg#%d expected pointer to btf or socket\n", i); 8624 + return -EINVAL; 8625 + } 8626 + ret = process_kf_arg_ptr_to_btf_id(env, reg, ref_t, ref_tname, ref_id, meta, i); 8627 + if (ret < 0) 8628 + return ret; 8629 + break; 8630 + case KF_ARG_PTR_TO_MEM: 8631 + resolve_ret = btf_resolve_size(btf, ref_t, &type_size); 8632 + if (IS_ERR(resolve_ret)) { 8633 + verbose(env, "arg#%d reference type('%s %s') size cannot be determined: %ld\n", 8634 + i, btf_type_str(ref_t), ref_tname, PTR_ERR(resolve_ret)); 8635 + return -EINVAL; 8636 + } 8637 + ret = check_mem_reg(env, reg, regno, type_size); 8638 + if (ret < 0) 8639 + return ret; 8640 + break; 8641 + case KF_ARG_PTR_TO_MEM_SIZE: 8642 + ret = check_kfunc_mem_size_reg(env, &regs[regno + 1], regno + 1); 8643 + if (ret < 0) { 8644 + verbose(env, "arg#%d arg#%d memory, len pair leads to invalid memory access\n", i, i + 1); 8645 + return ret; 8646 + } 8647 + /* Skip next '__sz' argument */ 8648 + i++; 8649 + break; 8650 + } 8651 + } 8652 + 8653 + if (is_kfunc_release(meta) && !meta->release_regno) { 8654 + verbose(env, "release kernel function %s expects refcounted PTR_TO_BTF_ID\n", 8655 + func_name); 8656 + return -EINVAL; 8657 + } 8658 + 8659 + return 0; 8660 + } 8661 + 7885 8662 static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn, 7886 8663 int *insn_idx_p) 7887 8664 { 7888 8665 const struct btf_type *t, *func, *func_proto, *ptr_type; 7889 8666 struct bpf_reg_state *regs = cur_regs(env); 7890 - struct bpf_kfunc_arg_meta meta = { 0 }; 7891 8667 const char *func_name, *ptr_type_name; 8668 + struct bpf_kfunc_call_arg_meta meta; 7892 8669 u32 i, nargs, func_id, ptr_type_id; 7893 8670 int err, insn_idx = *insn_idx_p; 7894 8671 const struct btf_param *args; 7895 8672 struct btf *desc_btf; 7896 8673 u32 *kfunc_flags; 7897 - bool acq; 7898 8674 7899 8675 /* skip for now, but return error when we find this in fixup_kfunc_call */ 7900 8676 if (!insn->imm) ··· 8778 7828 func_name); 8779 7829 return -EACCES; 8780 7830 } 8781 - if (*kfunc_flags & KF_DESTRUCTIVE && !capable(CAP_SYS_BOOT)) { 8782 - verbose(env, "destructive kfunc calls require CAP_SYS_BOOT capabilities\n"); 7831 + 7832 + /* Prepare kfunc call metadata */ 7833 + memset(&meta, 0, sizeof(meta)); 7834 + meta.btf = desc_btf; 7835 + meta.func_id = func_id; 7836 + meta.kfunc_flags = *kfunc_flags; 7837 + meta.func_proto = func_proto; 7838 + meta.func_name = func_name; 7839 + 7840 + if (is_kfunc_destructive(&meta) && !capable(CAP_SYS_BOOT)) { 7841 + verbose(env, "destructive kfunc calls require CAP_SYS_BOOT capability\n"); 8783 7842 return -EACCES; 8784 7843 } 8785 7844 8786 - acq = *kfunc_flags & KF_ACQUIRE; 8787 - 8788 - meta.flags = *kfunc_flags; 7845 + if (is_kfunc_sleepable(&meta) && !env->prog->aux->sleepable) { 7846 + verbose(env, "program must be sleepable to call sleepable kfunc %s\n", func_name); 7847 + return -EACCES; 7848 + } 8789 7849 8790 7850 /* Check the arguments */ 8791 - err = btf_check_kfunc_arg_match(env, desc_btf, func_id, regs, &meta); 7851 + err = check_kfunc_args(env, &meta); 8792 7852 if (err < 0) 8793 7853 return err; 8794 7854 /* In case of release function, we get register number of refcounted 8795 - * PTR_TO_BTF_ID back from btf_check_kfunc_arg_match, do the release now 7855 + * PTR_TO_BTF_ID in bpf_kfunc_arg_meta, do the release now. 8796 7856 */ 8797 - if (err) { 8798 - err = release_reference(env, regs[err].ref_obj_id); 7857 + if (meta.release_regno) { 7858 + err = release_reference(env, regs[meta.release_regno].ref_obj_id); 8799 7859 if (err) { 8800 7860 verbose(env, "kfunc %s#%d reference has not been acquired before\n", 8801 7861 func_name, func_id); ··· 8819 7859 /* Check return type */ 8820 7860 t = btf_type_skip_modifiers(desc_btf, func_proto->type, NULL); 8821 7861 8822 - if (acq && !btf_type_is_struct_ptr(desc_btf, t)) { 8823 - verbose(env, "acquire kernel function does not return PTR_TO_BTF_ID\n"); 8824 - return -EINVAL; 7862 + if (is_kfunc_acquire(&meta) && !btf_type_is_struct_ptr(meta.btf, t)) { 7863 + /* Only exception is bpf_obj_new_impl */ 7864 + if (meta.btf != btf_vmlinux || meta.func_id != special_kfunc_list[KF_bpf_obj_new_impl]) { 7865 + verbose(env, "acquire kernel function does not return PTR_TO_BTF_ID\n"); 7866 + return -EINVAL; 7867 + } 8825 7868 } 8826 7869 8827 7870 if (btf_type_is_scalar(t)) { 8828 7871 mark_reg_unknown(env, regs, BPF_REG_0); 8829 7872 mark_btf_func_reg_size(env, BPF_REG_0, t->size); 8830 7873 } else if (btf_type_is_ptr(t)) { 8831 - ptr_type = btf_type_skip_modifiers(desc_btf, t->type, 8832 - &ptr_type_id); 8833 - if (!btf_type_is_struct(ptr_type)) { 7874 + ptr_type = btf_type_skip_modifiers(desc_btf, t->type, &ptr_type_id); 7875 + 7876 + if (meta.btf == btf_vmlinux && btf_id_set_contains(&special_kfunc_set, meta.func_id)) { 7877 + if (meta.func_id == special_kfunc_list[KF_bpf_obj_new_impl]) { 7878 + const struct btf_type *ret_t; 7879 + struct btf *ret_btf; 7880 + u32 ret_btf_id; 7881 + 7882 + if (((u64)(u32)meta.arg_constant.value) != meta.arg_constant.value) { 7883 + verbose(env, "local type ID argument must be in range [0, U32_MAX]\n"); 7884 + return -EINVAL; 7885 + } 7886 + 7887 + ret_btf = env->prog->aux->btf; 7888 + ret_btf_id = meta.arg_constant.value; 7889 + 7890 + /* This may be NULL due to user not supplying a BTF */ 7891 + if (!ret_btf) { 7892 + verbose(env, "bpf_obj_new requires prog BTF\n"); 7893 + return -EINVAL; 7894 + } 7895 + 7896 + ret_t = btf_type_by_id(ret_btf, ret_btf_id); 7897 + if (!ret_t || !__btf_type_is_struct(ret_t)) { 7898 + verbose(env, "bpf_obj_new type ID argument must be of a struct\n"); 7899 + return -EINVAL; 7900 + } 7901 + 7902 + mark_reg_known_zero(env, regs, BPF_REG_0); 7903 + regs[BPF_REG_0].type = PTR_TO_BTF_ID | MEM_ALLOC; 7904 + regs[BPF_REG_0].btf = ret_btf; 7905 + regs[BPF_REG_0].btf_id = ret_btf_id; 7906 + 7907 + env->insn_aux_data[insn_idx].obj_new_size = ret_t->size; 7908 + env->insn_aux_data[insn_idx].kptr_struct_meta = 7909 + btf_find_struct_meta(ret_btf, ret_btf_id); 7910 + } else if (meta.func_id == special_kfunc_list[KF_bpf_obj_drop_impl]) { 7911 + env->insn_aux_data[insn_idx].kptr_struct_meta = 7912 + btf_find_struct_meta(meta.arg_obj_drop.btf, 7913 + meta.arg_obj_drop.btf_id); 7914 + } else if (meta.func_id == special_kfunc_list[KF_bpf_list_pop_front] || 7915 + meta.func_id == special_kfunc_list[KF_bpf_list_pop_back]) { 7916 + struct btf_field *field = meta.arg_list_head.field; 7917 + 7918 + mark_reg_known_zero(env, regs, BPF_REG_0); 7919 + regs[BPF_REG_0].type = PTR_TO_BTF_ID | MEM_ALLOC; 7920 + regs[BPF_REG_0].btf = field->list_head.btf; 7921 + regs[BPF_REG_0].btf_id = field->list_head.value_btf_id; 7922 + regs[BPF_REG_0].off = field->list_head.node_offset; 7923 + } else { 7924 + verbose(env, "kernel function %s unhandled dynamic return type\n", 7925 + meta.func_name); 7926 + return -EFAULT; 7927 + } 7928 + } else if (!__btf_type_is_struct(ptr_type)) { 8834 7929 if (!meta.r0_size) { 8835 7930 ptr_type_name = btf_name_by_offset(desc_btf, 8836 7931 ptr_type->name_off); ··· 8913 7898 regs[BPF_REG_0].type = PTR_TO_BTF_ID; 8914 7899 regs[BPF_REG_0].btf_id = ptr_type_id; 8915 7900 } 8916 - if (*kfunc_flags & KF_RET_NULL) { 7901 + 7902 + if (is_kfunc_ret_null(&meta)) { 8917 7903 regs[BPF_REG_0].type |= PTR_MAYBE_NULL; 8918 7904 /* For mark_ptr_or_null_reg, see 93c230e3f5bd6 */ 8919 7905 regs[BPF_REG_0].id = ++env->id_gen; 8920 7906 } 8921 7907 mark_btf_func_reg_size(env, BPF_REG_0, sizeof(void *)); 8922 - if (acq) { 7908 + if (is_kfunc_acquire(&meta)) { 8923 7909 int id = acquire_reference_state(env, insn_idx); 8924 7910 8925 7911 if (id < 0) 8926 7912 return id; 8927 - regs[BPF_REG_0].id = id; 7913 + if (is_kfunc_ret_null(&meta)) 7914 + regs[BPF_REG_0].id = id; 8928 7915 regs[BPF_REG_0].ref_obj_id = id; 8929 7916 } 7917 + if (reg_may_point_to_spin_lock(&regs[BPF_REG_0]) && !regs[BPF_REG_0].id) 7918 + regs[BPF_REG_0].id = ++env->id_gen; 8930 7919 } /* else { add_kfunc_call() ensures it is btf_type_is_void(t) } */ 8931 7920 8932 7921 nargs = btf_type_vlen(func_proto); ··· 11103 10084 { 11104 10085 if (type_may_be_null(reg->type) && reg->id == id && 11105 10086 !WARN_ON_ONCE(!reg->id)) { 11106 - if (WARN_ON_ONCE(reg->smin_value || reg->smax_value || 11107 - !tnum_equals_const(reg->var_off, 0) || 11108 - reg->off)) { 11109 - /* Old offset (both fixed and variable parts) should 11110 - * have been known-zero, because we don't allow pointer 11111 - * arithmetic on pointers that might be NULL. If we 11112 - * see this happening, don't convert the register. 11113 - */ 10087 + /* Old offset (both fixed and variable parts) should have been 10088 + * known-zero, because we don't allow pointer arithmetic on 10089 + * pointers that might be NULL. If we see this happening, don't 10090 + * convert the register. 10091 + * 10092 + * But in some cases, some helpers that return local kptrs 10093 + * advance offset for the returned pointer. In those cases, it 10094 + * is fine to expect to see reg->off. 10095 + */ 10096 + if (WARN_ON_ONCE(reg->smin_value || reg->smax_value || !tnum_equals_const(reg->var_off, 0))) 11114 10097 return; 11115 - } 10098 + if (reg->type != (PTR_TO_BTF_ID | MEM_ALLOC | PTR_MAYBE_NULL) && WARN_ON_ONCE(reg->off)) 10099 + return; 11116 10100 if (is_null) { 11117 10101 reg->type = SCALAR_VALUE; 11118 10102 /* We don't need id and ref_obj_id from this point ··· 11585 10563 insn->src_reg == BPF_PSEUDO_MAP_IDX_VALUE) { 11586 10564 dst_reg->type = PTR_TO_MAP_VALUE; 11587 10565 dst_reg->off = aux->map_off; 11588 - if (btf_record_has_field(map->record, BPF_SPIN_LOCK)) 11589 - dst_reg->id = ++env->id_gen; 10566 + WARN_ON_ONCE(map->max_entries != 1); 10567 + /* We want reg->id to be same (0) as map_value is not distinct */ 11590 10568 } else if (insn->src_reg == BPF_PSEUDO_MAP_FD || 11591 10569 insn->src_reg == BPF_PSEUDO_MAP_IDX) { 11592 10570 dst_reg->type = CONST_PTR_TO_MAP; ··· 11664 10642 return err; 11665 10643 } 11666 10644 11667 - if (env->cur_state->active_spin_lock) { 10645 + if (env->cur_state->active_lock.ptr) { 11668 10646 verbose(env, "BPF_LD_[ABS|IND] cannot be used inside bpf_spin_lock-ed region\n"); 11669 10647 return -EINVAL; 11670 10648 } ··· 12930 11908 if (old->speculative && !cur->speculative) 12931 11909 return false; 12932 11910 12933 - if (old->active_spin_lock != cur->active_spin_lock) 11911 + if (old->active_lock.ptr != cur->active_lock.ptr || 11912 + old->active_lock.id != cur->active_lock.id) 12934 11913 return false; 12935 11914 12936 11915 /* for states to be equal callsites have to be the same ··· 13576 12553 return -EINVAL; 13577 12554 } 13578 12555 13579 - if (env->cur_state->active_spin_lock && 13580 - (insn->src_reg == BPF_PSEUDO_CALL || 13581 - insn->imm != BPF_FUNC_spin_unlock)) { 13582 - verbose(env, "function calls are not allowed while holding a lock\n"); 13583 - return -EINVAL; 12556 + if (env->cur_state->active_lock.ptr) { 12557 + if ((insn->src_reg == BPF_REG_0 && insn->imm != BPF_FUNC_spin_unlock) || 12558 + (insn->src_reg == BPF_PSEUDO_CALL) || 12559 + (insn->src_reg == BPF_PSEUDO_KFUNC_CALL && 12560 + (insn->off != 0 || !is_bpf_list_api_kfunc(insn->imm)))) { 12561 + verbose(env, "function calls are not allowed while holding a lock\n"); 12562 + return -EINVAL; 12563 + } 13584 12564 } 13585 12565 if (insn->src_reg == BPF_PSEUDO_CALL) 13586 12566 err = check_func_call(env, insn, &env->insn_idx); ··· 13616 12590 return -EINVAL; 13617 12591 } 13618 12592 13619 - if (env->cur_state->active_spin_lock) { 12593 + if (env->cur_state->active_lock.ptr) { 13620 12594 verbose(env, "bpf_spin_unlock is missing\n"); 13621 12595 return -EINVAL; 13622 12596 } ··· 14716 13690 break; 14717 13691 case PTR_TO_BTF_ID: 14718 13692 case PTR_TO_BTF_ID | PTR_UNTRUSTED: 13693 + /* PTR_TO_BTF_ID | MEM_ALLOC always has a valid lifetime, unlike 13694 + * PTR_TO_BTF_ID, and an active ref_obj_id, but the same cannot 13695 + * be said once it is marked PTR_UNTRUSTED, hence we must handle 13696 + * any faults for loads into such types. BPF_WRITE is disallowed 13697 + * for this case. 13698 + */ 13699 + case PTR_TO_BTF_ID | MEM_ALLOC | PTR_UNTRUSTED: 14719 13700 if (type == BPF_READ) { 14720 13701 insn->code = BPF_LDX | BPF_PROBE_MEM | 14721 13702 BPF_SIZE((insn)->code); ··· 15088 14055 return err; 15089 14056 } 15090 14057 15091 - static int fixup_kfunc_call(struct bpf_verifier_env *env, 15092 - struct bpf_insn *insn) 14058 + static int fixup_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn, 14059 + struct bpf_insn *insn_buf, int insn_idx, int *cnt) 15093 14060 { 15094 14061 const struct bpf_kfunc_desc *desc; 15095 14062 ··· 15108 14075 return -EFAULT; 15109 14076 } 15110 14077 14078 + *cnt = 0; 15111 14079 insn->imm = desc->imm; 14080 + if (insn->off) 14081 + return 0; 14082 + if (desc->func_id == special_kfunc_list[KF_bpf_obj_new_impl]) { 14083 + struct btf_struct_meta *kptr_struct_meta = env->insn_aux_data[insn_idx].kptr_struct_meta; 14084 + struct bpf_insn addr[2] = { BPF_LD_IMM64(BPF_REG_2, (long)kptr_struct_meta) }; 14085 + u64 obj_new_size = env->insn_aux_data[insn_idx].obj_new_size; 15112 14086 14087 + insn_buf[0] = BPF_MOV64_IMM(BPF_REG_1, obj_new_size); 14088 + insn_buf[1] = addr[0]; 14089 + insn_buf[2] = addr[1]; 14090 + insn_buf[3] = *insn; 14091 + *cnt = 4; 14092 + } else if (desc->func_id == special_kfunc_list[KF_bpf_obj_drop_impl]) { 14093 + struct btf_struct_meta *kptr_struct_meta = env->insn_aux_data[insn_idx].kptr_struct_meta; 14094 + struct bpf_insn addr[2] = { BPF_LD_IMM64(BPF_REG_2, (long)kptr_struct_meta) }; 14095 + 14096 + insn_buf[0] = addr[0]; 14097 + insn_buf[1] = addr[1]; 14098 + insn_buf[2] = *insn; 14099 + *cnt = 3; 14100 + } 15113 14101 return 0; 15114 14102 } 15115 14103 ··· 15272 14218 if (insn->src_reg == BPF_PSEUDO_CALL) 15273 14219 continue; 15274 14220 if (insn->src_reg == BPF_PSEUDO_KFUNC_CALL) { 15275 - ret = fixup_kfunc_call(env, insn); 14221 + ret = fixup_kfunc_call(env, insn, insn_buf, i + delta, &cnt); 15276 14222 if (ret) 15277 14223 return ret; 14224 + if (cnt == 0) 14225 + continue; 14226 + 14227 + new_prog = bpf_patch_insn_data(env, i + delta, insn_buf, cnt); 14228 + if (!new_prog) 14229 + return -ENOMEM; 14230 + 14231 + delta += cnt - 1; 14232 + env->prog = prog = new_prog; 14233 + insn = new_prog->insnsi + i + delta; 15278 14234 continue; 15279 14235 } 15280 14236
+1
tools/testing/selftests/bpf/DENYLIST.aarch64
··· 38 38 ksyms_module/libbpf # 'bpf_testmod_ksym_percpu': not found in kernel BTF 39 39 ksyms_module/lskel # test_ksyms_module_lskel__open_and_load unexpected error: -2 40 40 libbpf_get_fd_by_id_opts # test_libbpf_get_fd_by_id_opts__attach unexpected error: -524 (errno 524) 41 + linked_list 41 42 lookup_key # test_lookup_key__attach unexpected error: -524 (errno 524) 42 43 lru_bug # lru_bug__attach unexpected error: -524 (errno 524) 43 44 modify_return # modify_return__attach failed unexpected error: -524 (errno 524)
+1
tools/testing/selftests/bpf/DENYLIST.s390x
··· 33 33 ksyms_module_libbpf # JIT does not support calling kernel function (kfunc) 34 34 ksyms_module_lskel # test_ksyms_module_lskel__open_and_load unexpected error: -9 (?) 35 35 libbpf_get_fd_by_id_opts # failed to attach: ERROR: strerror_r(-524)=22 (trampoline) 36 + linked_list # JIT does not support calling kernel function (kfunc) 36 37 lookup_key # JIT does not support calling kernel function (kfunc) 37 38 lru_bug # prog 'printk': failed to auto-attach: -524 38 39 map_kptr # failed to open_and_load program: -524 (trampoline)
+68
tools/testing/selftests/bpf/bpf_experimental.h
··· 1 + #ifndef __BPF_EXPERIMENTAL__ 2 + #define __BPF_EXPERIMENTAL__ 3 + 4 + #include <vmlinux.h> 5 + #include <bpf/bpf_tracing.h> 6 + #include <bpf/bpf_helpers.h> 7 + #include <bpf/bpf_core_read.h> 8 + 9 + #define __contains(name, node) __attribute__((btf_decl_tag("contains:" #name ":" #node))) 10 + 11 + /* Description 12 + * Allocates an object of the type represented by 'local_type_id' in 13 + * program BTF. User may use the bpf_core_type_id_local macro to pass the 14 + * type ID of a struct in program BTF. 15 + * 16 + * The 'local_type_id' parameter must be a known constant. 17 + * The 'meta' parameter is a hidden argument that is ignored. 18 + * Returns 19 + * A pointer to an object of the type corresponding to the passed in 20 + * 'local_type_id', or NULL on failure. 21 + */ 22 + extern void *bpf_obj_new_impl(__u64 local_type_id, void *meta) __ksym; 23 + 24 + /* Convenience macro to wrap over bpf_obj_new_impl */ 25 + #define bpf_obj_new(type) ((type *)bpf_obj_new_impl(bpf_core_type_id_local(type), NULL)) 26 + 27 + /* Description 28 + * Free an allocated object. All fields of the object that require 29 + * destruction will be destructed before the storage is freed. 30 + * 31 + * The 'meta' parameter is a hidden argument that is ignored. 32 + * Returns 33 + * Void. 34 + */ 35 + extern void bpf_obj_drop_impl(void *kptr, void *meta) __ksym; 36 + 37 + /* Convenience macro to wrap over bpf_obj_drop_impl */ 38 + #define bpf_obj_drop(kptr) bpf_obj_drop_impl(kptr, NULL) 39 + 40 + /* Description 41 + * Add a new entry to the beginning of the BPF linked list. 42 + * Returns 43 + * Void. 44 + */ 45 + extern void bpf_list_push_front(struct bpf_list_head *head, struct bpf_list_node *node) __ksym; 46 + 47 + /* Description 48 + * Add a new entry to the end of the BPF linked list. 49 + * Returns 50 + * Void. 51 + */ 52 + extern void bpf_list_push_back(struct bpf_list_head *head, struct bpf_list_node *node) __ksym; 53 + 54 + /* Description 55 + * Remove the entry at the beginning of the BPF linked list. 56 + * Returns 57 + * Pointer to bpf_list_node of deleted entry, or NULL if list is empty. 58 + */ 59 + extern struct bpf_list_node *bpf_list_pop_front(struct bpf_list_head *head) __ksym; 60 + 61 + /* Description 62 + * Remove the entry at the end of the BPF linked list. 63 + * Returns 64 + * Pointer to bpf_list_node of deleted entry, or NULL if list is empty. 65 + */ 66 + extern struct bpf_list_node *bpf_list_pop_back(struct bpf_list_head *head) __ksym; 67 + 68 + #endif
+1 -1
tools/testing/selftests/bpf/prog_tests/kfunc_dynptr_param.c
··· 22 22 "arg#0 pointer type STRUCT bpf_dynptr_kern points to unsupported dynamic pointer type", 0}, 23 23 {"not_valid_dynptr", 24 24 "arg#0 pointer type STRUCT bpf_dynptr_kern must be valid and initialized", 0}, 25 - {"not_ptr_to_stack", "arg#0 pointer type STRUCT bpf_dynptr_kern not to stack", 0}, 25 + {"not_ptr_to_stack", "arg#0 expected pointer to stack", 0}, 26 26 {"dynptr_data_null", NULL, -EBADMSG}, 27 27 }; 28 28
+747
tools/testing/selftests/bpf/prog_tests/linked_list.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + #include <bpf/btf.h> 3 + #include <test_btf.h> 4 + #include <linux/btf.h> 5 + #include <test_progs.h> 6 + #include <network_helpers.h> 7 + 8 + #include "linked_list.skel.h" 9 + #include "linked_list_fail.skel.h" 10 + 11 + static char log_buf[1024 * 1024]; 12 + 13 + static struct { 14 + const char *prog_name; 15 + const char *err_msg; 16 + } linked_list_fail_tests[] = { 17 + #define TEST(test, off) \ 18 + { #test "_missing_lock_push_front", \ 19 + "bpf_spin_lock at off=" #off " must be held for bpf_list_head" }, \ 20 + { #test "_missing_lock_push_back", \ 21 + "bpf_spin_lock at off=" #off " must be held for bpf_list_head" }, \ 22 + { #test "_missing_lock_pop_front", \ 23 + "bpf_spin_lock at off=" #off " must be held for bpf_list_head" }, \ 24 + { #test "_missing_lock_pop_back", \ 25 + "bpf_spin_lock at off=" #off " must be held for bpf_list_head" }, 26 + TEST(kptr, 32) 27 + /* FIXME 28 + TEST(global, 16) 29 + */ 30 + TEST(map, 0) 31 + TEST(inner_map, 0) 32 + #undef TEST 33 + #define TEST(test, op) \ 34 + { #test "_kptr_incorrect_lock_" #op, \ 35 + "held lock and object are not in the same allocation\n" \ 36 + "bpf_spin_lock at off=32 must be held for bpf_list_head" }, \ 37 + { #test "_map_incorrect_lock_" #op, \ 38 + "held lock and object are not in the same allocation\n" \ 39 + "bpf_spin_lock at off=0 must be held for bpf_list_head" }, \ 40 + { #test "_inner_map_incorrect_lock_" #op, \ 41 + "held lock and object are not in the same allocation\n" \ 42 + "bpf_spin_lock at off=0 must be held for bpf_list_head" }, 43 + TEST(kptr, push_front) 44 + TEST(kptr, push_back) 45 + TEST(kptr, pop_front) 46 + TEST(kptr, pop_back) 47 + TEST(map, push_front) 48 + TEST(map, push_back) 49 + TEST(map, pop_front) 50 + TEST(map, pop_back) 51 + TEST(inner_map, push_front) 52 + TEST(inner_map, push_back) 53 + TEST(inner_map, pop_front) 54 + TEST(inner_map, pop_back) 55 + #undef TEST 56 + /* FIXME 57 + { "map_compat_kprobe", "tracing progs cannot use bpf_list_head yet" }, 58 + { "map_compat_kretprobe", "tracing progs cannot use bpf_list_head yet" }, 59 + { "map_compat_tp", "tracing progs cannot use bpf_list_head yet" }, 60 + { "map_compat_perf", "tracing progs cannot use bpf_list_head yet" }, 61 + { "map_compat_raw_tp", "tracing progs cannot use bpf_list_head yet" }, 62 + { "map_compat_raw_tp_w", "tracing progs cannot use bpf_list_head yet" }, 63 + */ 64 + { "obj_type_id_oor", "local type ID argument must be in range [0, U32_MAX]" }, 65 + { "obj_new_no_composite", "bpf_obj_new type ID argument must be of a struct" }, 66 + { "obj_new_no_struct", "bpf_obj_new type ID argument must be of a struct" }, 67 + { "obj_drop_non_zero_off", "R1 must have zero offset when passed to release func" }, 68 + { "new_null_ret", "R0 invalid mem access 'ptr_or_null_'" }, 69 + { "obj_new_acq", "Unreleased reference id=" }, 70 + { "use_after_drop", "invalid mem access 'scalar'" }, 71 + { "ptr_walk_scalar", "type=scalar expected=percpu_ptr_" }, 72 + { "direct_read_lock", "direct access to bpf_spin_lock is disallowed" }, 73 + { "direct_write_lock", "direct access to bpf_spin_lock is disallowed" }, 74 + { "direct_read_head", "direct access to bpf_list_head is disallowed" }, 75 + { "direct_write_head", "direct access to bpf_list_head is disallowed" }, 76 + { "direct_read_node", "direct access to bpf_list_node is disallowed" }, 77 + { "direct_write_node", "direct access to bpf_list_node is disallowed" }, 78 + /* FIXME 79 + { "write_after_push_front", "only read is supported" }, 80 + { "write_after_push_back", "only read is supported" }, 81 + { "use_after_unlock_push_front", "invalid mem access 'scalar'" }, 82 + { "use_after_unlock_push_back", "invalid mem access 'scalar'" }, 83 + { "double_push_front", "arg#1 expected pointer to allocated object" }, 84 + { "double_push_back", "arg#1 expected pointer to allocated object" }, 85 + { "no_node_value_type", "bpf_list_node not found at offset=0" }, 86 + { "incorrect_value_type", 87 + "operation on bpf_list_head expects arg#1 bpf_list_node at offset=0 in struct foo, " 88 + "but arg is at offset=0 in struct bar" }, 89 + { "incorrect_node_var_off", "variable ptr_ access var_off=(0x0; 0xffffffff) disallowed" }, 90 + { "incorrect_node_off1", "bpf_list_node not found at offset=1" }, 91 + { "incorrect_node_off2", "arg#1 offset=40, but expected bpf_list_node at offset=0 in struct foo" }, 92 + { "no_head_type", "bpf_list_head not found at offset=0" }, 93 + { "incorrect_head_var_off1", "R1 doesn't have constant offset" }, 94 + { "incorrect_head_var_off2", "variable ptr_ access var_off=(0x0; 0xffffffff) disallowed" }, 95 + */ 96 + { "incorrect_head_off1", "bpf_list_head not found at offset=17" }, 97 + /* FIXME 98 + { "incorrect_head_off2", "bpf_list_head not found at offset=1" }, 99 + */ 100 + { "pop_front_off", 101 + "15: (bf) r1 = r6 ; R1_w=ptr_or_null_foo(id=4,ref_obj_id=4,off=40,imm=0) " 102 + "R6_w=ptr_or_null_foo(id=4,ref_obj_id=4,off=40,imm=0) refs=2,4\n" 103 + "16: (85) call bpf_this_cpu_ptr#154\nR1 type=ptr_or_null_ expected=percpu_ptr_" }, 104 + { "pop_back_off", 105 + "15: (bf) r1 = r6 ; R1_w=ptr_or_null_foo(id=4,ref_obj_id=4,off=40,imm=0) " 106 + "R6_w=ptr_or_null_foo(id=4,ref_obj_id=4,off=40,imm=0) refs=2,4\n" 107 + "16: (85) call bpf_this_cpu_ptr#154\nR1 type=ptr_or_null_ expected=percpu_ptr_" }, 108 + }; 109 + 110 + static void test_linked_list_fail_prog(const char *prog_name, const char *err_msg) 111 + { 112 + LIBBPF_OPTS(bpf_object_open_opts, opts, .kernel_log_buf = log_buf, 113 + .kernel_log_size = sizeof(log_buf), 114 + .kernel_log_level = 1); 115 + struct linked_list_fail *skel; 116 + struct bpf_program *prog; 117 + int ret; 118 + 119 + skel = linked_list_fail__open_opts(&opts); 120 + if (!ASSERT_OK_PTR(skel, "linked_list_fail__open_opts")) 121 + return; 122 + 123 + prog = bpf_object__find_program_by_name(skel->obj, prog_name); 124 + if (!ASSERT_OK_PTR(prog, "bpf_object__find_program_by_name")) 125 + goto end; 126 + 127 + bpf_program__set_autoload(prog, true); 128 + 129 + ret = linked_list_fail__load(skel); 130 + if (!ASSERT_ERR(ret, "linked_list_fail__load must fail")) 131 + goto end; 132 + 133 + if (!ASSERT_OK_PTR(strstr(log_buf, err_msg), "expected error message")) { 134 + fprintf(stderr, "Expected: %s\n", err_msg); 135 + fprintf(stderr, "Verifier: %s\n", log_buf); 136 + } 137 + 138 + end: 139 + linked_list_fail__destroy(skel); 140 + } 141 + 142 + static void clear_fields(struct bpf_map *map) 143 + { 144 + char buf[24]; 145 + int key = 0; 146 + 147 + memset(buf, 0xff, sizeof(buf)); 148 + ASSERT_OK(bpf_map__update_elem(map, &key, sizeof(key), buf, sizeof(buf), 0), "check_and_free_fields"); 149 + } 150 + 151 + enum { 152 + TEST_ALL, 153 + PUSH_POP, 154 + PUSH_POP_MULT, 155 + LIST_IN_LIST, 156 + }; 157 + 158 + static void test_linked_list_success(int mode, bool leave_in_map) 159 + { 160 + LIBBPF_OPTS(bpf_test_run_opts, opts, 161 + .data_in = &pkt_v4, 162 + .data_size_in = sizeof(pkt_v4), 163 + .repeat = 1, 164 + ); 165 + struct linked_list *skel; 166 + int ret; 167 + 168 + skel = linked_list__open_and_load(); 169 + if (!ASSERT_OK_PTR(skel, "linked_list__open_and_load")) 170 + return; 171 + 172 + if (mode == LIST_IN_LIST) 173 + goto lil; 174 + if (mode == PUSH_POP_MULT) 175 + goto ppm; 176 + 177 + ret = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.map_list_push_pop), &opts); 178 + ASSERT_OK(ret, "map_list_push_pop"); 179 + ASSERT_OK(opts.retval, "map_list_push_pop retval"); 180 + if (!leave_in_map) 181 + clear_fields(skel->maps.array_map); 182 + 183 + ret = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.inner_map_list_push_pop), &opts); 184 + ASSERT_OK(ret, "inner_map_list_push_pop"); 185 + ASSERT_OK(opts.retval, "inner_map_list_push_pop retval"); 186 + if (!leave_in_map) 187 + clear_fields(skel->maps.inner_map); 188 + 189 + ret = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.global_list_push_pop), &opts); 190 + ASSERT_OK(ret, "global_list_push_pop"); 191 + ASSERT_OK(opts.retval, "global_list_push_pop retval"); 192 + /* FIXME: 193 + if (!leave_in_map) 194 + clear_fields(skel->maps.data_A); 195 + */ 196 + 197 + if (mode == PUSH_POP) 198 + goto end; 199 + 200 + ppm: 201 + ret = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.map_list_push_pop_multiple), &opts); 202 + ASSERT_OK(ret, "map_list_push_pop_multiple"); 203 + ASSERT_OK(opts.retval, "map_list_push_pop_multiple retval"); 204 + if (!leave_in_map) 205 + clear_fields(skel->maps.array_map); 206 + 207 + ret = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.inner_map_list_push_pop_multiple), &opts); 208 + ASSERT_OK(ret, "inner_map_list_push_pop_multiple"); 209 + ASSERT_OK(opts.retval, "inner_map_list_push_pop_multiple retval"); 210 + if (!leave_in_map) 211 + clear_fields(skel->maps.inner_map); 212 + 213 + ret = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.global_list_push_pop_multiple), &opts); 214 + ASSERT_OK(ret, "global_list_push_pop_multiple"); 215 + ASSERT_OK(opts.retval, "global_list_push_pop_multiple retval"); 216 + /* FIXME: 217 + if (!leave_in_map) 218 + clear_fields(skel->maps.data_A); 219 + */ 220 + 221 + if (mode == PUSH_POP_MULT) 222 + goto end; 223 + 224 + lil: 225 + ret = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.map_list_in_list), &opts); 226 + ASSERT_OK(ret, "map_list_in_list"); 227 + ASSERT_OK(opts.retval, "map_list_in_list retval"); 228 + if (!leave_in_map) 229 + clear_fields(skel->maps.array_map); 230 + 231 + ret = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.inner_map_list_in_list), &opts); 232 + ASSERT_OK(ret, "inner_map_list_in_list"); 233 + ASSERT_OK(opts.retval, "inner_map_list_in_list retval"); 234 + if (!leave_in_map) 235 + clear_fields(skel->maps.inner_map); 236 + 237 + ret = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.global_list_in_list), &opts); 238 + ASSERT_OK(ret, "global_list_in_list"); 239 + ASSERT_OK(opts.retval, "global_list_in_list retval"); 240 + /* FIXME: 241 + if (!leave_in_map) 242 + clear_fields(skel->maps.data_A); 243 + */ 244 + end: 245 + linked_list__destroy(skel); 246 + } 247 + 248 + #define SPIN_LOCK 2 249 + #define LIST_HEAD 3 250 + #define LIST_NODE 4 251 + 252 + static struct btf *init_btf(void) 253 + { 254 + int id, lid, hid, nid; 255 + struct btf *btf; 256 + 257 + btf = btf__new_empty(); 258 + if (!ASSERT_OK_PTR(btf, "btf__new_empty")) 259 + return NULL; 260 + id = btf__add_int(btf, "int", 4, BTF_INT_SIGNED); 261 + if (!ASSERT_EQ(id, 1, "btf__add_int")) 262 + goto end; 263 + lid = btf__add_struct(btf, "bpf_spin_lock", 4); 264 + if (!ASSERT_EQ(lid, SPIN_LOCK, "btf__add_struct bpf_spin_lock")) 265 + goto end; 266 + hid = btf__add_struct(btf, "bpf_list_head", 16); 267 + if (!ASSERT_EQ(hid, LIST_HEAD, "btf__add_struct bpf_list_head")) 268 + goto end; 269 + nid = btf__add_struct(btf, "bpf_list_node", 16); 270 + if (!ASSERT_EQ(nid, LIST_NODE, "btf__add_struct bpf_list_node")) 271 + goto end; 272 + return btf; 273 + end: 274 + btf__free(btf); 275 + return NULL; 276 + } 277 + 278 + static void test_btf(void) 279 + { 280 + struct btf *btf = NULL; 281 + int id, err; 282 + 283 + while (test__start_subtest("btf: too many locks")) { 284 + btf = init_btf(); 285 + if (!ASSERT_OK_PTR(btf, "init_btf")) 286 + break; 287 + id = btf__add_struct(btf, "foo", 24); 288 + if (!ASSERT_EQ(id, 5, "btf__add_struct foo")) 289 + break; 290 + err = btf__add_field(btf, "a", SPIN_LOCK, 0, 0); 291 + if (!ASSERT_OK(err, "btf__add_struct foo::a")) 292 + break; 293 + err = btf__add_field(btf, "b", SPIN_LOCK, 32, 0); 294 + if (!ASSERT_OK(err, "btf__add_struct foo::a")) 295 + break; 296 + err = btf__add_field(btf, "c", LIST_HEAD, 64, 0); 297 + if (!ASSERT_OK(err, "btf__add_struct foo::a")) 298 + break; 299 + 300 + err = btf__load_into_kernel(btf); 301 + ASSERT_EQ(err, -E2BIG, "check btf"); 302 + btf__free(btf); 303 + break; 304 + } 305 + 306 + while (test__start_subtest("btf: missing lock")) { 307 + btf = init_btf(); 308 + if (!ASSERT_OK_PTR(btf, "init_btf")) 309 + break; 310 + id = btf__add_struct(btf, "foo", 16); 311 + if (!ASSERT_EQ(id, 5, "btf__add_struct foo")) 312 + break; 313 + err = btf__add_field(btf, "a", LIST_HEAD, 0, 0); 314 + if (!ASSERT_OK(err, "btf__add_struct foo::a")) 315 + break; 316 + id = btf__add_decl_tag(btf, "contains:baz:a", 5, 0); 317 + if (!ASSERT_EQ(id, 6, "btf__add_decl_tag contains:baz:a")) 318 + break; 319 + id = btf__add_struct(btf, "baz", 16); 320 + if (!ASSERT_EQ(id, 7, "btf__add_struct baz")) 321 + break; 322 + err = btf__add_field(btf, "a", LIST_NODE, 0, 0); 323 + if (!ASSERT_OK(err, "btf__add_field baz::a")) 324 + break; 325 + 326 + err = btf__load_into_kernel(btf); 327 + ASSERT_EQ(err, -EINVAL, "check btf"); 328 + btf__free(btf); 329 + break; 330 + } 331 + 332 + while (test__start_subtest("btf: bad offset")) { 333 + btf = init_btf(); 334 + if (!ASSERT_OK_PTR(btf, "init_btf")) 335 + break; 336 + id = btf__add_struct(btf, "foo", 36); 337 + if (!ASSERT_EQ(id, 5, "btf__add_struct foo")) 338 + break; 339 + err = btf__add_field(btf, "a", LIST_HEAD, 0, 0); 340 + if (!ASSERT_OK(err, "btf__add_field foo::a")) 341 + break; 342 + err = btf__add_field(btf, "b", LIST_NODE, 0, 0); 343 + if (!ASSERT_OK(err, "btf__add_field foo::b")) 344 + break; 345 + err = btf__add_field(btf, "c", SPIN_LOCK, 0, 0); 346 + if (!ASSERT_OK(err, "btf__add_field foo::c")) 347 + break; 348 + id = btf__add_decl_tag(btf, "contains:foo:b", 5, 0); 349 + if (!ASSERT_EQ(id, 6, "btf__add_decl_tag contains:foo:b")) 350 + break; 351 + 352 + err = btf__load_into_kernel(btf); 353 + ASSERT_EQ(err, -EEXIST, "check btf"); 354 + btf__free(btf); 355 + break; 356 + } 357 + 358 + while (test__start_subtest("btf: missing contains:")) { 359 + btf = init_btf(); 360 + if (!ASSERT_OK_PTR(btf, "init_btf")) 361 + break; 362 + id = btf__add_struct(btf, "foo", 24); 363 + if (!ASSERT_EQ(id, 5, "btf__add_struct foo")) 364 + break; 365 + err = btf__add_field(btf, "a", SPIN_LOCK, 0, 0); 366 + if (!ASSERT_OK(err, "btf__add_field foo::a")) 367 + break; 368 + err = btf__add_field(btf, "b", LIST_HEAD, 64, 0); 369 + if (!ASSERT_OK(err, "btf__add_field foo::b")) 370 + break; 371 + 372 + err = btf__load_into_kernel(btf); 373 + ASSERT_EQ(err, -EINVAL, "check btf"); 374 + btf__free(btf); 375 + break; 376 + } 377 + 378 + while (test__start_subtest("btf: missing struct")) { 379 + btf = init_btf(); 380 + if (!ASSERT_OK_PTR(btf, "init_btf")) 381 + break; 382 + id = btf__add_struct(btf, "foo", 24); 383 + if (!ASSERT_EQ(id, 5, "btf__add_struct foo")) 384 + break; 385 + err = btf__add_field(btf, "a", SPIN_LOCK, 0, 0); 386 + if (!ASSERT_OK(err, "btf__add_field foo::a")) 387 + break; 388 + err = btf__add_field(btf, "b", LIST_HEAD, 64, 0); 389 + if (!ASSERT_OK(err, "btf__add_field foo::b")) 390 + break; 391 + id = btf__add_decl_tag(btf, "contains:bar:bar", 5, 1); 392 + if (!ASSERT_EQ(id, 6, "btf__add_decl_tag contains:bar:bar")) 393 + break; 394 + 395 + err = btf__load_into_kernel(btf); 396 + ASSERT_EQ(err, -ENOENT, "check btf"); 397 + btf__free(btf); 398 + break; 399 + } 400 + 401 + while (test__start_subtest("btf: missing node")) { 402 + btf = init_btf(); 403 + if (!ASSERT_OK_PTR(btf, "init_btf")) 404 + break; 405 + id = btf__add_struct(btf, "foo", 24); 406 + if (!ASSERT_EQ(id, 5, "btf__add_struct foo")) 407 + break; 408 + err = btf__add_field(btf, "a", SPIN_LOCK, 0, 0); 409 + if (!ASSERT_OK(err, "btf__add_field foo::a")) 410 + break; 411 + err = btf__add_field(btf, "b", LIST_HEAD, 64, 0); 412 + if (!ASSERT_OK(err, "btf__add_field foo::b")) 413 + break; 414 + id = btf__add_decl_tag(btf, "contains:foo:c", 5, 1); 415 + if (!ASSERT_EQ(id, 6, "btf__add_decl_tag contains:foo:c")) 416 + break; 417 + 418 + err = btf__load_into_kernel(btf); 419 + btf__free(btf); 420 + ASSERT_EQ(err, -ENOENT, "check btf"); 421 + break; 422 + } 423 + 424 + while (test__start_subtest("btf: node incorrect type")) { 425 + btf = init_btf(); 426 + if (!ASSERT_OK_PTR(btf, "init_btf")) 427 + break; 428 + id = btf__add_struct(btf, "foo", 20); 429 + if (!ASSERT_EQ(id, 5, "btf__add_struct foo")) 430 + break; 431 + err = btf__add_field(btf, "a", LIST_HEAD, 0, 0); 432 + if (!ASSERT_OK(err, "btf__add_field foo::a")) 433 + break; 434 + err = btf__add_field(btf, "b", SPIN_LOCK, 128, 0); 435 + if (!ASSERT_OK(err, "btf__add_field foo::b")) 436 + break; 437 + id = btf__add_decl_tag(btf, "contains:bar:a", 5, 0); 438 + if (!ASSERT_EQ(id, 6, "btf__add_decl_tag contains:bar:a")) 439 + break; 440 + id = btf__add_struct(btf, "bar", 4); 441 + if (!ASSERT_EQ(id, 7, "btf__add_struct bar")) 442 + break; 443 + err = btf__add_field(btf, "a", SPIN_LOCK, 0, 0); 444 + if (!ASSERT_OK(err, "btf__add_field bar::a")) 445 + break; 446 + 447 + err = btf__load_into_kernel(btf); 448 + ASSERT_EQ(err, -EINVAL, "check btf"); 449 + btf__free(btf); 450 + break; 451 + } 452 + 453 + while (test__start_subtest("btf: multiple bpf_list_node with name b")) { 454 + btf = init_btf(); 455 + if (!ASSERT_OK_PTR(btf, "init_btf")) 456 + break; 457 + id = btf__add_struct(btf, "foo", 52); 458 + if (!ASSERT_EQ(id, 5, "btf__add_struct foo")) 459 + break; 460 + err = btf__add_field(btf, "a", LIST_HEAD, 0, 0); 461 + if (!ASSERT_OK(err, "btf__add_field foo::a")) 462 + break; 463 + err = btf__add_field(btf, "b", LIST_NODE, 128, 0); 464 + if (!ASSERT_OK(err, "btf__add_field foo::b")) 465 + break; 466 + err = btf__add_field(btf, "b", LIST_NODE, 256, 0); 467 + if (!ASSERT_OK(err, "btf__add_field foo::c")) 468 + break; 469 + err = btf__add_field(btf, "d", SPIN_LOCK, 384, 0); 470 + if (!ASSERT_OK(err, "btf__add_field foo::d")) 471 + break; 472 + id = btf__add_decl_tag(btf, "contains:foo:b", 5, 0); 473 + if (!ASSERT_EQ(id, 6, "btf__add_decl_tag contains:foo:b")) 474 + break; 475 + 476 + err = btf__load_into_kernel(btf); 477 + ASSERT_EQ(err, -EINVAL, "check btf"); 478 + btf__free(btf); 479 + break; 480 + } 481 + 482 + while (test__start_subtest("btf: owning | owned AA cycle")) { 483 + btf = init_btf(); 484 + if (!ASSERT_OK_PTR(btf, "init_btf")) 485 + break; 486 + id = btf__add_struct(btf, "foo", 36); 487 + if (!ASSERT_EQ(id, 5, "btf__add_struct foo")) 488 + break; 489 + err = btf__add_field(btf, "a", LIST_HEAD, 0, 0); 490 + if (!ASSERT_OK(err, "btf__add_field foo::a")) 491 + break; 492 + err = btf__add_field(btf, "b", LIST_NODE, 128, 0); 493 + if (!ASSERT_OK(err, "btf__add_field foo::b")) 494 + break; 495 + err = btf__add_field(btf, "c", SPIN_LOCK, 256, 0); 496 + if (!ASSERT_OK(err, "btf__add_field foo::c")) 497 + break; 498 + id = btf__add_decl_tag(btf, "contains:foo:b", 5, 0); 499 + if (!ASSERT_EQ(id, 6, "btf__add_decl_tag contains:foo:b")) 500 + break; 501 + 502 + err = btf__load_into_kernel(btf); 503 + ASSERT_EQ(err, -ELOOP, "check btf"); 504 + btf__free(btf); 505 + break; 506 + } 507 + 508 + while (test__start_subtest("btf: owning | owned ABA cycle")) { 509 + btf = init_btf(); 510 + if (!ASSERT_OK_PTR(btf, "init_btf")) 511 + break; 512 + id = btf__add_struct(btf, "foo", 36); 513 + if (!ASSERT_EQ(id, 5, "btf__add_struct foo")) 514 + break; 515 + err = btf__add_field(btf, "a", LIST_HEAD, 0, 0); 516 + if (!ASSERT_OK(err, "btf__add_field foo::a")) 517 + break; 518 + err = btf__add_field(btf, "b", LIST_NODE, 128, 0); 519 + if (!ASSERT_OK(err, "btf__add_field foo::b")) 520 + break; 521 + err = btf__add_field(btf, "c", SPIN_LOCK, 256, 0); 522 + if (!ASSERT_OK(err, "btf__add_field foo::c")) 523 + break; 524 + id = btf__add_decl_tag(btf, "contains:bar:b", 5, 0); 525 + if (!ASSERT_EQ(id, 6, "btf__add_decl_tag contains:bar:b")) 526 + break; 527 + id = btf__add_struct(btf, "bar", 36); 528 + if (!ASSERT_EQ(id, 7, "btf__add_struct bar")) 529 + break; 530 + err = btf__add_field(btf, "a", LIST_HEAD, 0, 0); 531 + if (!ASSERT_OK(err, "btf__add_field bar::a")) 532 + break; 533 + err = btf__add_field(btf, "b", LIST_NODE, 128, 0); 534 + if (!ASSERT_OK(err, "btf__add_field bar::b")) 535 + break; 536 + err = btf__add_field(btf, "c", SPIN_LOCK, 256, 0); 537 + if (!ASSERT_OK(err, "btf__add_field bar::c")) 538 + break; 539 + id = btf__add_decl_tag(btf, "contains:foo:b", 7, 0); 540 + if (!ASSERT_EQ(id, 8, "btf__add_decl_tag contains:foo:b")) 541 + break; 542 + 543 + err = btf__load_into_kernel(btf); 544 + ASSERT_EQ(err, -ELOOP, "check btf"); 545 + btf__free(btf); 546 + break; 547 + } 548 + 549 + while (test__start_subtest("btf: owning -> owned")) { 550 + btf = init_btf(); 551 + if (!ASSERT_OK_PTR(btf, "init_btf")) 552 + break; 553 + id = btf__add_struct(btf, "foo", 20); 554 + if (!ASSERT_EQ(id, 5, "btf__add_struct foo")) 555 + break; 556 + err = btf__add_field(btf, "a", LIST_HEAD, 0, 0); 557 + if (!ASSERT_OK(err, "btf__add_field foo::a")) 558 + break; 559 + err = btf__add_field(btf, "b", SPIN_LOCK, 128, 0); 560 + if (!ASSERT_OK(err, "btf__add_field foo::b")) 561 + break; 562 + id = btf__add_decl_tag(btf, "contains:bar:a", 5, 0); 563 + if (!ASSERT_EQ(id, 6, "btf__add_decl_tag contains:bar:a")) 564 + break; 565 + id = btf__add_struct(btf, "bar", 16); 566 + if (!ASSERT_EQ(id, 7, "btf__add_struct bar")) 567 + break; 568 + err = btf__add_field(btf, "a", LIST_NODE, 0, 0); 569 + if (!ASSERT_OK(err, "btf__add_field bar::a")) 570 + break; 571 + 572 + err = btf__load_into_kernel(btf); 573 + ASSERT_EQ(err, 0, "check btf"); 574 + btf__free(btf); 575 + break; 576 + } 577 + 578 + while (test__start_subtest("btf: owning -> owning | owned -> owned")) { 579 + btf = init_btf(); 580 + if (!ASSERT_OK_PTR(btf, "init_btf")) 581 + break; 582 + id = btf__add_struct(btf, "foo", 20); 583 + if (!ASSERT_EQ(id, 5, "btf__add_struct foo")) 584 + break; 585 + err = btf__add_field(btf, "a", LIST_HEAD, 0, 0); 586 + if (!ASSERT_OK(err, "btf__add_field foo::a")) 587 + break; 588 + err = btf__add_field(btf, "b", SPIN_LOCK, 128, 0); 589 + if (!ASSERT_OK(err, "btf__add_field foo::b")) 590 + break; 591 + id = btf__add_decl_tag(btf, "contains:bar:b", 5, 0); 592 + if (!ASSERT_EQ(id, 6, "btf__add_decl_tag contains:bar:b")) 593 + break; 594 + id = btf__add_struct(btf, "bar", 36); 595 + if (!ASSERT_EQ(id, 7, "btf__add_struct bar")) 596 + break; 597 + err = btf__add_field(btf, "a", LIST_HEAD, 0, 0); 598 + if (!ASSERT_OK(err, "btf__add_field bar::a")) 599 + break; 600 + err = btf__add_field(btf, "b", LIST_NODE, 128, 0); 601 + if (!ASSERT_OK(err, "btf__add_field bar::b")) 602 + break; 603 + err = btf__add_field(btf, "c", SPIN_LOCK, 256, 0); 604 + if (!ASSERT_OK(err, "btf__add_field bar::c")) 605 + break; 606 + id = btf__add_decl_tag(btf, "contains:baz:a", 7, 0); 607 + if (!ASSERT_EQ(id, 8, "btf__add_decl_tag contains:baz:a")) 608 + break; 609 + id = btf__add_struct(btf, "baz", 16); 610 + if (!ASSERT_EQ(id, 9, "btf__add_struct baz")) 611 + break; 612 + err = btf__add_field(btf, "a", LIST_NODE, 0, 0); 613 + if (!ASSERT_OK(err, "btf__add_field baz:a")) 614 + break; 615 + 616 + err = btf__load_into_kernel(btf); 617 + ASSERT_EQ(err, 0, "check btf"); 618 + btf__free(btf); 619 + break; 620 + } 621 + 622 + while (test__start_subtest("btf: owning | owned -> owning | owned -> owned")) { 623 + btf = init_btf(); 624 + if (!ASSERT_OK_PTR(btf, "init_btf")) 625 + break; 626 + id = btf__add_struct(btf, "foo", 36); 627 + if (!ASSERT_EQ(id, 5, "btf__add_struct foo")) 628 + break; 629 + err = btf__add_field(btf, "a", LIST_HEAD, 0, 0); 630 + if (!ASSERT_OK(err, "btf__add_field foo::a")) 631 + break; 632 + err = btf__add_field(btf, "b", LIST_NODE, 128, 0); 633 + if (!ASSERT_OK(err, "btf__add_field foo::b")) 634 + break; 635 + err = btf__add_field(btf, "c", SPIN_LOCK, 256, 0); 636 + if (!ASSERT_OK(err, "btf__add_field foo::c")) 637 + break; 638 + id = btf__add_decl_tag(btf, "contains:bar:b", 5, 0); 639 + if (!ASSERT_EQ(id, 6, "btf__add_decl_tag contains:bar:b")) 640 + break; 641 + id = btf__add_struct(btf, "bar", 36); 642 + if (!ASSERT_EQ(id, 7, "btf__add_struct bar")) 643 + break; 644 + err = btf__add_field(btf, "a", LIST_HEAD, 0, 0); 645 + if (!ASSERT_OK(err, "btf__add_field bar:a")) 646 + break; 647 + err = btf__add_field(btf, "b", LIST_NODE, 128, 0); 648 + if (!ASSERT_OK(err, "btf__add_field bar:b")) 649 + break; 650 + err = btf__add_field(btf, "c", SPIN_LOCK, 256, 0); 651 + if (!ASSERT_OK(err, "btf__add_field bar:c")) 652 + break; 653 + id = btf__add_decl_tag(btf, "contains:baz:a", 7, 0); 654 + if (!ASSERT_EQ(id, 8, "btf__add_decl_tag contains:baz:a")) 655 + break; 656 + id = btf__add_struct(btf, "baz", 16); 657 + if (!ASSERT_EQ(id, 9, "btf__add_struct baz")) 658 + break; 659 + err = btf__add_field(btf, "a", LIST_NODE, 0, 0); 660 + if (!ASSERT_OK(err, "btf__add_field baz:a")) 661 + break; 662 + 663 + err = btf__load_into_kernel(btf); 664 + ASSERT_EQ(err, -ELOOP, "check btf"); 665 + btf__free(btf); 666 + break; 667 + } 668 + 669 + while (test__start_subtest("btf: owning -> owning | owned -> owning | owned -> owned")) { 670 + btf = init_btf(); 671 + if (!ASSERT_OK_PTR(btf, "init_btf")) 672 + break; 673 + id = btf__add_struct(btf, "foo", 20); 674 + if (!ASSERT_EQ(id, 5, "btf__add_struct foo")) 675 + break; 676 + err = btf__add_field(btf, "a", LIST_HEAD, 0, 0); 677 + if (!ASSERT_OK(err, "btf__add_field foo::a")) 678 + break; 679 + err = btf__add_field(btf, "b", SPIN_LOCK, 128, 0); 680 + if (!ASSERT_OK(err, "btf__add_field foo::b")) 681 + break; 682 + id = btf__add_decl_tag(btf, "contains:bar:b", 5, 0); 683 + if (!ASSERT_EQ(id, 6, "btf__add_decl_tag contains:bar:b")) 684 + break; 685 + id = btf__add_struct(btf, "bar", 36); 686 + if (!ASSERT_EQ(id, 7, "btf__add_struct bar")) 687 + break; 688 + err = btf__add_field(btf, "a", LIST_HEAD, 0, 0); 689 + if (!ASSERT_OK(err, "btf__add_field bar::a")) 690 + break; 691 + err = btf__add_field(btf, "b", LIST_NODE, 128, 0); 692 + if (!ASSERT_OK(err, "btf__add_field bar::b")) 693 + break; 694 + err = btf__add_field(btf, "c", SPIN_LOCK, 256, 0); 695 + if (!ASSERT_OK(err, "btf__add_field bar::c")) 696 + break; 697 + id = btf__add_decl_tag(btf, "contains:baz:b", 7, 0); 698 + if (!ASSERT_EQ(id, 8, "btf__add_decl_tag")) 699 + break; 700 + id = btf__add_struct(btf, "baz", 36); 701 + if (!ASSERT_EQ(id, 9, "btf__add_struct baz")) 702 + break; 703 + err = btf__add_field(btf, "a", LIST_HEAD, 0, 0); 704 + if (!ASSERT_OK(err, "btf__add_field bar::a")) 705 + break; 706 + err = btf__add_field(btf, "b", LIST_NODE, 128, 0); 707 + if (!ASSERT_OK(err, "btf__add_field bar::b")) 708 + break; 709 + err = btf__add_field(btf, "c", SPIN_LOCK, 256, 0); 710 + if (!ASSERT_OK(err, "btf__add_field bar::c")) 711 + break; 712 + id = btf__add_decl_tag(btf, "contains:bam:a", 9, 0); 713 + if (!ASSERT_EQ(id, 10, "btf__add_decl_tag contains:bam:a")) 714 + break; 715 + id = btf__add_struct(btf, "bam", 16); 716 + if (!ASSERT_EQ(id, 11, "btf__add_struct bam")) 717 + break; 718 + err = btf__add_field(btf, "a", LIST_NODE, 0, 0); 719 + if (!ASSERT_OK(err, "btf__add_field bam::a")) 720 + break; 721 + 722 + err = btf__load_into_kernel(btf); 723 + ASSERT_EQ(err, -ELOOP, "check btf"); 724 + btf__free(btf); 725 + break; 726 + } 727 + } 728 + 729 + void test_linked_list(void) 730 + { 731 + int i; 732 + 733 + for (i = 0; i < ARRAY_SIZE(linked_list_fail_tests); i++) { 734 + if (!test__start_subtest(linked_list_fail_tests[i].prog_name)) 735 + continue; 736 + test_linked_list_fail_prog(linked_list_fail_tests[i].prog_name, 737 + linked_list_fail_tests[i].err_msg); 738 + } 739 + test_btf(); 740 + test_linked_list_success(PUSH_POP, false); 741 + test_linked_list_success(PUSH_POP, true); 742 + test_linked_list_success(PUSH_POP_MULT, false); 743 + test_linked_list_success(PUSH_POP_MULT, true); 744 + test_linked_list_success(LIST_IN_LIST, false); 745 + test_linked_list_success(LIST_IN_LIST, true); 746 + test_linked_list_success(TEST_ALL, false); 747 + }
+136
tools/testing/selftests/bpf/prog_tests/spin_lock.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + #include <test_progs.h> 3 + #include <network_helpers.h> 4 + 5 + #include "test_spin_lock.skel.h" 6 + #include "test_spin_lock_fail.skel.h" 7 + 8 + static char log_buf[1024 * 1024]; 9 + 10 + static struct { 11 + const char *prog_name; 12 + const char *err_msg; 13 + } spin_lock_fail_tests[] = { 14 + { "lock_id_kptr_preserve", 15 + "5: (bf) r1 = r0 ; R0_w=ptr_foo(id=2,ref_obj_id=2,off=0,imm=0) " 16 + "R1_w=ptr_foo(id=2,ref_obj_id=2,off=0,imm=0) refs=2\n6: (85) call bpf_this_cpu_ptr#154\n" 17 + "R1 type=ptr_ expected=percpu_ptr_" }, 18 + { "lock_id_global_zero", 19 + "; R1_w=map_value(off=0,ks=4,vs=4,imm=0)\n2: (85) call bpf_this_cpu_ptr#154\n" 20 + "R1 type=map_value expected=percpu_ptr_" }, 21 + { "lock_id_mapval_preserve", 22 + "8: (bf) r1 = r0 ; R0_w=map_value(id=1,off=0,ks=4,vs=8,imm=0) " 23 + "R1_w=map_value(id=1,off=0,ks=4,vs=8,imm=0)\n9: (85) call bpf_this_cpu_ptr#154\n" 24 + "R1 type=map_value expected=percpu_ptr_" }, 25 + { "lock_id_innermapval_preserve", 26 + "13: (bf) r1 = r0 ; R0=map_value(id=2,off=0,ks=4,vs=8,imm=0) " 27 + "R1_w=map_value(id=2,off=0,ks=4,vs=8,imm=0)\n14: (85) call bpf_this_cpu_ptr#154\n" 28 + "R1 type=map_value expected=percpu_ptr_" }, 29 + { "lock_id_mismatch_kptr_kptr", "bpf_spin_unlock of different lock" }, 30 + { "lock_id_mismatch_kptr_global", "bpf_spin_unlock of different lock" }, 31 + { "lock_id_mismatch_kptr_mapval", "bpf_spin_unlock of different lock" }, 32 + { "lock_id_mismatch_kptr_innermapval", "bpf_spin_unlock of different lock" }, 33 + { "lock_id_mismatch_global_global", "bpf_spin_unlock of different lock" }, 34 + { "lock_id_mismatch_global_kptr", "bpf_spin_unlock of different lock" }, 35 + { "lock_id_mismatch_global_mapval", "bpf_spin_unlock of different lock" }, 36 + { "lock_id_mismatch_global_innermapval", "bpf_spin_unlock of different lock" }, 37 + { "lock_id_mismatch_mapval_mapval", "bpf_spin_unlock of different lock" }, 38 + { "lock_id_mismatch_mapval_kptr", "bpf_spin_unlock of different lock" }, 39 + { "lock_id_mismatch_mapval_global", "bpf_spin_unlock of different lock" }, 40 + { "lock_id_mismatch_mapval_innermapval", "bpf_spin_unlock of different lock" }, 41 + { "lock_id_mismatch_innermapval_innermapval1", "bpf_spin_unlock of different lock" }, 42 + { "lock_id_mismatch_innermapval_innermapval2", "bpf_spin_unlock of different lock" }, 43 + { "lock_id_mismatch_innermapval_kptr", "bpf_spin_unlock of different lock" }, 44 + { "lock_id_mismatch_innermapval_global", "bpf_spin_unlock of different lock" }, 45 + { "lock_id_mismatch_innermapval_mapval", "bpf_spin_unlock of different lock" }, 46 + }; 47 + 48 + static void test_spin_lock_fail_prog(const char *prog_name, const char *err_msg) 49 + { 50 + LIBBPF_OPTS(bpf_object_open_opts, opts, .kernel_log_buf = log_buf, 51 + .kernel_log_size = sizeof(log_buf), 52 + .kernel_log_level = 1); 53 + struct test_spin_lock_fail *skel; 54 + struct bpf_program *prog; 55 + int ret; 56 + 57 + skel = test_spin_lock_fail__open_opts(&opts); 58 + if (!ASSERT_OK_PTR(skel, "test_spin_lock_fail__open_opts")) 59 + return; 60 + 61 + prog = bpf_object__find_program_by_name(skel->obj, prog_name); 62 + if (!ASSERT_OK_PTR(prog, "bpf_object__find_program_by_name")) 63 + goto end; 64 + 65 + bpf_program__set_autoload(prog, true); 66 + 67 + ret = test_spin_lock_fail__load(skel); 68 + if (!ASSERT_ERR(ret, "test_spin_lock_fail__load must fail")) 69 + goto end; 70 + 71 + if (!ASSERT_OK_PTR(strstr(log_buf, err_msg), "expected error message")) { 72 + fprintf(stderr, "Expected: %s\n", err_msg); 73 + fprintf(stderr, "Verifier: %s\n", log_buf); 74 + } 75 + 76 + end: 77 + test_spin_lock_fail__destroy(skel); 78 + } 79 + 80 + static void *spin_lock_thread(void *arg) 81 + { 82 + int err, prog_fd = *(u32 *) arg; 83 + LIBBPF_OPTS(bpf_test_run_opts, topts, 84 + .data_in = &pkt_v4, 85 + .data_size_in = sizeof(pkt_v4), 86 + .repeat = 10000, 87 + ); 88 + 89 + err = bpf_prog_test_run_opts(prog_fd, &topts); 90 + ASSERT_OK(err, "test_run"); 91 + ASSERT_OK(topts.retval, "test_run retval"); 92 + pthread_exit(arg); 93 + } 94 + 95 + void test_spin_lock_success(void) 96 + { 97 + struct test_spin_lock *skel; 98 + pthread_t thread_id[4]; 99 + int prog_fd, i; 100 + void *ret; 101 + 102 + skel = test_spin_lock__open_and_load(); 103 + if (!ASSERT_OK_PTR(skel, "test_spin_lock__open_and_load")) 104 + return; 105 + prog_fd = bpf_program__fd(skel->progs.bpf_spin_lock_test); 106 + for (i = 0; i < 4; i++) { 107 + int err; 108 + 109 + err = pthread_create(&thread_id[i], NULL, &spin_lock_thread, &prog_fd); 110 + if (!ASSERT_OK(err, "pthread_create")) 111 + goto end; 112 + } 113 + 114 + for (i = 0; i < 4; i++) { 115 + if (!ASSERT_OK(pthread_join(thread_id[i], &ret), "pthread_join")) 116 + goto end; 117 + if (!ASSERT_EQ(ret, &prog_fd, "ret == prog_fd")) 118 + goto end; 119 + } 120 + end: 121 + test_spin_lock__destroy(skel); 122 + } 123 + 124 + void test_spin_lock(void) 125 + { 126 + int i; 127 + 128 + test_spin_lock_success(); 129 + 130 + for (i = 0; i < ARRAY_SIZE(spin_lock_fail_tests); i++) { 131 + if (!test__start_subtest(spin_lock_fail_tests[i].prog_name)) 132 + continue; 133 + test_spin_lock_fail_prog(spin_lock_fail_tests[i].prog_name, 134 + spin_lock_fail_tests[i].err_msg); 135 + } 136 + }
-45
tools/testing/selftests/bpf/prog_tests/spinlock.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - #include <test_progs.h> 3 - #include <network_helpers.h> 4 - 5 - static void *spin_lock_thread(void *arg) 6 - { 7 - int err, prog_fd = *(u32 *) arg; 8 - LIBBPF_OPTS(bpf_test_run_opts, topts, 9 - .data_in = &pkt_v4, 10 - .data_size_in = sizeof(pkt_v4), 11 - .repeat = 10000, 12 - ); 13 - 14 - err = bpf_prog_test_run_opts(prog_fd, &topts); 15 - ASSERT_OK(err, "test_run"); 16 - ASSERT_OK(topts.retval, "test_run retval"); 17 - pthread_exit(arg); 18 - } 19 - 20 - void test_spinlock(void) 21 - { 22 - const char *file = "./test_spin_lock.bpf.o"; 23 - pthread_t thread_id[4]; 24 - struct bpf_object *obj = NULL; 25 - int prog_fd; 26 - int err = 0, i; 27 - void *ret; 28 - 29 - err = bpf_prog_test_load(file, BPF_PROG_TYPE_CGROUP_SKB, &obj, &prog_fd); 30 - if (CHECK_FAIL(err)) { 31 - printf("test_spin_lock:bpf_prog_test_load errno %d\n", errno); 32 - goto close_prog; 33 - } 34 - for (i = 0; i < 4; i++) 35 - if (CHECK_FAIL(pthread_create(&thread_id[i], NULL, 36 - &spin_lock_thread, &prog_fd))) 37 - goto close_prog; 38 - 39 - for (i = 0; i < 4; i++) 40 - if (CHECK_FAIL(pthread_join(thread_id[i], &ret) || 41 - ret != (void *)&prog_fd)) 42 - goto close_prog; 43 - close_prog: 44 - bpf_object__close(obj); 45 - }
+379
tools/testing/selftests/bpf/progs/linked_list.c
··· 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_experimental.h" 7 + 8 + #ifndef ARRAY_SIZE 9 + #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 10 + #endif 11 + 12 + #include "linked_list.h" 13 + 14 + static __always_inline 15 + int list_push_pop(struct bpf_spin_lock *lock, struct bpf_list_head *head, bool leave_in_map) 16 + { 17 + struct bpf_list_node *n; 18 + struct foo *f; 19 + 20 + f = bpf_obj_new(typeof(*f)); 21 + if (!f) 22 + return 2; 23 + 24 + bpf_spin_lock(lock); 25 + n = bpf_list_pop_front(head); 26 + bpf_spin_unlock(lock); 27 + if (n) { 28 + bpf_obj_drop(container_of(n, struct foo, node)); 29 + bpf_obj_drop(f); 30 + return 3; 31 + } 32 + 33 + bpf_spin_lock(lock); 34 + n = bpf_list_pop_back(head); 35 + bpf_spin_unlock(lock); 36 + if (n) { 37 + bpf_obj_drop(container_of(n, struct foo, node)); 38 + bpf_obj_drop(f); 39 + return 4; 40 + } 41 + 42 + 43 + bpf_spin_lock(lock); 44 + f->data = 42; 45 + bpf_list_push_front(head, &f->node); 46 + bpf_spin_unlock(lock); 47 + if (leave_in_map) 48 + return 0; 49 + bpf_spin_lock(lock); 50 + n = bpf_list_pop_back(head); 51 + bpf_spin_unlock(lock); 52 + if (!n) 53 + return 5; 54 + f = container_of(n, struct foo, node); 55 + if (f->data != 42) { 56 + bpf_obj_drop(f); 57 + return 6; 58 + } 59 + 60 + bpf_spin_lock(lock); 61 + f->data = 13; 62 + bpf_list_push_front(head, &f->node); 63 + bpf_spin_unlock(lock); 64 + bpf_spin_lock(lock); 65 + n = bpf_list_pop_front(head); 66 + bpf_spin_unlock(lock); 67 + if (!n) 68 + return 7; 69 + f = container_of(n, struct foo, node); 70 + if (f->data != 13) { 71 + bpf_obj_drop(f); 72 + return 8; 73 + } 74 + bpf_obj_drop(f); 75 + 76 + bpf_spin_lock(lock); 77 + n = bpf_list_pop_front(head); 78 + bpf_spin_unlock(lock); 79 + if (n) { 80 + bpf_obj_drop(container_of(n, struct foo, node)); 81 + return 9; 82 + } 83 + 84 + bpf_spin_lock(lock); 85 + n = bpf_list_pop_back(head); 86 + bpf_spin_unlock(lock); 87 + if (n) { 88 + bpf_obj_drop(container_of(n, struct foo, node)); 89 + return 10; 90 + } 91 + return 0; 92 + } 93 + 94 + 95 + static __always_inline 96 + int list_push_pop_multiple(struct bpf_spin_lock *lock, struct bpf_list_head *head, bool leave_in_map) 97 + { 98 + struct bpf_list_node *n; 99 + struct foo *f[8], *pf; 100 + int i; 101 + 102 + for (i = 0; i < ARRAY_SIZE(f); i++) { 103 + f[i] = bpf_obj_new(typeof(**f)); 104 + if (!f[i]) 105 + return 2; 106 + f[i]->data = i; 107 + bpf_spin_lock(lock); 108 + bpf_list_push_front(head, &f[i]->node); 109 + bpf_spin_unlock(lock); 110 + } 111 + 112 + for (i = 0; i < ARRAY_SIZE(f); i++) { 113 + bpf_spin_lock(lock); 114 + n = bpf_list_pop_front(head); 115 + bpf_spin_unlock(lock); 116 + if (!n) 117 + return 3; 118 + pf = container_of(n, struct foo, node); 119 + if (pf->data != (ARRAY_SIZE(f) - i - 1)) { 120 + bpf_obj_drop(pf); 121 + return 4; 122 + } 123 + bpf_spin_lock(lock); 124 + bpf_list_push_back(head, &pf->node); 125 + bpf_spin_unlock(lock); 126 + } 127 + 128 + if (leave_in_map) 129 + return 0; 130 + 131 + for (i = 0; i < ARRAY_SIZE(f); i++) { 132 + bpf_spin_lock(lock); 133 + n = bpf_list_pop_back(head); 134 + bpf_spin_unlock(lock); 135 + if (!n) 136 + return 5; 137 + pf = container_of(n, struct foo, node); 138 + if (pf->data != i) { 139 + bpf_obj_drop(pf); 140 + return 6; 141 + } 142 + bpf_obj_drop(pf); 143 + } 144 + bpf_spin_lock(lock); 145 + n = bpf_list_pop_back(head); 146 + bpf_spin_unlock(lock); 147 + if (n) { 148 + bpf_obj_drop(container_of(n, struct foo, node)); 149 + return 7; 150 + } 151 + 152 + bpf_spin_lock(lock); 153 + n = bpf_list_pop_front(head); 154 + bpf_spin_unlock(lock); 155 + if (n) { 156 + bpf_obj_drop(container_of(n, struct foo, node)); 157 + return 8; 158 + } 159 + return 0; 160 + } 161 + 162 + static __always_inline 163 + int list_in_list(struct bpf_spin_lock *lock, struct bpf_list_head *head, bool leave_in_map) 164 + { 165 + struct bpf_list_node *n; 166 + struct bar *ba[8], *b; 167 + struct foo *f; 168 + int i; 169 + 170 + f = bpf_obj_new(typeof(*f)); 171 + if (!f) 172 + return 2; 173 + for (i = 0; i < ARRAY_SIZE(ba); i++) { 174 + b = bpf_obj_new(typeof(*b)); 175 + if (!b) { 176 + bpf_obj_drop(f); 177 + return 3; 178 + } 179 + b->data = i; 180 + bpf_spin_lock(&f->lock); 181 + bpf_list_push_back(&f->head, &b->node); 182 + bpf_spin_unlock(&f->lock); 183 + } 184 + 185 + bpf_spin_lock(lock); 186 + f->data = 42; 187 + bpf_list_push_front(head, &f->node); 188 + bpf_spin_unlock(lock); 189 + 190 + if (leave_in_map) 191 + return 0; 192 + 193 + bpf_spin_lock(lock); 194 + n = bpf_list_pop_front(head); 195 + bpf_spin_unlock(lock); 196 + if (!n) 197 + return 4; 198 + f = container_of(n, struct foo, node); 199 + if (f->data != 42) { 200 + bpf_obj_drop(f); 201 + return 5; 202 + } 203 + 204 + for (i = 0; i < ARRAY_SIZE(ba); i++) { 205 + bpf_spin_lock(&f->lock); 206 + n = bpf_list_pop_front(&f->head); 207 + bpf_spin_unlock(&f->lock); 208 + if (!n) { 209 + bpf_obj_drop(f); 210 + return 6; 211 + } 212 + b = container_of(n, struct bar, node); 213 + if (b->data != i) { 214 + bpf_obj_drop(f); 215 + bpf_obj_drop(b); 216 + return 7; 217 + } 218 + bpf_obj_drop(b); 219 + } 220 + bpf_spin_lock(&f->lock); 221 + n = bpf_list_pop_front(&f->head); 222 + bpf_spin_unlock(&f->lock); 223 + if (n) { 224 + bpf_obj_drop(f); 225 + bpf_obj_drop(container_of(n, struct bar, node)); 226 + return 8; 227 + } 228 + bpf_obj_drop(f); 229 + return 0; 230 + } 231 + 232 + static __always_inline 233 + int test_list_push_pop(struct bpf_spin_lock *lock, struct bpf_list_head *head) 234 + { 235 + int ret; 236 + 237 + ret = list_push_pop(lock, head, false); 238 + if (ret) 239 + return ret; 240 + return list_push_pop(lock, head, true); 241 + } 242 + 243 + static __always_inline 244 + int test_list_push_pop_multiple(struct bpf_spin_lock *lock, struct bpf_list_head *head) 245 + { 246 + int ret; 247 + 248 + ret = list_push_pop_multiple(lock ,head, false); 249 + if (ret) 250 + return ret; 251 + return list_push_pop_multiple(lock, head, true); 252 + } 253 + 254 + static __always_inline 255 + int test_list_in_list(struct bpf_spin_lock *lock, struct bpf_list_head *head) 256 + { 257 + int ret; 258 + 259 + ret = list_in_list(lock, head, false); 260 + if (ret) 261 + return ret; 262 + return list_in_list(lock, head, true); 263 + } 264 + 265 + SEC("tc") 266 + int map_list_push_pop(void *ctx) 267 + { 268 + struct map_value *v; 269 + 270 + v = bpf_map_lookup_elem(&array_map, &(int){0}); 271 + if (!v) 272 + return 1; 273 + return test_list_push_pop(&v->lock, &v->head); 274 + } 275 + 276 + SEC("tc") 277 + int inner_map_list_push_pop(void *ctx) 278 + { 279 + struct map_value *v; 280 + void *map; 281 + 282 + map = bpf_map_lookup_elem(&map_of_maps, &(int){0}); 283 + if (!map) 284 + return 1; 285 + v = bpf_map_lookup_elem(map, &(int){0}); 286 + if (!v) 287 + return 1; 288 + return test_list_push_pop(&v->lock, &v->head); 289 + } 290 + 291 + SEC("tc") 292 + int global_list_push_pop(void *ctx) 293 + { 294 + /* FIXME: 295 + * return test_list_push_pop(&glock, &ghead); 296 + */ 297 + return 0; 298 + } 299 + 300 + SEC("tc") 301 + int map_list_push_pop_multiple(void *ctx) 302 + { 303 + struct map_value *v; 304 + int ret; 305 + 306 + v = bpf_map_lookup_elem(&array_map, &(int){0}); 307 + if (!v) 308 + return 1; 309 + return test_list_push_pop_multiple(&v->lock, &v->head); 310 + } 311 + 312 + SEC("tc") 313 + int inner_map_list_push_pop_multiple(void *ctx) 314 + { 315 + struct map_value *v; 316 + void *map; 317 + int ret; 318 + 319 + map = bpf_map_lookup_elem(&map_of_maps, &(int){0}); 320 + if (!map) 321 + return 1; 322 + v = bpf_map_lookup_elem(map, &(int){0}); 323 + if (!v) 324 + return 1; 325 + return test_list_push_pop_multiple(&v->lock, &v->head); 326 + } 327 + 328 + SEC("tc") 329 + int global_list_push_pop_multiple(void *ctx) 330 + { 331 + int ret; 332 + 333 + /* FIXME: 334 + ret = list_push_pop_multiple(&glock, &ghead, false); 335 + if (ret) 336 + return ret; 337 + return list_push_pop_multiple(&glock, &ghead, true); 338 + */ 339 + return 0; 340 + } 341 + 342 + SEC("tc") 343 + int map_list_in_list(void *ctx) 344 + { 345 + struct map_value *v; 346 + int ret; 347 + 348 + v = bpf_map_lookup_elem(&array_map, &(int){0}); 349 + if (!v) 350 + return 1; 351 + return test_list_in_list(&v->lock, &v->head); 352 + } 353 + 354 + SEC("tc") 355 + int inner_map_list_in_list(void *ctx) 356 + { 357 + struct map_value *v; 358 + void *map; 359 + int ret; 360 + 361 + map = bpf_map_lookup_elem(&map_of_maps, &(int){0}); 362 + if (!map) 363 + return 1; 364 + v = bpf_map_lookup_elem(map, &(int){0}); 365 + if (!v) 366 + return 1; 367 + return test_list_in_list(&v->lock, &v->head); 368 + } 369 + 370 + SEC("tc") 371 + int global_list_in_list(void *ctx) 372 + { 373 + /* FIXME 374 + return test_list_in_list(&glock, &ghead); 375 + */ 376 + return 0; 377 + } 378 + 379 + char _license[] SEC("license") = "GPL";
+58
tools/testing/selftests/bpf/progs/linked_list.h
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + #ifndef LINKED_LIST_H 3 + #define LINKED_LIST_H 4 + 5 + #include <vmlinux.h> 6 + #include <bpf/bpf_helpers.h> 7 + #include "bpf_experimental.h" 8 + 9 + struct bar { 10 + struct bpf_list_node node; 11 + int data; 12 + }; 13 + 14 + struct foo { 15 + struct bpf_list_node node; 16 + struct bpf_list_head head __contains(bar, node); 17 + struct bpf_spin_lock lock; 18 + int data; 19 + struct bpf_list_node node2; 20 + }; 21 + 22 + struct map_value { 23 + struct bpf_spin_lock lock; 24 + int data; 25 + struct bpf_list_head head __contains(foo, node); 26 + }; 27 + 28 + struct array_map { 29 + __uint(type, BPF_MAP_TYPE_ARRAY); 30 + __type(key, int); 31 + __type(value, struct map_value); 32 + __uint(max_entries, 1); 33 + }; 34 + 35 + struct array_map array_map SEC(".maps"); 36 + struct array_map inner_map SEC(".maps"); 37 + 38 + struct { 39 + __uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS); 40 + __uint(max_entries, 1); 41 + __type(key, int); 42 + __type(value, int); 43 + __array(values, struct array_map); 44 + } map_of_maps SEC(".maps") = { 45 + .values = { 46 + [0] = &inner_map, 47 + }, 48 + }; 49 + 50 + /* FIXME 51 + #define private(name) SEC(".data." #name) __hidden __attribute__((aligned(8))) 52 + 53 + private(A) struct bpf_spin_lock glock; 54 + private(A) struct bpf_list_head ghead __contains(foo, node); 55 + private(B) struct bpf_spin_lock glock2; 56 + 57 + */ 58 + #endif
+581
tools/testing/selftests/bpf/progs/linked_list_fail.c
··· 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_experimental.h" 7 + 8 + #include "linked_list.h" 9 + 10 + #define INIT \ 11 + struct map_value *v, *v2, *iv, *iv2; \ 12 + struct foo *f, *f1, *f2; \ 13 + struct bar *b; \ 14 + void *map; \ 15 + \ 16 + map = bpf_map_lookup_elem(&map_of_maps, &(int){ 0 }); \ 17 + if (!map) \ 18 + return 0; \ 19 + v = bpf_map_lookup_elem(&array_map, &(int){ 0 }); \ 20 + if (!v) \ 21 + return 0; \ 22 + v2 = bpf_map_lookup_elem(&array_map, &(int){ 0 }); \ 23 + if (!v2) \ 24 + return 0; \ 25 + iv = bpf_map_lookup_elem(map, &(int){ 0 }); \ 26 + if (!iv) \ 27 + return 0; \ 28 + iv2 = bpf_map_lookup_elem(map, &(int){ 0 }); \ 29 + if (!iv2) \ 30 + return 0; \ 31 + f = bpf_obj_new(typeof(*f)); \ 32 + if (!f) \ 33 + return 0; \ 34 + f1 = f; \ 35 + f2 = bpf_obj_new(typeof(*f2)); \ 36 + if (!f2) { \ 37 + bpf_obj_drop(f1); \ 38 + return 0; \ 39 + } \ 40 + b = bpf_obj_new(typeof(*b)); \ 41 + if (!b) { \ 42 + bpf_obj_drop(f2); \ 43 + bpf_obj_drop(f1); \ 44 + return 0; \ 45 + } 46 + 47 + #define CHECK(test, op, hexpr) \ 48 + SEC("?tc") \ 49 + int test##_missing_lock_##op(void *ctx) \ 50 + { \ 51 + INIT; \ 52 + void (*p)(void *) = (void *)&bpf_list_##op; \ 53 + p(hexpr); \ 54 + return 0; \ 55 + } 56 + 57 + CHECK(kptr, push_front, &f->head); 58 + CHECK(kptr, push_back, &f->head); 59 + CHECK(kptr, pop_front, &f->head); 60 + CHECK(kptr, pop_back, &f->head); 61 + 62 + /* FIXME 63 + CHECK(global, push_front, &ghead); 64 + CHECK(global, push_back, &ghead); 65 + CHECK(global, pop_front, &ghead); 66 + CHECK(global, pop_back, &ghead); 67 + */ 68 + 69 + CHECK(map, push_front, &v->head); 70 + CHECK(map, push_back, &v->head); 71 + CHECK(map, pop_front, &v->head); 72 + CHECK(map, pop_back, &v->head); 73 + 74 + CHECK(inner_map, push_front, &iv->head); 75 + CHECK(inner_map, push_back, &iv->head); 76 + CHECK(inner_map, pop_front, &iv->head); 77 + CHECK(inner_map, pop_back, &iv->head); 78 + 79 + #undef CHECK 80 + 81 + #define CHECK(test, op, lexpr, hexpr) \ 82 + SEC("?tc") \ 83 + int test##_incorrect_lock_##op(void *ctx) \ 84 + { \ 85 + INIT; \ 86 + void (*p)(void *) = (void *)&bpf_list_##op; \ 87 + bpf_spin_lock(lexpr); \ 88 + p(hexpr); \ 89 + return 0; \ 90 + } 91 + 92 + #define CHECK_OP(op) \ 93 + CHECK(kptr_kptr, op, &f1->lock, &f2->head); \ 94 + CHECK(kptr_map, op, &f1->lock, &v->head); \ 95 + CHECK(kptr_inner_map, op, &f1->lock, &iv->head); \ 96 + \ 97 + CHECK(map_map, op, &v->lock, &v2->head); \ 98 + CHECK(map_kptr, op, &v->lock, &f2->head); \ 99 + CHECK(map_inner_map, op, &v->lock, &iv->head); \ 100 + \ 101 + CHECK(inner_map_inner_map, op, &iv->lock, &iv2->head); \ 102 + CHECK(inner_map_kptr, op, &iv->lock, &f2->head); \ 103 + CHECK(inner_map_map, op, &iv->lock, &v->head); 104 + 105 + CHECK_OP(push_front); 106 + CHECK_OP(push_back); 107 + CHECK_OP(pop_front); 108 + CHECK_OP(pop_back); 109 + 110 + #undef CHECK 111 + #undef CHECK_OP 112 + #undef INIT 113 + 114 + /* FIXME 115 + SEC("?kprobe/xyz") 116 + int map_compat_kprobe(void *ctx) 117 + { 118 + bpf_list_push_front(&ghead, NULL); 119 + return 0; 120 + } 121 + 122 + SEC("?kretprobe/xyz") 123 + int map_compat_kretprobe(void *ctx) 124 + { 125 + bpf_list_push_front(&ghead, NULL); 126 + return 0; 127 + } 128 + 129 + SEC("?tracepoint/xyz") 130 + int map_compat_tp(void *ctx) 131 + { 132 + bpf_list_push_front(&ghead, NULL); 133 + return 0; 134 + } 135 + 136 + SEC("?perf_event") 137 + int map_compat_perf(void *ctx) 138 + { 139 + bpf_list_push_front(&ghead, NULL); 140 + return 0; 141 + } 142 + 143 + SEC("?raw_tp/xyz") 144 + int map_compat_raw_tp(void *ctx) 145 + { 146 + bpf_list_push_front(&ghead, NULL); 147 + return 0; 148 + } 149 + 150 + SEC("?raw_tp.w/xyz") 151 + int map_compat_raw_tp_w(void *ctx) 152 + { 153 + bpf_list_push_front(&ghead, NULL); 154 + return 0; 155 + } 156 + */ 157 + 158 + SEC("?tc") 159 + int obj_type_id_oor(void *ctx) 160 + { 161 + bpf_obj_new_impl(~0UL, NULL); 162 + return 0; 163 + } 164 + 165 + SEC("?tc") 166 + int obj_new_no_composite(void *ctx) 167 + { 168 + bpf_obj_new_impl(bpf_core_type_id_local(int), (void *)42); 169 + return 0; 170 + } 171 + 172 + SEC("?tc") 173 + int obj_new_no_struct(void *ctx) 174 + { 175 + 176 + bpf_obj_new(union { int data; unsigned udata; }); 177 + return 0; 178 + } 179 + 180 + SEC("?tc") 181 + int obj_drop_non_zero_off(void *ctx) 182 + { 183 + void *f; 184 + 185 + f = bpf_obj_new(struct foo); 186 + if (!f) 187 + return 0; 188 + bpf_obj_drop(f+1); 189 + return 0; 190 + } 191 + 192 + SEC("?tc") 193 + int new_null_ret(void *ctx) 194 + { 195 + return bpf_obj_new(struct foo)->data; 196 + } 197 + 198 + SEC("?tc") 199 + int obj_new_acq(void *ctx) 200 + { 201 + bpf_obj_new(struct foo); 202 + return 0; 203 + } 204 + 205 + SEC("?tc") 206 + int use_after_drop(void *ctx) 207 + { 208 + struct foo *f; 209 + 210 + f = bpf_obj_new(typeof(*f)); 211 + if (!f) 212 + return 0; 213 + bpf_obj_drop(f); 214 + return f->data; 215 + } 216 + 217 + SEC("?tc") 218 + int ptr_walk_scalar(void *ctx) 219 + { 220 + struct test1 { 221 + struct test2 { 222 + struct test2 *next; 223 + } *ptr; 224 + } *p; 225 + 226 + p = bpf_obj_new(typeof(*p)); 227 + if (!p) 228 + return 0; 229 + bpf_this_cpu_ptr(p->ptr); 230 + return 0; 231 + } 232 + 233 + SEC("?tc") 234 + int direct_read_lock(void *ctx) 235 + { 236 + struct foo *f; 237 + 238 + f = bpf_obj_new(typeof(*f)); 239 + if (!f) 240 + return 0; 241 + return *(int *)&f->lock; 242 + } 243 + 244 + SEC("?tc") 245 + int direct_write_lock(void *ctx) 246 + { 247 + struct foo *f; 248 + 249 + f = bpf_obj_new(typeof(*f)); 250 + if (!f) 251 + return 0; 252 + *(int *)&f->lock = 0; 253 + return 0; 254 + } 255 + 256 + SEC("?tc") 257 + int direct_read_head(void *ctx) 258 + { 259 + struct foo *f; 260 + 261 + f = bpf_obj_new(typeof(*f)); 262 + if (!f) 263 + return 0; 264 + return *(int *)&f->head; 265 + } 266 + 267 + SEC("?tc") 268 + int direct_write_head(void *ctx) 269 + { 270 + struct foo *f; 271 + 272 + f = bpf_obj_new(typeof(*f)); 273 + if (!f) 274 + return 0; 275 + *(int *)&f->head = 0; 276 + return 0; 277 + } 278 + 279 + SEC("?tc") 280 + int direct_read_node(void *ctx) 281 + { 282 + struct foo *f; 283 + 284 + f = bpf_obj_new(typeof(*f)); 285 + if (!f) 286 + return 0; 287 + return *(int *)&f->node; 288 + } 289 + 290 + SEC("?tc") 291 + int direct_write_node(void *ctx) 292 + { 293 + struct foo *f; 294 + 295 + f = bpf_obj_new(typeof(*f)); 296 + if (!f) 297 + return 0; 298 + *(int *)&f->node = 0; 299 + return 0; 300 + } 301 + 302 + /* FIXME 303 + static __always_inline 304 + int write_after_op(void (*push_op)(void *head, void *node)) 305 + { 306 + struct foo *f; 307 + 308 + f = bpf_obj_new(typeof(*f)); 309 + if (!f) 310 + return 0; 311 + bpf_spin_lock(&glock); 312 + push_op(&ghead, &f->node); 313 + f->data = 42; 314 + bpf_spin_unlock(&glock); 315 + 316 + return 0; 317 + } 318 + 319 + SEC("?tc") 320 + int write_after_push_front(void *ctx) 321 + { 322 + return write_after_op((void *)bpf_list_push_front); 323 + } 324 + 325 + SEC("?tc") 326 + int write_after_push_back(void *ctx) 327 + { 328 + return write_after_op((void *)bpf_list_push_back); 329 + } 330 + 331 + static __always_inline 332 + int use_after_unlock(void (*op)(void *head, void *node)) 333 + { 334 + struct foo *f; 335 + 336 + f = bpf_obj_new(typeof(*f)); 337 + if (!f) 338 + return 0; 339 + bpf_spin_lock(&glock); 340 + f->data = 42; 341 + op(&ghead, &f->node); 342 + bpf_spin_unlock(&glock); 343 + 344 + return f->data; 345 + } 346 + 347 + SEC("?tc") 348 + int use_after_unlock_push_front(void *ctx) 349 + { 350 + return use_after_unlock((void *)bpf_list_push_front); 351 + } 352 + 353 + SEC("?tc") 354 + int use_after_unlock_push_back(void *ctx) 355 + { 356 + return use_after_unlock((void *)bpf_list_push_back); 357 + } 358 + 359 + static __always_inline 360 + int list_double_add(void (*op)(void *head, void *node)) 361 + { 362 + struct foo *f; 363 + 364 + f = bpf_obj_new(typeof(*f)); 365 + if (!f) 366 + return 0; 367 + bpf_spin_lock(&glock); 368 + op(&ghead, &f->node); 369 + op(&ghead, &f->node); 370 + bpf_spin_unlock(&glock); 371 + 372 + return 0; 373 + } 374 + 375 + SEC("?tc") 376 + int double_push_front(void *ctx) 377 + { 378 + return list_double_add((void *)bpf_list_push_front); 379 + } 380 + 381 + SEC("?tc") 382 + int double_push_back(void *ctx) 383 + { 384 + return list_double_add((void *)bpf_list_push_back); 385 + } 386 + 387 + SEC("?tc") 388 + int no_node_value_type(void *ctx) 389 + { 390 + void *p; 391 + 392 + p = bpf_obj_new(struct { int data; }); 393 + if (!p) 394 + return 0; 395 + bpf_spin_lock(&glock); 396 + bpf_list_push_front(&ghead, p); 397 + bpf_spin_unlock(&glock); 398 + 399 + return 0; 400 + } 401 + 402 + SEC("?tc") 403 + int incorrect_value_type(void *ctx) 404 + { 405 + struct bar *b; 406 + 407 + b = bpf_obj_new(typeof(*b)); 408 + if (!b) 409 + return 0; 410 + bpf_spin_lock(&glock); 411 + bpf_list_push_front(&ghead, &b->node); 412 + bpf_spin_unlock(&glock); 413 + 414 + return 0; 415 + } 416 + 417 + SEC("?tc") 418 + int incorrect_node_var_off(struct __sk_buff *ctx) 419 + { 420 + struct foo *f; 421 + 422 + f = bpf_obj_new(typeof(*f)); 423 + if (!f) 424 + return 0; 425 + bpf_spin_lock(&glock); 426 + bpf_list_push_front(&ghead, (void *)&f->node + ctx->protocol); 427 + bpf_spin_unlock(&glock); 428 + 429 + return 0; 430 + } 431 + 432 + SEC("?tc") 433 + int incorrect_node_off1(void *ctx) 434 + { 435 + struct foo *f; 436 + 437 + f = bpf_obj_new(typeof(*f)); 438 + if (!f) 439 + return 0; 440 + bpf_spin_lock(&glock); 441 + bpf_list_push_front(&ghead, (void *)&f->node + 1); 442 + bpf_spin_unlock(&glock); 443 + 444 + return 0; 445 + } 446 + 447 + SEC("?tc") 448 + int incorrect_node_off2(void *ctx) 449 + { 450 + struct foo *f; 451 + 452 + f = bpf_obj_new(typeof(*f)); 453 + if (!f) 454 + return 0; 455 + bpf_spin_lock(&glock); 456 + bpf_list_push_front(&ghead, &f->node2); 457 + bpf_spin_unlock(&glock); 458 + 459 + return 0; 460 + } 461 + 462 + SEC("?tc") 463 + int no_head_type(void *ctx) 464 + { 465 + void *p; 466 + 467 + p = bpf_obj_new(typeof(struct { int data; })); 468 + if (!p) 469 + return 0; 470 + bpf_spin_lock(&glock); 471 + bpf_list_push_front(p, NULL); 472 + bpf_spin_lock(&glock); 473 + 474 + return 0; 475 + } 476 + 477 + SEC("?tc") 478 + int incorrect_head_var_off1(struct __sk_buff *ctx) 479 + { 480 + struct foo *f; 481 + 482 + f = bpf_obj_new(typeof(*f)); 483 + if (!f) 484 + return 0; 485 + bpf_spin_lock(&glock); 486 + bpf_list_push_front((void *)&ghead + ctx->protocol, &f->node); 487 + bpf_spin_unlock(&glock); 488 + 489 + return 0; 490 + } 491 + 492 + SEC("?tc") 493 + int incorrect_head_var_off2(struct __sk_buff *ctx) 494 + { 495 + struct foo *f; 496 + 497 + f = bpf_obj_new(typeof(*f)); 498 + if (!f) 499 + return 0; 500 + bpf_spin_lock(&glock); 501 + bpf_list_push_front((void *)&f->head + ctx->protocol, &f->node); 502 + bpf_spin_unlock(&glock); 503 + 504 + return 0; 505 + } 506 + */ 507 + 508 + SEC("?tc") 509 + int incorrect_head_off1(void *ctx) 510 + { 511 + struct foo *f; 512 + struct bar *b; 513 + 514 + f = bpf_obj_new(typeof(*f)); 515 + if (!f) 516 + return 0; 517 + b = bpf_obj_new(typeof(*b)); 518 + if (!b) { 519 + bpf_obj_drop(f); 520 + return 0; 521 + } 522 + 523 + bpf_spin_lock(&f->lock); 524 + bpf_list_push_front((void *)&f->head + 1, &b->node); 525 + bpf_spin_unlock(&f->lock); 526 + 527 + return 0; 528 + } 529 + 530 + /* FIXME 531 + SEC("?tc") 532 + int incorrect_head_off2(void *ctx) 533 + { 534 + struct foo *f; 535 + struct bar *b; 536 + 537 + f = bpf_obj_new(typeof(*f)); 538 + if (!f) 539 + return 0; 540 + 541 + bpf_spin_lock(&glock); 542 + bpf_list_push_front((void *)&ghead + 1, &f->node); 543 + bpf_spin_unlock(&glock); 544 + 545 + return 0; 546 + } 547 + */ 548 + 549 + static __always_inline 550 + int pop_ptr_off(void *(*op)(void *head)) 551 + { 552 + struct { 553 + struct bpf_list_head head __contains(foo, node2); 554 + struct bpf_spin_lock lock; 555 + } *p; 556 + struct bpf_list_node *n; 557 + 558 + p = bpf_obj_new(typeof(*p)); 559 + if (!p) 560 + return 0; 561 + bpf_spin_lock(&p->lock); 562 + n = op(&p->head); 563 + bpf_spin_unlock(&p->lock); 564 + 565 + bpf_this_cpu_ptr(n); 566 + return 0; 567 + } 568 + 569 + SEC("?tc") 570 + int pop_front_off(void *ctx) 571 + { 572 + return pop_ptr_off((void *)bpf_list_pop_front); 573 + } 574 + 575 + SEC("?tc") 576 + int pop_back_off(void *ctx) 577 + { 578 + return pop_ptr_off((void *)bpf_list_pop_back); 579 + } 580 + 581 + char _license[] SEC("license") = "GPL";
+2 -2
tools/testing/selftests/bpf/progs/test_spin_lock.c
··· 45 45 46 46 #define CREDIT_PER_NS(delta, rate) (((delta) * rate) >> 20) 47 47 48 - SEC("tc") 49 - int bpf_sping_lock_test(struct __sk_buff *skb) 48 + SEC("cgroup_skb/ingress") 49 + int bpf_spin_lock_test(struct __sk_buff *skb) 50 50 { 51 51 volatile int credit = 0, max_credit = 100, pkt_len = 64; 52 52 struct hmap_elem zero = {}, *val;
+204
tools/testing/selftests/bpf/progs/test_spin_lock_fail.c
··· 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_experimental.h" 6 + 7 + struct foo { 8 + struct bpf_spin_lock lock; 9 + int data; 10 + }; 11 + 12 + struct array_map { 13 + __uint(type, BPF_MAP_TYPE_ARRAY); 14 + __type(key, int); 15 + __type(value, struct foo); 16 + __uint(max_entries, 1); 17 + } array_map SEC(".maps"); 18 + 19 + struct { 20 + __uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS); 21 + __uint(max_entries, 1); 22 + __type(key, int); 23 + __type(value, int); 24 + __array(values, struct array_map); 25 + } map_of_maps SEC(".maps") = { 26 + .values = { 27 + [0] = &array_map, 28 + }, 29 + }; 30 + 31 + SEC(".data.A") struct bpf_spin_lock lockA; 32 + SEC(".data.B") struct bpf_spin_lock lockB; 33 + 34 + SEC("?tc") 35 + int lock_id_kptr_preserve(void *ctx) 36 + { 37 + struct foo *f; 38 + 39 + f = bpf_obj_new(typeof(*f)); 40 + if (!f) 41 + return 0; 42 + bpf_this_cpu_ptr(f); 43 + return 0; 44 + } 45 + 46 + SEC("?tc") 47 + int lock_id_global_zero(void *ctx) 48 + { 49 + bpf_this_cpu_ptr(&lockA); 50 + return 0; 51 + } 52 + 53 + SEC("?tc") 54 + int lock_id_mapval_preserve(void *ctx) 55 + { 56 + struct foo *f; 57 + int key = 0; 58 + 59 + f = bpf_map_lookup_elem(&array_map, &key); 60 + if (!f) 61 + return 0; 62 + bpf_this_cpu_ptr(f); 63 + return 0; 64 + } 65 + 66 + SEC("?tc") 67 + int lock_id_innermapval_preserve(void *ctx) 68 + { 69 + struct foo *f; 70 + int key = 0; 71 + void *map; 72 + 73 + map = bpf_map_lookup_elem(&map_of_maps, &key); 74 + if (!map) 75 + return 0; 76 + f = bpf_map_lookup_elem(map, &key); 77 + if (!f) 78 + return 0; 79 + bpf_this_cpu_ptr(f); 80 + return 0; 81 + } 82 + 83 + #define CHECK(test, A, B) \ 84 + SEC("?tc") \ 85 + int lock_id_mismatch_##test(void *ctx) \ 86 + { \ 87 + struct foo *f1, *f2, *v, *iv; \ 88 + int key = 0; \ 89 + void *map; \ 90 + \ 91 + map = bpf_map_lookup_elem(&map_of_maps, &key); \ 92 + if (!map) \ 93 + return 0; \ 94 + iv = bpf_map_lookup_elem(map, &key); \ 95 + if (!iv) \ 96 + return 0; \ 97 + v = bpf_map_lookup_elem(&array_map, &key); \ 98 + if (!v) \ 99 + return 0; \ 100 + f1 = bpf_obj_new(typeof(*f1)); \ 101 + if (!f1) \ 102 + return 0; \ 103 + f2 = bpf_obj_new(typeof(*f2)); \ 104 + if (!f2) { \ 105 + bpf_obj_drop(f1); \ 106 + return 0; \ 107 + } \ 108 + bpf_spin_lock(A); \ 109 + bpf_spin_unlock(B); \ 110 + return 0; \ 111 + } 112 + 113 + CHECK(kptr_kptr, &f1->lock, &f2->lock); 114 + CHECK(kptr_global, &f1->lock, &lockA); 115 + CHECK(kptr_mapval, &f1->lock, &v->lock); 116 + CHECK(kptr_innermapval, &f1->lock, &iv->lock); 117 + 118 + CHECK(global_global, &lockA, &lockB); 119 + CHECK(global_kptr, &lockA, &f1->lock); 120 + CHECK(global_mapval, &lockA, &v->lock); 121 + CHECK(global_innermapval, &lockA, &iv->lock); 122 + 123 + SEC("?tc") 124 + int lock_id_mismatch_mapval_mapval(void *ctx) 125 + { 126 + struct foo *f1, *f2; 127 + int key = 0; 128 + 129 + f1 = bpf_map_lookup_elem(&array_map, &key); 130 + if (!f1) 131 + return 0; 132 + f2 = bpf_map_lookup_elem(&array_map, &key); 133 + if (!f2) 134 + return 0; 135 + 136 + bpf_spin_lock(&f1->lock); 137 + f1->data = 42; 138 + bpf_spin_unlock(&f2->lock); 139 + 140 + return 0; 141 + } 142 + 143 + CHECK(mapval_kptr, &v->lock, &f1->lock); 144 + CHECK(mapval_global, &v->lock, &lockB); 145 + CHECK(mapval_innermapval, &v->lock, &iv->lock); 146 + 147 + SEC("?tc") 148 + int lock_id_mismatch_innermapval_innermapval1(void *ctx) 149 + { 150 + struct foo *f1, *f2; 151 + int key = 0; 152 + void *map; 153 + 154 + map = bpf_map_lookup_elem(&map_of_maps, &key); 155 + if (!map) 156 + return 0; 157 + f1 = bpf_map_lookup_elem(map, &key); 158 + if (!f1) 159 + return 0; 160 + f2 = bpf_map_lookup_elem(map, &key); 161 + if (!f2) 162 + return 0; 163 + 164 + bpf_spin_lock(&f1->lock); 165 + f1->data = 42; 166 + bpf_spin_unlock(&f2->lock); 167 + 168 + return 0; 169 + } 170 + 171 + SEC("?tc") 172 + int lock_id_mismatch_innermapval_innermapval2(void *ctx) 173 + { 174 + struct foo *f1, *f2; 175 + int key = 0; 176 + void *map; 177 + 178 + map = bpf_map_lookup_elem(&map_of_maps, &key); 179 + if (!map) 180 + return 0; 181 + f1 = bpf_map_lookup_elem(map, &key); 182 + if (!f1) 183 + return 0; 184 + map = bpf_map_lookup_elem(&map_of_maps, &key); 185 + if (!map) 186 + return 0; 187 + f2 = bpf_map_lookup_elem(map, &key); 188 + if (!f2) 189 + return 0; 190 + 191 + bpf_spin_lock(&f1->lock); 192 + f1->data = 42; 193 + bpf_spin_unlock(&f2->lock); 194 + 195 + return 0; 196 + } 197 + 198 + CHECK(innermapval_kptr, &iv->lock, &f1->lock); 199 + CHECK(innermapval_global, &iv->lock, &lockA); 200 + CHECK(innermapval_mapval, &iv->lock, &v->lock); 201 + 202 + #undef CHECK 203 + 204 + char _license[] SEC("license") = "GPL";
+1 -1
tools/testing/selftests/bpf/verifier/calls.c
··· 109 109 }, 110 110 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 111 111 .result = REJECT, 112 - .errstr = "arg#0 pointer type STRUCT prog_test_ref_kfunc must point", 112 + .errstr = "arg#0 expected pointer to btf or socket", 113 113 .fixup_kfunc_btf_id = { 114 114 { "bpf_kfunc_call_test_acquire", 3 }, 115 115 { "bpf_kfunc_call_test_release", 5 },
+2 -2
tools/testing/selftests/bpf/verifier/ref_tracking.c
··· 142 142 .kfunc = "bpf", 143 143 .expected_attach_type = BPF_LSM_MAC, 144 144 .flags = BPF_F_SLEEPABLE, 145 - .errstr = "arg#0 pointer type STRUCT bpf_key must point to scalar, or struct with scalar", 145 + .errstr = "arg#0 expected pointer to btf or socket", 146 146 .fixup_kfunc_btf_id = { 147 147 { "bpf_lookup_user_key", 2 }, 148 148 { "bpf_key_put", 4 }, ··· 163 163 .kfunc = "bpf", 164 164 .expected_attach_type = BPF_LSM_MAC, 165 165 .flags = BPF_F_SLEEPABLE, 166 - .errstr = "arg#0 pointer type STRUCT bpf_key must point to scalar, or struct with scalar", 166 + .errstr = "arg#0 expected pointer to btf or socket", 167 167 .fixup_kfunc_btf_id = { 168 168 { "bpf_lookup_system_key", 1 }, 169 169 { "bpf_key_put", 3 },