Some types, such as type kptr, bpf_rb_root, and bpf_list_head, are treated in a special way. Previously, these types could not be the type of a field in a struct type that is used as the type of a global variable. They could not be the type of a field in a struct type that is used as the type of a field in the value type of a map either. They could not even be the type of array elements. This means that they can only be the type of global variables or of direct fields in the value type of a map. The patch set aims to enable the use of these specific types in arrays and struct fields, providing flexibility. It examines the types of global variables or the value types of maps, such as arrays and struct types, recursively to identify these special types and generate field information for them. For example, ... struct task_struct __kptr *ptr[3]; ... it will create 3 instances of "struct btf_field" in the "btf_record" of the data section. [..., btf_field(offset=0x100, type=BPF_KPTR_REF), btf_field(offset=0x108, type=BPF_KPTR_REF), btf_field(offset=0x110, type=BPF_KPTR_REF), ... ] It creates a record of each of three elements. These three records are almost identical except their offsets. Another example is ... struct A { ... struct task_struct __kptr *task; struct bpf_rb_root root; ... } struct A foo[2]; it will create 4 records. [..., btf_field(offset=0x7100, type=BPF_KPTR_REF), btf_field(offset=0x7108, type=BPF_RB_ROOT:), btf_field(offset=0x7200, type=BPF_KPTR_REF), btf_field(offset=0x7208, type=BPF_RB_ROOT:), ... ] Assuming that the size of an element/struct A is 0x100 and "foo" starts at 0x7000, it includes two kptr records at 0x7100 and 0x7200, and two rbtree root records at 0x7108 and 0x7208. All these field information will be flatten, for struct types, and repeated, for arrays. --- Changes from v2: - Support fields in nested struct type. - Remove nelems and duplicate field information with offset adjustments for arrays. Changes from v1: - Move the check of element alignment out of btf_field_cmp() to btf_record_find(). - Change the order of the previous patch 4 "bpf: check_map_kptr_access() compute the offset from the reg state" as the patch 7 now. - Reject BPF_RB_NODE and BPF_LIST_NODE with nelems > 1. - Rephrase the commit log of the patch "bpf: check_map_access() with the knowledge of arrays" to clarify the alignment on elements. v2: https://lore.kernel.org/all/20240412210814.603377-1-thinker.li@xxxxxxxxx/ v1: https://lore.kernel.org/bpf/20240410004150.2917641-1-thinker.li@xxxxxxxxx/ Kui-Feng Lee (7): bpf: Remove unnecessary checks on the offset of btf_field. bpf: Remove unnecessary call to btf_field_type_size(). bpf: create repeated fields for arrays. bpf: look into the types of the fields of a struct type recursively. selftests/bpf: Test kptr arrays and kptrs in nested struct fields. selftests/bpf: Test global bpf_rb_root arrays and fields in nested struct types. selftests/bpf: Test global bpf_list_head arrays. kernel/bpf/btf.c | 161 +++++++++++++++++- kernel/bpf/verifier.c | 4 +- .../selftests/bpf/prog_tests/cpumask.c | 5 + .../selftests/bpf/prog_tests/linked_list.c | 12 ++ .../testing/selftests/bpf/prog_tests/rbtree.c | 47 +++++ .../selftests/bpf/progs/cpumask_success.c | 133 +++++++++++++++ .../testing/selftests/bpf/progs/linked_list.c | 42 +++++ tools/testing/selftests/bpf/progs/rbtree.c | 77 +++++++++ 8 files changed, 473 insertions(+), 8 deletions(-) -- 2.34.1