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

Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next

Daniel Borkmann says:

====================
pull-request: bpf-next 2019-04-12

The following pull-request contains BPF updates for your *net-next* tree.

The main changes are:

1) Improve BPF verifier scalability for large programs through two
optimizations: i) remove verifier states that are not useful in pruning,
ii) stop walking parentage chain once first LIVE_READ is seen. Combined
gives approx 20x speedup. Increase limits for accepting large programs
under root, and add various stress tests, from Alexei.

2) Implement global data support in BPF. This enables static global variables
for .data, .rodata and .bss sections to be properly handled which allows
for more natural program development. This also opens up the possibility
to optimize program workflow by compiling ELFs only once and later only
rewriting section data before reload, from Daniel and with test cases and
libbpf refactoring from Joe.

3) Add config option to generate BTF type info for vmlinux as part of the
kernel build process. DWARF debug info is converted via pahole to BTF.
Latter relies on libbpf and makes use of BTF deduplication algorithm which
results in 100x savings compared to DWARF data. Resulting .BTF section is
typically about 2MB in size, from Andrii.

4) Add BPF verifier support for stack access with variable offset from
helpers and add various test cases along with it, from Andrey.

5) Extend bpf_skb_adjust_room() growth BPF helper to mark inner MAC header
so that L2 encapsulation can be used for tc tunnels, from Alan.

6) Add support for input __sk_buff context in BPF_PROG_TEST_RUN so that
users can define a subset of allowed __sk_buff fields that get fed into
the test program, from Stanislav.

7) Add bpf fs multi-dimensional array tests for BTF test suite and fix up
various UBSAN warnings in bpftool, from Yonghong.

8) Generate a pkg-config file for libbpf, from Luca.

9) Dump program's BTF id in bpftool, from Prashant.

10) libbpf fix to use smaller BPF log buffer size for AF_XDP's XDP
program, from Magnus.

11) kallsyms related fixes for the case when symbols are not present in
BPF selftests and samples, from Daniel
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+4605 -427
+9
.mailmap
··· 16 16 Alan Cox <root@hraefn.swansea.linux.org.uk> 17 17 Aleksey Gorelov <aleksey_gorelov@phoenix.com> 18 18 Aleksandar Markovic <aleksandar.markovic@mips.com> <aleksandar.markovic@imgtec.com> 19 + Alexei Starovoitov <ast@kernel.org> <ast@plumgrid.com> 20 + Alexei Starovoitov <ast@kernel.org> <alexei.starovoitov@gmail.com> 21 + Alexei Starovoitov <ast@kernel.org> <ast@fb.com> 19 22 Al Viro <viro@ftp.linux.org.uk> 20 23 Al Viro <viro@zenIV.linux.org.uk> 21 24 Andi Shyti <andi@etezian.org> <andi.shyti@samsung.com> ··· 49 46 Christophe Ricard <christophe.ricard@gmail.com> 50 47 Corey Minyard <minyard@acm.org> 51 48 Damian Hobson-Garcia <dhobsong@igel.co.jp> 49 + Daniel Borkmann <daniel@iogearbox.net> <dborkman@redhat.com> 50 + Daniel Borkmann <daniel@iogearbox.net> <dborkmann@redhat.com> 51 + Daniel Borkmann <daniel@iogearbox.net> <danborkmann@iogearbox.net> 52 + Daniel Borkmann <daniel@iogearbox.net> <daniel.borkmann@tik.ee.ethz.ch> 53 + Daniel Borkmann <daniel@iogearbox.net> <danborkmann@googlemail.com> 54 + Daniel Borkmann <daniel@iogearbox.net> <dxchgb@gmail.com> 52 55 David Brownell <david-b@pacbell.net> 53 56 David Woodhouse <dwmw2@shinybook.infradead.org> 54 57 Dengcheng Zhu <dzhu@wavecomp.com> <dengcheng.zhu@mips.com>
+57
Documentation/bpf/btf.rst
··· 82 82 #define BTF_KIND_RESTRICT 11 /* Restrict */ 83 83 #define BTF_KIND_FUNC 12 /* Function */ 84 84 #define BTF_KIND_FUNC_PROTO 13 /* Function Proto */ 85 + #define BTF_KIND_VAR 14 /* Variable */ 86 + #define BTF_KIND_DATASEC 15 /* Section */ 85 87 86 88 Note that the type section encodes debug info, not just pure types. 87 89 ``BTF_KIND_FUNC`` is not a type, and it represents a defined subprogram. ··· 394 392 395 393 If the function has variable arguments, the last parameter is encoded with 396 394 ``name_off = 0`` and ``type = 0``. 395 + 396 + 2.2.14 BTF_KIND_VAR 397 + ~~~~~~~~~~~~~~~~~~~ 398 + 399 + ``struct btf_type`` encoding requirement: 400 + * ``name_off``: offset to a valid C identifier 401 + * ``info.kind_flag``: 0 402 + * ``info.kind``: BTF_KIND_VAR 403 + * ``info.vlen``: 0 404 + * ``type``: the type of the variable 405 + 406 + ``btf_type`` is followed by a single ``struct btf_variable`` with the 407 + following data:: 408 + 409 + struct btf_var { 410 + __u32 linkage; 411 + }; 412 + 413 + ``struct btf_var`` encoding: 414 + * ``linkage``: currently only static variable 0, or globally allocated 415 + variable in ELF sections 1 416 + 417 + Not all type of global variables are supported by LLVM at this point. 418 + The following is currently available: 419 + 420 + * static variables with or without section attributes 421 + * global variables with section attributes 422 + 423 + The latter is for future extraction of map key/value type id's from a 424 + map definition. 425 + 426 + 2.2.15 BTF_KIND_DATASEC 427 + ~~~~~~~~~~~~~~~~~~~~~~~ 428 + 429 + ``struct btf_type`` encoding requirement: 430 + * ``name_off``: offset to a valid name associated with a variable or 431 + one of .data/.bss/.rodata 432 + * ``info.kind_flag``: 0 433 + * ``info.kind``: BTF_KIND_DATASEC 434 + * ``info.vlen``: # of variables 435 + * ``size``: total section size in bytes (0 at compilation time, patched 436 + to actual size by BPF loaders such as libbpf) 437 + 438 + ``btf_type`` is followed by ``info.vlen`` number of ``struct btf_var_secinfo``.:: 439 + 440 + struct btf_var_secinfo { 441 + __u32 type; 442 + __u32 offset; 443 + __u32 size; 444 + }; 445 + 446 + ``struct btf_var_secinfo`` encoding: 447 + * ``type``: the type of the BTF_KIND_VAR variable 448 + * ``offset``: the in-section offset of the variable 449 + * ``size``: the size of the variable in bytes 397 450 398 451 3. BTF Kernel API 399 452 *****************
+2 -1
Makefile
··· 401 401 STRIP = $(CROSS_COMPILE)strip 402 402 OBJCOPY = $(CROSS_COMPILE)objcopy 403 403 OBJDUMP = $(CROSS_COMPILE)objdump 404 + PAHOLE = pahole 404 405 LEX = flex 405 406 YACC = bison 406 407 AWK = awk ··· 456 455 GCC_PLUGINS_CFLAGS := 457 456 458 457 export ARCH SRCARCH CONFIG_SHELL HOSTCC KBUILD_HOSTCFLAGS CROSS_COMPILE AS LD CC 459 - export CPP AR NM STRIP OBJCOPY OBJDUMP KBUILD_HOSTLDFLAGS KBUILD_HOSTLDLIBS 458 + export CPP AR NM STRIP OBJCOPY OBJDUMP PAHOLE KBUILD_HOSTLDFLAGS KBUILD_HOSTLDLIBS 460 459 export MAKE LEX YACC AWK INSTALLKERNEL PERL PYTHON PYTHON2 PYTHON3 UTS_MACHINE 461 460 export HOSTCXX KBUILD_HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS 462 461
+66 -9
include/linux/bpf.h
··· 57 57 const struct btf *btf, 58 58 const struct btf_type *key_type, 59 59 const struct btf_type *value_type); 60 + 61 + /* Direct value access helpers. */ 62 + int (*map_direct_value_addr)(const struct bpf_map *map, 63 + u64 *imm, u32 off); 64 + int (*map_direct_value_meta)(const struct bpf_map *map, 65 + u64 imm, u32 *off); 60 66 }; 61 67 62 68 struct bpf_map { ··· 87 81 struct btf *btf; 88 82 u32 pages; 89 83 bool unpriv_array; 90 - /* 51 bytes hole */ 84 + bool frozen; /* write-once */ 85 + /* 48 bytes hole */ 91 86 92 87 /* The 3rd and 4th cacheline with misc members to avoid false sharing 93 88 * particularly with refcounting. ··· 428 421 }; 429 422 }; 430 423 424 + #define BPF_COMPLEXITY_LIMIT_INSNS 1000000 /* yes. 1M insns */ 431 425 #define MAX_TAIL_CALL_CNT 32 426 + 427 + #define BPF_F_ACCESS_MASK (BPF_F_RDONLY | \ 428 + BPF_F_RDONLY_PROG | \ 429 + BPF_F_WRONLY | \ 430 + BPF_F_WRONLY_PROG) 431 + 432 + #define BPF_MAP_CAN_READ BIT(0) 433 + #define BPF_MAP_CAN_WRITE BIT(1) 434 + 435 + static inline u32 bpf_map_flags_to_cap(struct bpf_map *map) 436 + { 437 + u32 access_flags = map->map_flags & (BPF_F_RDONLY_PROG | BPF_F_WRONLY_PROG); 438 + 439 + /* Combination of BPF_F_RDONLY_PROG | BPF_F_WRONLY_PROG is 440 + * not possible. 441 + */ 442 + if (access_flags & BPF_F_RDONLY_PROG) 443 + return BPF_MAP_CAN_READ; 444 + else if (access_flags & BPF_F_WRONLY_PROG) 445 + return BPF_MAP_CAN_WRITE; 446 + else 447 + return BPF_MAP_CAN_READ | BPF_MAP_CAN_WRITE; 448 + } 449 + 450 + static inline bool bpf_map_flags_access_ok(u32 access_flags) 451 + { 452 + return (access_flags & (BPF_F_RDONLY_PROG | BPF_F_WRONLY_PROG)) != 453 + (BPF_F_RDONLY_PROG | BPF_F_WRONLY_PROG); 454 + } 432 455 433 456 struct bpf_event_entry { 434 457 struct perf_event *event; ··· 482 445 483 446 u64 bpf_event_output(struct bpf_map *map, u64 flags, void *meta, u64 meta_size, 484 447 void *ctx, u64 ctx_size, bpf_ctx_copy_t ctx_copy); 485 - 486 - int bpf_prog_test_run_xdp(struct bpf_prog *prog, const union bpf_attr *kattr, 487 - union bpf_attr __user *uattr); 488 - int bpf_prog_test_run_skb(struct bpf_prog *prog, const union bpf_attr *kattr, 489 - union bpf_attr __user *uattr); 490 - int bpf_prog_test_run_flow_dissector(struct bpf_prog *prog, 491 - const union bpf_attr *kattr, 492 - union bpf_attr __user *uattr); 493 448 494 449 /* an array of programs to be executed under rcu_lock. 495 450 * ··· 673 644 struct bpf_prog *bpf_prog_get_type_path(const char *name, enum bpf_prog_type type); 674 645 int array_map_alloc_check(union bpf_attr *attr); 675 646 647 + int bpf_prog_test_run_xdp(struct bpf_prog *prog, const union bpf_attr *kattr, 648 + union bpf_attr __user *uattr); 649 + int bpf_prog_test_run_skb(struct bpf_prog *prog, const union bpf_attr *kattr, 650 + union bpf_attr __user *uattr); 651 + int bpf_prog_test_run_flow_dissector(struct bpf_prog *prog, 652 + const union bpf_attr *kattr, 653 + union bpf_attr __user *uattr); 676 654 #else /* !CONFIG_BPF_SYSCALL */ 677 655 static inline struct bpf_prog *bpf_prog_get(u32 ufd) 678 656 { ··· 790 754 enum bpf_prog_type type) 791 755 { 792 756 return ERR_PTR(-EOPNOTSUPP); 757 + } 758 + 759 + static inline int bpf_prog_test_run_xdp(struct bpf_prog *prog, 760 + const union bpf_attr *kattr, 761 + union bpf_attr __user *uattr) 762 + { 763 + return -ENOTSUPP; 764 + } 765 + 766 + static inline int bpf_prog_test_run_skb(struct bpf_prog *prog, 767 + const union bpf_attr *kattr, 768 + union bpf_attr __user *uattr) 769 + { 770 + return -ENOTSUPP; 771 + } 772 + 773 + static inline int bpf_prog_test_run_flow_dissector(struct bpf_prog *prog, 774 + const union bpf_attr *kattr, 775 + union bpf_attr __user *uattr) 776 + { 777 + return -ENOTSUPP; 793 778 } 794 779 #endif /* CONFIG_BPF_SYSCALL */ 795 780
+27
include/linux/bpf_verifier.h
··· 207 207 struct bpf_verifier_state_list { 208 208 struct bpf_verifier_state state; 209 209 struct bpf_verifier_state_list *next; 210 + int miss_cnt, hit_cnt; 210 211 }; 211 212 212 213 /* Possible states for alu_state member. */ ··· 224 223 unsigned long map_state; /* pointer/poison value for maps */ 225 224 s32 call_imm; /* saved imm field of call insn */ 226 225 u32 alu_limit; /* limit for add/sub register with pointer */ 226 + struct { 227 + u32 map_index; /* index into used_maps[] */ 228 + u32 map_off; /* offset from value base address */ 229 + }; 227 230 }; 228 231 int ctx_field_size; /* the ctx field size for load insn, maybe 0 */ 229 232 int sanitize_stack_off; /* stack slot to be cleared */ ··· 252 247 { 253 248 return log->len_used >= log->len_total - 1; 254 249 } 250 + 251 + #define BPF_LOG_LEVEL1 1 252 + #define BPF_LOG_LEVEL2 2 253 + #define BPF_LOG_STATS 4 254 + #define BPF_LOG_LEVEL (BPF_LOG_LEVEL1 | BPF_LOG_LEVEL2) 255 + #define BPF_LOG_MASK (BPF_LOG_LEVEL | BPF_LOG_STATS) 255 256 256 257 static inline bool bpf_verifier_log_needed(const struct bpf_verifier_log *log) 257 258 { ··· 285 274 bool strict_alignment; /* perform strict pointer alignment checks */ 286 275 struct bpf_verifier_state *cur_state; /* current verifier state */ 287 276 struct bpf_verifier_state_list **explored_states; /* search pruning optimization */ 277 + struct bpf_verifier_state_list *free_list; 288 278 struct bpf_map *used_maps[MAX_USED_MAPS]; /* array of map's used by eBPF program */ 289 279 u32 used_map_cnt; /* number of used maps */ 290 280 u32 id_gen; /* used to generate unique reg IDs */ ··· 296 284 struct bpf_verifier_log log; 297 285 struct bpf_subprog_info subprog_info[BPF_MAX_SUBPROGS + 1]; 298 286 u32 subprog_cnt; 287 + /* number of instructions analyzed by the verifier */ 288 + u32 insn_processed; 289 + /* total verification time */ 290 + u64 verification_time; 291 + /* maximum number of verifier states kept in 'branching' instructions */ 292 + u32 max_states_per_insn; 293 + /* total number of allocated verifier states */ 294 + u32 total_states; 295 + /* some states are freed during program analysis. 296 + * this is peak number of states. this number dominates kernel 297 + * memory consumption during verification 298 + */ 299 + u32 peak_states; 300 + /* longest register parentage chain walked for liveness marking */ 301 + u32 longest_mark_read_walk; 299 302 }; 300 303 301 304 __printf(2, 0) void bpf_verifier_vlog(struct bpf_verifier_log *log,
+1
include/linux/btf.h
··· 51 51 const struct btf_member *m, 52 52 u32 expected_offset, u32 expected_size); 53 53 int btf_find_spin_lock(const struct btf *btf, const struct btf_type *t); 54 + bool btf_type_is_void(const struct btf_type *t); 54 55 55 56 #ifdef CONFIG_BPF_SYSCALL 56 57 const struct btf_type *btf_type_by_id(const struct btf *btf, u32 type_id);
+35 -2
include/uapi/linux/bpf.h
··· 105 105 BPF_BTF_GET_FD_BY_ID, 106 106 BPF_TASK_FD_QUERY, 107 107 BPF_MAP_LOOKUP_AND_DELETE_ELEM, 108 + BPF_MAP_FREEZE, 108 109 }; 109 110 110 111 enum bpf_map_type { ··· 256 255 */ 257 256 #define BPF_F_ANY_ALIGNMENT (1U << 1) 258 257 259 - /* when bpf_ldimm64->src_reg == BPF_PSEUDO_MAP_FD, bpf_ldimm64->imm == fd */ 258 + /* When BPF ldimm64's insn[0].src_reg != 0 then this can have 259 + * two extensions: 260 + * 261 + * insn[0].src_reg: BPF_PSEUDO_MAP_FD BPF_PSEUDO_MAP_VALUE 262 + * insn[0].imm: map fd map fd 263 + * insn[1].imm: 0 offset into value 264 + * insn[0].off: 0 0 265 + * insn[1].off: 0 0 266 + * ldimm64 rewrite: address of map address of map[0]+offset 267 + * verifier type: CONST_PTR_TO_MAP PTR_TO_MAP_VALUE 268 + */ 260 269 #define BPF_PSEUDO_MAP_FD 1 270 + #define BPF_PSEUDO_MAP_VALUE 2 261 271 262 272 /* when bpf_call->src_reg == BPF_PSEUDO_CALL, bpf_call->imm == pc-relative 263 273 * offset to another bpf function ··· 295 283 296 284 #define BPF_OBJ_NAME_LEN 16U 297 285 298 - /* Flags for accessing BPF object */ 286 + /* Flags for accessing BPF object from syscall side. */ 299 287 #define BPF_F_RDONLY (1U << 3) 300 288 #define BPF_F_WRONLY (1U << 4) 301 289 ··· 304 292 305 293 /* Zero-initialize hash function seed. This should only be used for testing. */ 306 294 #define BPF_F_ZERO_SEED (1U << 6) 295 + 296 + /* Flags for accessing BPF object from program side. */ 297 + #define BPF_F_RDONLY_PROG (1U << 7) 298 + #define BPF_F_WRONLY_PROG (1U << 8) 307 299 308 300 /* flags for BPF_PROG_QUERY */ 309 301 #define BPF_F_QUERY_EFFECTIVE (1U << 0) ··· 412 396 __aligned_u64 data_out; 413 397 __u32 repeat; 414 398 __u32 duration; 399 + __u32 ctx_size_in; /* input: len of ctx_in */ 400 + __u32 ctx_size_out; /* input/output: len of ctx_out 401 + * returns ENOSPC if ctx_out 402 + * is too small. 403 + */ 404 + __aligned_u64 ctx_in; 405 + __aligned_u64 ctx_out; 415 406 } test; 416 407 417 408 struct { /* anonymous struct used by BPF_*_GET_*_ID */ ··· 1522 1499 * * **BPF_F_ADJ_ROOM_ENCAP_L4_GRE **: 1523 1500 * * **BPF_F_ADJ_ROOM_ENCAP_L4_UDP **: 1524 1501 * Use with ENCAP_L3 flags to further specify the tunnel type. 1502 + * 1503 + * * **BPF_F_ADJ_ROOM_ENCAP_L2(len) **: 1504 + * Use with ENCAP_L3/L4 flags to further specify the tunnel 1505 + * type; **len** is the length of the inner MAC header. 1525 1506 * 1526 1507 * A call to this helper is susceptible to change the underlaying 1527 1508 * packet buffer. Therefore, at load time, all checks on pointers ··· 2668 2641 /* BPF_FUNC_skb_adjust_room flags. */ 2669 2642 #define BPF_F_ADJ_ROOM_FIXED_GSO (1ULL << 0) 2670 2643 2644 + #define BPF_ADJ_ROOM_ENCAP_L2_MASK 0xff 2645 + #define BPF_ADJ_ROOM_ENCAP_L2_SHIFT 56 2646 + 2671 2647 #define BPF_F_ADJ_ROOM_ENCAP_L3_IPV4 (1ULL << 1) 2672 2648 #define BPF_F_ADJ_ROOM_ENCAP_L3_IPV6 (1ULL << 2) 2673 2649 #define BPF_F_ADJ_ROOM_ENCAP_L4_GRE (1ULL << 3) 2674 2650 #define BPF_F_ADJ_ROOM_ENCAP_L4_UDP (1ULL << 4) 2651 + #define BPF_F_ADJ_ROOM_ENCAP_L2(len) (((__u64)len & \ 2652 + BPF_ADJ_ROOM_ENCAP_L2_MASK) \ 2653 + << BPF_ADJ_ROOM_ENCAP_L2_SHIFT) 2675 2654 2676 2655 /* Mode for BPF_FUNC_skb_adjust_room helper. */ 2677 2656 enum bpf_adj_room_mode {
+28 -4
include/uapi/linux/btf.h
··· 39 39 * struct, union and fwd 40 40 */ 41 41 __u32 info; 42 - /* "size" is used by INT, ENUM, STRUCT and UNION. 42 + /* "size" is used by INT, ENUM, STRUCT, UNION and DATASEC. 43 43 * "size" tells the size of the type it is describing. 44 44 * 45 45 * "type" is used by PTR, TYPEDEF, VOLATILE, CONST, RESTRICT, 46 - * FUNC and FUNC_PROTO. 46 + * FUNC, FUNC_PROTO and VAR. 47 47 * "type" is a type_id referring to another type. 48 48 */ 49 49 union { ··· 70 70 #define BTF_KIND_RESTRICT 11 /* Restrict */ 71 71 #define BTF_KIND_FUNC 12 /* Function */ 72 72 #define BTF_KIND_FUNC_PROTO 13 /* Function Proto */ 73 - #define BTF_KIND_MAX 13 74 - #define NR_BTF_KINDS 14 73 + #define BTF_KIND_VAR 14 /* Variable */ 74 + #define BTF_KIND_DATASEC 15 /* Section */ 75 + #define BTF_KIND_MAX BTF_KIND_DATASEC 76 + #define NR_BTF_KINDS (BTF_KIND_MAX + 1) 75 77 76 78 /* For some specific BTF_KIND, "struct btf_type" is immediately 77 79 * followed by extra data. ··· 138 136 struct btf_param { 139 137 __u32 name_off; 140 138 __u32 type; 139 + }; 140 + 141 + enum { 142 + BTF_VAR_STATIC = 0, 143 + BTF_VAR_GLOBAL_ALLOCATED, 144 + }; 145 + 146 + /* BTF_KIND_VAR is followed by a single "struct btf_var" to describe 147 + * additional information related to the variable such as its linkage. 148 + */ 149 + struct btf_var { 150 + __u32 linkage; 151 + }; 152 + 153 + /* BTF_KIND_DATASEC is followed by multiple "struct btf_var_secinfo" 154 + * to describe all BTF_KIND_VAR types it contains along with it's 155 + * in-section offset as well as size. 156 + */ 157 + struct btf_var_secinfo { 158 + __u32 type; 159 + __u32 offset; 160 + __u32 size; 141 161 }; 142 162 143 163 #endif /* _UAPI__LINUX_BTF_H__ */
+51 -2
kernel/bpf/arraymap.c
··· 22 22 #include "map_in_map.h" 23 23 24 24 #define ARRAY_CREATE_FLAG_MASK \ 25 - (BPF_F_NUMA_NODE | BPF_F_RDONLY | BPF_F_WRONLY) 25 + (BPF_F_NUMA_NODE | BPF_F_ACCESS_MASK) 26 26 27 27 static void bpf_array_free_percpu(struct bpf_array *array) 28 28 { ··· 63 63 if (attr->max_entries == 0 || attr->key_size != 4 || 64 64 attr->value_size == 0 || 65 65 attr->map_flags & ~ARRAY_CREATE_FLAG_MASK || 66 + !bpf_map_flags_access_ok(attr->map_flags) || 66 67 (percpu && numa_node != NUMA_NO_NODE)) 67 68 return -EINVAL; 68 69 ··· 159 158 return NULL; 160 159 161 160 return array->value + array->elem_size * (index & array->index_mask); 161 + } 162 + 163 + static int array_map_direct_value_addr(const struct bpf_map *map, u64 *imm, 164 + u32 off) 165 + { 166 + struct bpf_array *array = container_of(map, struct bpf_array, map); 167 + 168 + if (map->max_entries != 1) 169 + return -ENOTSUPP; 170 + if (off >= map->value_size) 171 + return -EINVAL; 172 + 173 + *imm = (unsigned long)array->value; 174 + return 0; 175 + } 176 + 177 + static int array_map_direct_value_meta(const struct bpf_map *map, u64 imm, 178 + u32 *off) 179 + { 180 + struct bpf_array *array = container_of(map, struct bpf_array, map); 181 + u64 base = (unsigned long)array->value; 182 + u64 range = array->elem_size; 183 + 184 + if (map->max_entries != 1) 185 + return -ENOTSUPP; 186 + if (imm < base || imm >= base + range) 187 + return -ENOENT; 188 + 189 + *off = imm - base; 190 + return 0; 162 191 } 163 192 164 193 /* emit BPF instructions equivalent to C code of array_map_lookup_elem() */ ··· 391 360 return; 392 361 } 393 362 394 - seq_printf(m, "%u: ", *(u32 *)key); 363 + if (map->btf_key_type_id) 364 + seq_printf(m, "%u: ", *(u32 *)key); 395 365 btf_type_seq_show(map->btf, map->btf_value_type_id, value, m); 396 366 seq_puts(m, "\n"); 397 367 ··· 429 397 { 430 398 u32 int_data; 431 399 400 + /* One exception for keyless BTF: .bss/.data/.rodata map */ 401 + if (btf_type_is_void(key_type)) { 402 + if (map->map_type != BPF_MAP_TYPE_ARRAY || 403 + map->max_entries != 1) 404 + return -EINVAL; 405 + 406 + if (BTF_INFO_KIND(value_type->info) != BTF_KIND_DATASEC) 407 + return -EINVAL; 408 + 409 + return 0; 410 + } 411 + 432 412 if (BTF_INFO_KIND(key_type->info) != BTF_KIND_INT) 433 413 return -EINVAL; 434 414 ··· 463 419 .map_update_elem = array_map_update_elem, 464 420 .map_delete_elem = array_map_delete_elem, 465 421 .map_gen_lookup = array_map_gen_lookup, 422 + .map_direct_value_addr = array_map_direct_value_addr, 423 + .map_direct_value_meta = array_map_direct_value_meta, 466 424 .map_seq_show_elem = array_map_seq_show_elem, 467 425 .map_check_btf = array_map_check_btf, 468 426 }; ··· 485 439 { 486 440 /* only file descriptors can be stored in this type of map */ 487 441 if (attr->value_size != sizeof(u32)) 442 + return -EINVAL; 443 + /* Program read-only/write-only not supported for special maps yet. */ 444 + if (attr->map_flags & (BPF_F_RDONLY_PROG | BPF_F_WRONLY_PROG)) 488 445 return -EINVAL; 489 446 return array_map_alloc_check(attr); 490 447 }
+398 -21
kernel/bpf/btf.c
··· 185 185 i < btf_type_vlen(struct_type); \ 186 186 i++, member++) 187 187 188 + #define for_each_vsi(i, struct_type, member) \ 189 + for (i = 0, member = btf_type_var_secinfo(struct_type); \ 190 + i < btf_type_vlen(struct_type); \ 191 + i++, member++) 192 + 193 + #define for_each_vsi_from(i, from, struct_type, member) \ 194 + for (i = from, member = btf_type_var_secinfo(struct_type) + from; \ 195 + i < btf_type_vlen(struct_type); \ 196 + i++, member++) 197 + 188 198 static DEFINE_IDR(btf_idr); 189 199 static DEFINE_SPINLOCK(btf_idr_lock); 190 200 ··· 272 262 [BTF_KIND_RESTRICT] = "RESTRICT", 273 263 [BTF_KIND_FUNC] = "FUNC", 274 264 [BTF_KIND_FUNC_PROTO] = "FUNC_PROTO", 265 + [BTF_KIND_VAR] = "VAR", 266 + [BTF_KIND_DATASEC] = "DATASEC", 275 267 }; 276 268 277 269 struct btf_kind_operations { ··· 326 314 return false; 327 315 } 328 316 329 - static bool btf_type_is_void(const struct btf_type *t) 317 + bool btf_type_is_void(const struct btf_type *t) 330 318 { 331 319 return t == &btf_void; 332 320 } ··· 387 375 return BTF_INFO_KIND(t->info) == BTF_KIND_INT; 388 376 } 389 377 378 + static bool btf_type_is_var(const struct btf_type *t) 379 + { 380 + return BTF_INFO_KIND(t->info) == BTF_KIND_VAR; 381 + } 382 + 383 + static bool btf_type_is_datasec(const struct btf_type *t) 384 + { 385 + return BTF_INFO_KIND(t->info) == BTF_KIND_DATASEC; 386 + } 387 + 388 + /* Types that act only as a source, not sink or intermediate 389 + * type when resolving. 390 + */ 391 + static bool btf_type_is_resolve_source_only(const struct btf_type *t) 392 + { 393 + return btf_type_is_var(t) || 394 + btf_type_is_datasec(t); 395 + } 396 + 390 397 /* What types need to be resolved? 391 398 * 392 399 * btf_type_is_modifier() is an obvious one. 393 400 * 394 401 * btf_type_is_struct() because its member refers to 395 402 * another type (through member->type). 396 - 403 + * 404 + * btf_type_is_var() because the variable refers to 405 + * another type. btf_type_is_datasec() holds multiple 406 + * btf_type_is_var() types that need resolving. 407 + * 397 408 * btf_type_is_array() because its element (array->type) 398 409 * refers to another type. Array can be thought of a 399 410 * special case of struct while array just has the same ··· 425 390 static bool btf_type_needs_resolve(const struct btf_type *t) 426 391 { 427 392 return btf_type_is_modifier(t) || 428 - btf_type_is_ptr(t) || 429 - btf_type_is_struct(t) || 430 - btf_type_is_array(t); 393 + btf_type_is_ptr(t) || 394 + btf_type_is_struct(t) || 395 + btf_type_is_array(t) || 396 + btf_type_is_var(t) || 397 + btf_type_is_datasec(t); 431 398 } 432 399 433 400 /* t->size can be used */ ··· 440 403 case BTF_KIND_STRUCT: 441 404 case BTF_KIND_UNION: 442 405 case BTF_KIND_ENUM: 406 + case BTF_KIND_DATASEC: 443 407 return true; 444 408 } 445 409 ··· 505 467 return (const struct btf_enum *)(t + 1); 506 468 } 507 469 470 + static const struct btf_var *btf_type_var(const struct btf_type *t) 471 + { 472 + return (const struct btf_var *)(t + 1); 473 + } 474 + 475 + static const struct btf_var_secinfo *btf_type_var_secinfo(const struct btf_type *t) 476 + { 477 + return (const struct btf_var_secinfo *)(t + 1); 478 + } 479 + 508 480 static const struct btf_kind_operations *btf_type_ops(const struct btf_type *t) 509 481 { 510 482 return kind_ops[BTF_INFO_KIND(t->info)]; ··· 526 478 offset < btf->hdr.str_len; 527 479 } 528 480 529 - /* Only C-style identifier is permitted. This can be relaxed if 530 - * necessary. 531 - */ 532 - static bool btf_name_valid_identifier(const struct btf *btf, u32 offset) 481 + static bool __btf_name_char_ok(char c, bool first, bool dot_ok) 482 + { 483 + if ((first ? !isalpha(c) : 484 + !isalnum(c)) && 485 + c != '_' && 486 + ((c == '.' && !dot_ok) || 487 + c != '.')) 488 + return false; 489 + return true; 490 + } 491 + 492 + static bool __btf_name_valid(const struct btf *btf, u32 offset, bool dot_ok) 533 493 { 534 494 /* offset must be valid */ 535 495 const char *src = &btf->strings[offset]; 536 496 const char *src_limit; 537 497 538 - if (!isalpha(*src) && *src != '_') 498 + if (!__btf_name_char_ok(*src, true, dot_ok)) 539 499 return false; 540 500 541 501 /* set a limit on identifier length */ 542 502 src_limit = src + KSYM_NAME_LEN; 543 503 src++; 544 504 while (*src && src < src_limit) { 545 - if (!isalnum(*src) && *src != '_') 505 + if (!__btf_name_char_ok(*src, false, dot_ok)) 546 506 return false; 547 507 src++; 548 508 } 549 509 550 510 return !*src; 511 + } 512 + 513 + /* Only C-style identifier is permitted. This can be relaxed if 514 + * necessary. 515 + */ 516 + static bool btf_name_valid_identifier(const struct btf *btf, u32 offset) 517 + { 518 + return __btf_name_valid(btf, offset, false); 519 + } 520 + 521 + static bool btf_name_valid_section(const struct btf *btf, u32 offset) 522 + { 523 + return __btf_name_valid(btf, offset, true); 551 524 } 552 525 553 526 static const char *__btf_name_by_offset(const struct btf *btf, u32 offset) ··· 756 687 __btf_name_by_offset(btf, member->name_off), 757 688 member->type, member->offset); 758 689 690 + if (fmt && *fmt) { 691 + __btf_verifier_log(log, " "); 692 + va_start(args, fmt); 693 + bpf_verifier_vlog(log, fmt, args); 694 + va_end(args); 695 + } 696 + 697 + __btf_verifier_log(log, "\n"); 698 + } 699 + 700 + __printf(4, 5) 701 + static void btf_verifier_log_vsi(struct btf_verifier_env *env, 702 + const struct btf_type *datasec_type, 703 + const struct btf_var_secinfo *vsi, 704 + const char *fmt, ...) 705 + { 706 + struct bpf_verifier_log *log = &env->log; 707 + va_list args; 708 + 709 + if (!bpf_verifier_log_needed(log)) 710 + return; 711 + if (env->phase != CHECK_META) 712 + btf_verifier_log_type(env, datasec_type, NULL); 713 + 714 + __btf_verifier_log(log, "\t type_id=%u offset=%u size=%u", 715 + vsi->type, vsi->offset, vsi->size); 759 716 if (fmt && *fmt) { 760 717 __btf_verifier_log(log, " "); 761 718 va_start(args, fmt); ··· 1069 974 } else if (btf_type_is_ptr(size_type)) { 1070 975 size = sizeof(void *); 1071 976 } else { 1072 - if (WARN_ON_ONCE(!btf_type_is_modifier(size_type))) 977 + if (WARN_ON_ONCE(!btf_type_is_modifier(size_type) && 978 + !btf_type_is_var(size_type))) 1073 979 return NULL; 1074 980 1075 981 size = btf->resolved_sizes[size_type_id]; ··· 1605 1509 u32 next_type_size = 0; 1606 1510 1607 1511 next_type = btf_type_by_id(btf, next_type_id); 1608 - if (!next_type) { 1512 + if (!next_type || btf_type_is_resolve_source_only(next_type)) { 1609 1513 btf_verifier_log_type(env, v->t, "Invalid type_id"); 1610 1514 return -EINVAL; 1611 1515 } ··· 1638 1542 return 0; 1639 1543 } 1640 1544 1545 + static int btf_var_resolve(struct btf_verifier_env *env, 1546 + const struct resolve_vertex *v) 1547 + { 1548 + const struct btf_type *next_type; 1549 + const struct btf_type *t = v->t; 1550 + u32 next_type_id = t->type; 1551 + struct btf *btf = env->btf; 1552 + u32 next_type_size; 1553 + 1554 + next_type = btf_type_by_id(btf, next_type_id); 1555 + if (!next_type || btf_type_is_resolve_source_only(next_type)) { 1556 + btf_verifier_log_type(env, v->t, "Invalid type_id"); 1557 + return -EINVAL; 1558 + } 1559 + 1560 + if (!env_type_is_resolve_sink(env, next_type) && 1561 + !env_type_is_resolved(env, next_type_id)) 1562 + return env_stack_push(env, next_type, next_type_id); 1563 + 1564 + if (btf_type_is_modifier(next_type)) { 1565 + const struct btf_type *resolved_type; 1566 + u32 resolved_type_id; 1567 + 1568 + resolved_type_id = next_type_id; 1569 + resolved_type = btf_type_id_resolve(btf, &resolved_type_id); 1570 + 1571 + if (btf_type_is_ptr(resolved_type) && 1572 + !env_type_is_resolve_sink(env, resolved_type) && 1573 + !env_type_is_resolved(env, resolved_type_id)) 1574 + return env_stack_push(env, resolved_type, 1575 + resolved_type_id); 1576 + } 1577 + 1578 + /* We must resolve to something concrete at this point, no 1579 + * forward types or similar that would resolve to size of 1580 + * zero is allowed. 1581 + */ 1582 + if (!btf_type_id_size(btf, &next_type_id, &next_type_size)) { 1583 + btf_verifier_log_type(env, v->t, "Invalid type_id"); 1584 + return -EINVAL; 1585 + } 1586 + 1587 + env_stack_pop_resolved(env, next_type_id, next_type_size); 1588 + 1589 + return 0; 1590 + } 1591 + 1641 1592 static int btf_ptr_resolve(struct btf_verifier_env *env, 1642 1593 const struct resolve_vertex *v) 1643 1594 { ··· 1694 1551 struct btf *btf = env->btf; 1695 1552 1696 1553 next_type = btf_type_by_id(btf, next_type_id); 1697 - if (!next_type) { 1554 + if (!next_type || btf_type_is_resolve_source_only(next_type)) { 1698 1555 btf_verifier_log_type(env, v->t, "Invalid type_id"); 1699 1556 return -EINVAL; 1700 1557 } ··· 1746 1603 const struct btf_type *t, 1747 1604 u32 type_id, void *data, 1748 1605 u8 bits_offset, struct seq_file *m) 1606 + { 1607 + t = btf_type_id_resolve(btf, &type_id); 1608 + 1609 + btf_type_ops(t)->seq_show(btf, t, type_id, data, bits_offset, m); 1610 + } 1611 + 1612 + static void btf_var_seq_show(const struct btf *btf, const struct btf_type *t, 1613 + u32 type_id, void *data, u8 bits_offset, 1614 + struct seq_file *m) 1749 1615 { 1750 1616 t = btf_type_id_resolve(btf, &type_id); 1751 1617 ··· 1928 1776 /* Check array->index_type */ 1929 1777 index_type_id = array->index_type; 1930 1778 index_type = btf_type_by_id(btf, index_type_id); 1931 - if (btf_type_nosize_or_null(index_type)) { 1779 + if (btf_type_is_resolve_source_only(index_type) || 1780 + btf_type_nosize_or_null(index_type)) { 1932 1781 btf_verifier_log_type(env, v->t, "Invalid index"); 1933 1782 return -EINVAL; 1934 1783 } ··· 1948 1795 /* Check array->type */ 1949 1796 elem_type_id = array->type; 1950 1797 elem_type = btf_type_by_id(btf, elem_type_id); 1951 - if (btf_type_nosize_or_null(elem_type)) { 1798 + if (btf_type_is_resolve_source_only(elem_type) || 1799 + btf_type_nosize_or_null(elem_type)) { 1952 1800 btf_verifier_log_type(env, v->t, 1953 1801 "Invalid elem"); 1954 1802 return -EINVAL; ··· 2170 2016 const struct btf_type *member_type = btf_type_by_id(env->btf, 2171 2017 member_type_id); 2172 2018 2173 - if (btf_type_nosize_or_null(member_type)) { 2019 + if (btf_type_is_resolve_source_only(member_type) || 2020 + btf_type_nosize_or_null(member_type)) { 2174 2021 btf_verifier_log_member(env, v->t, member, 2175 2022 "Invalid member"); 2176 2023 return -EINVAL; ··· 2566 2411 .seq_show = btf_df_seq_show, 2567 2412 }; 2568 2413 2414 + static s32 btf_var_check_meta(struct btf_verifier_env *env, 2415 + const struct btf_type *t, 2416 + u32 meta_left) 2417 + { 2418 + const struct btf_var *var; 2419 + u32 meta_needed = sizeof(*var); 2420 + 2421 + if (meta_left < meta_needed) { 2422 + btf_verifier_log_basic(env, t, 2423 + "meta_left:%u meta_needed:%u", 2424 + meta_left, meta_needed); 2425 + return -EINVAL; 2426 + } 2427 + 2428 + if (btf_type_vlen(t)) { 2429 + btf_verifier_log_type(env, t, "vlen != 0"); 2430 + return -EINVAL; 2431 + } 2432 + 2433 + if (btf_type_kflag(t)) { 2434 + btf_verifier_log_type(env, t, "Invalid btf_info kind_flag"); 2435 + return -EINVAL; 2436 + } 2437 + 2438 + if (!t->name_off || 2439 + !__btf_name_valid(env->btf, t->name_off, true)) { 2440 + btf_verifier_log_type(env, t, "Invalid name"); 2441 + return -EINVAL; 2442 + } 2443 + 2444 + /* A var cannot be in type void */ 2445 + if (!t->type || !BTF_TYPE_ID_VALID(t->type)) { 2446 + btf_verifier_log_type(env, t, "Invalid type_id"); 2447 + return -EINVAL; 2448 + } 2449 + 2450 + var = btf_type_var(t); 2451 + if (var->linkage != BTF_VAR_STATIC && 2452 + var->linkage != BTF_VAR_GLOBAL_ALLOCATED) { 2453 + btf_verifier_log_type(env, t, "Linkage not supported"); 2454 + return -EINVAL; 2455 + } 2456 + 2457 + btf_verifier_log_type(env, t, NULL); 2458 + 2459 + return meta_needed; 2460 + } 2461 + 2462 + static void btf_var_log(struct btf_verifier_env *env, const struct btf_type *t) 2463 + { 2464 + const struct btf_var *var = btf_type_var(t); 2465 + 2466 + btf_verifier_log(env, "type_id=%u linkage=%u", t->type, var->linkage); 2467 + } 2468 + 2469 + static const struct btf_kind_operations var_ops = { 2470 + .check_meta = btf_var_check_meta, 2471 + .resolve = btf_var_resolve, 2472 + .check_member = btf_df_check_member, 2473 + .check_kflag_member = btf_df_check_kflag_member, 2474 + .log_details = btf_var_log, 2475 + .seq_show = btf_var_seq_show, 2476 + }; 2477 + 2478 + static s32 btf_datasec_check_meta(struct btf_verifier_env *env, 2479 + const struct btf_type *t, 2480 + u32 meta_left) 2481 + { 2482 + const struct btf_var_secinfo *vsi; 2483 + u64 last_vsi_end_off = 0, sum = 0; 2484 + u32 i, meta_needed; 2485 + 2486 + meta_needed = btf_type_vlen(t) * sizeof(*vsi); 2487 + if (meta_left < meta_needed) { 2488 + btf_verifier_log_basic(env, t, 2489 + "meta_left:%u meta_needed:%u", 2490 + meta_left, meta_needed); 2491 + return -EINVAL; 2492 + } 2493 + 2494 + if (!btf_type_vlen(t)) { 2495 + btf_verifier_log_type(env, t, "vlen == 0"); 2496 + return -EINVAL; 2497 + } 2498 + 2499 + if (!t->size) { 2500 + btf_verifier_log_type(env, t, "size == 0"); 2501 + return -EINVAL; 2502 + } 2503 + 2504 + if (btf_type_kflag(t)) { 2505 + btf_verifier_log_type(env, t, "Invalid btf_info kind_flag"); 2506 + return -EINVAL; 2507 + } 2508 + 2509 + if (!t->name_off || 2510 + !btf_name_valid_section(env->btf, t->name_off)) { 2511 + btf_verifier_log_type(env, t, "Invalid name"); 2512 + return -EINVAL; 2513 + } 2514 + 2515 + btf_verifier_log_type(env, t, NULL); 2516 + 2517 + for_each_vsi(i, t, vsi) { 2518 + /* A var cannot be in type void */ 2519 + if (!vsi->type || !BTF_TYPE_ID_VALID(vsi->type)) { 2520 + btf_verifier_log_vsi(env, t, vsi, 2521 + "Invalid type_id"); 2522 + return -EINVAL; 2523 + } 2524 + 2525 + if (vsi->offset < last_vsi_end_off || vsi->offset >= t->size) { 2526 + btf_verifier_log_vsi(env, t, vsi, 2527 + "Invalid offset"); 2528 + return -EINVAL; 2529 + } 2530 + 2531 + if (!vsi->size || vsi->size > t->size) { 2532 + btf_verifier_log_vsi(env, t, vsi, 2533 + "Invalid size"); 2534 + return -EINVAL; 2535 + } 2536 + 2537 + last_vsi_end_off = vsi->offset + vsi->size; 2538 + if (last_vsi_end_off > t->size) { 2539 + btf_verifier_log_vsi(env, t, vsi, 2540 + "Invalid offset+size"); 2541 + return -EINVAL; 2542 + } 2543 + 2544 + btf_verifier_log_vsi(env, t, vsi, NULL); 2545 + sum += vsi->size; 2546 + } 2547 + 2548 + if (t->size < sum) { 2549 + btf_verifier_log_type(env, t, "Invalid btf_info size"); 2550 + return -EINVAL; 2551 + } 2552 + 2553 + return meta_needed; 2554 + } 2555 + 2556 + static int btf_datasec_resolve(struct btf_verifier_env *env, 2557 + const struct resolve_vertex *v) 2558 + { 2559 + const struct btf_var_secinfo *vsi; 2560 + struct btf *btf = env->btf; 2561 + u16 i; 2562 + 2563 + for_each_vsi_from(i, v->next_member, v->t, vsi) { 2564 + u32 var_type_id = vsi->type, type_id, type_size = 0; 2565 + const struct btf_type *var_type = btf_type_by_id(env->btf, 2566 + var_type_id); 2567 + if (!var_type || !btf_type_is_var(var_type)) { 2568 + btf_verifier_log_vsi(env, v->t, vsi, 2569 + "Not a VAR kind member"); 2570 + return -EINVAL; 2571 + } 2572 + 2573 + if (!env_type_is_resolve_sink(env, var_type) && 2574 + !env_type_is_resolved(env, var_type_id)) { 2575 + env_stack_set_next_member(env, i + 1); 2576 + return env_stack_push(env, var_type, var_type_id); 2577 + } 2578 + 2579 + type_id = var_type->type; 2580 + if (!btf_type_id_size(btf, &type_id, &type_size)) { 2581 + btf_verifier_log_vsi(env, v->t, vsi, "Invalid type"); 2582 + return -EINVAL; 2583 + } 2584 + 2585 + if (vsi->size < type_size) { 2586 + btf_verifier_log_vsi(env, v->t, vsi, "Invalid size"); 2587 + return -EINVAL; 2588 + } 2589 + } 2590 + 2591 + env_stack_pop_resolved(env, 0, 0); 2592 + return 0; 2593 + } 2594 + 2595 + static void btf_datasec_log(struct btf_verifier_env *env, 2596 + const struct btf_type *t) 2597 + { 2598 + btf_verifier_log(env, "size=%u vlen=%u", t->size, btf_type_vlen(t)); 2599 + } 2600 + 2601 + static void btf_datasec_seq_show(const struct btf *btf, 2602 + const struct btf_type *t, u32 type_id, 2603 + void *data, u8 bits_offset, 2604 + struct seq_file *m) 2605 + { 2606 + const struct btf_var_secinfo *vsi; 2607 + const struct btf_type *var; 2608 + u32 i; 2609 + 2610 + seq_printf(m, "section (\"%s\") = {", __btf_name_by_offset(btf, t->name_off)); 2611 + for_each_vsi(i, t, vsi) { 2612 + var = btf_type_by_id(btf, vsi->type); 2613 + if (i) 2614 + seq_puts(m, ","); 2615 + btf_type_ops(var)->seq_show(btf, var, vsi->type, 2616 + data + vsi->offset, bits_offset, m); 2617 + } 2618 + seq_puts(m, "}"); 2619 + } 2620 + 2621 + static const struct btf_kind_operations datasec_ops = { 2622 + .check_meta = btf_datasec_check_meta, 2623 + .resolve = btf_datasec_resolve, 2624 + .check_member = btf_df_check_member, 2625 + .check_kflag_member = btf_df_check_kflag_member, 2626 + .log_details = btf_datasec_log, 2627 + .seq_show = btf_datasec_seq_show, 2628 + }; 2629 + 2569 2630 static int btf_func_proto_check(struct btf_verifier_env *env, 2570 2631 const struct btf_type *t) 2571 2632 { ··· 2913 2542 [BTF_KIND_RESTRICT] = &modifier_ops, 2914 2543 [BTF_KIND_FUNC] = &func_ops, 2915 2544 [BTF_KIND_FUNC_PROTO] = &func_proto_ops, 2545 + [BTF_KIND_VAR] = &var_ops, 2546 + [BTF_KIND_DATASEC] = &datasec_ops, 2916 2547 }; 2917 2548 2918 2549 static s32 btf_check_meta(struct btf_verifier_env *env, ··· 2995 2622 if (!env_type_is_resolved(env, type_id)) 2996 2623 return false; 2997 2624 2998 - if (btf_type_is_struct(t)) 2625 + if (btf_type_is_struct(t) || btf_type_is_datasec(t)) 2999 2626 return !btf->resolved_ids[type_id] && 3000 - !btf->resolved_sizes[type_id]; 2627 + !btf->resolved_sizes[type_id]; 3001 2628 3002 - if (btf_type_is_modifier(t) || btf_type_is_ptr(t)) { 2629 + if (btf_type_is_modifier(t) || btf_type_is_ptr(t) || 2630 + btf_type_is_var(t)) { 3003 2631 t = btf_type_id_resolve(btf, &type_id); 3004 - return t && !btf_type_is_modifier(t); 2632 + return t && 2633 + !btf_type_is_modifier(t) && 2634 + !btf_type_is_var(t) && 2635 + !btf_type_is_datasec(t); 3005 2636 } 3006 2637 3007 2638 if (btf_type_is_array(t)) {
+8 -6
kernel/bpf/core.c
··· 292 292 dst[i] = fp->insnsi[i]; 293 293 if (!was_ld_map && 294 294 dst[i].code == (BPF_LD | BPF_IMM | BPF_DW) && 295 - dst[i].src_reg == BPF_PSEUDO_MAP_FD) { 295 + (dst[i].src_reg == BPF_PSEUDO_MAP_FD || 296 + dst[i].src_reg == BPF_PSEUDO_MAP_VALUE)) { 296 297 was_ld_map = true; 297 298 dst[i].imm = 0; 298 299 } else if (was_ld_map && ··· 439 438 u32 insn_adj_cnt, insn_rest, insn_delta = len - 1; 440 439 const u32 cnt_max = S16_MAX; 441 440 struct bpf_prog *prog_adj; 441 + int err; 442 442 443 443 /* Since our patchlet doesn't expand the image, we're done. */ 444 444 if (insn_delta == 0) { ··· 455 453 * we afterwards may not fail anymore. 456 454 */ 457 455 if (insn_adj_cnt > cnt_max && 458 - bpf_adj_branches(prog, off, off + 1, off + len, true)) 459 - return NULL; 456 + (err = bpf_adj_branches(prog, off, off + 1, off + len, true))) 457 + return ERR_PTR(err); 460 458 461 459 /* Several new instructions need to be inserted. Make room 462 460 * for them. Likely, there's no need for a new allocation as ··· 465 463 prog_adj = bpf_prog_realloc(prog, bpf_prog_size(insn_adj_cnt), 466 464 GFP_USER); 467 465 if (!prog_adj) 468 - return NULL; 466 + return ERR_PTR(-ENOMEM); 469 467 470 468 prog_adj->len = insn_adj_cnt; 471 469 ··· 1098 1096 continue; 1099 1097 1100 1098 tmp = bpf_patch_insn_single(clone, i, insn_buff, rewritten); 1101 - if (!tmp) { 1099 + if (IS_ERR(tmp)) { 1102 1100 /* Patching may have repointed aux->prog during 1103 1101 * realloc from the original one, so we need to 1104 1102 * fix it up here on error. 1105 1103 */ 1106 1104 bpf_jit_prog_release_other(prog, clone); 1107 - return ERR_PTR(-ENOMEM); 1105 + return tmp; 1108 1106 } 1109 1107 1110 1108 clone = tmp;
+3 -2
kernel/bpf/disasm.c
··· 205 205 * part of the ldimm64 insn is accessible. 206 206 */ 207 207 u64 imm = ((u64)(insn + 1)->imm << 32) | (u32)insn->imm; 208 - bool map_ptr = insn->src_reg == BPF_PSEUDO_MAP_FD; 208 + bool is_ptr = insn->src_reg == BPF_PSEUDO_MAP_FD || 209 + insn->src_reg == BPF_PSEUDO_MAP_VALUE; 209 210 char tmp[64]; 210 211 211 - if (map_ptr && !allow_ptr_leaks) 212 + if (is_ptr && !allow_ptr_leaks) 212 213 imm = 0; 213 214 214 215 verbose(cbs->private_data, "(%02x) r%d = %s\n",
+3 -3
kernel/bpf/hashtab.c
··· 23 23 24 24 #define HTAB_CREATE_FLAG_MASK \ 25 25 (BPF_F_NO_PREALLOC | BPF_F_NO_COMMON_LRU | BPF_F_NUMA_NODE | \ 26 - BPF_F_RDONLY | BPF_F_WRONLY | BPF_F_ZERO_SEED) 26 + BPF_F_ACCESS_MASK | BPF_F_ZERO_SEED) 27 27 28 28 struct bucket { 29 29 struct hlist_nulls_head head; ··· 262 262 /* Guard against local DoS, and discourage production use. */ 263 263 return -EPERM; 264 264 265 - if (attr->map_flags & ~HTAB_CREATE_FLAG_MASK) 266 - /* reserved bits should not be used */ 265 + if (attr->map_flags & ~HTAB_CREATE_FLAG_MASK || 266 + !bpf_map_flags_access_ok(attr->map_flags)) 267 267 return -EINVAL; 268 268 269 269 if (!lru && percpu_lru)
+3 -3
kernel/bpf/local_storage.c
··· 14 14 #ifdef CONFIG_CGROUP_BPF 15 15 16 16 #define LOCAL_STORAGE_CREATE_FLAG_MASK \ 17 - (BPF_F_NUMA_NODE | BPF_F_RDONLY | BPF_F_WRONLY) 17 + (BPF_F_NUMA_NODE | BPF_F_ACCESS_MASK) 18 18 19 19 struct bpf_cgroup_storage_map { 20 20 struct bpf_map map; ··· 282 282 if (attr->value_size > PAGE_SIZE) 283 283 return ERR_PTR(-E2BIG); 284 284 285 - if (attr->map_flags & ~LOCAL_STORAGE_CREATE_FLAG_MASK) 286 - /* reserved bits should not be used */ 285 + if (attr->map_flags & ~LOCAL_STORAGE_CREATE_FLAG_MASK || 286 + !bpf_map_flags_access_ok(attr->map_flags)) 287 287 return ERR_PTR(-EINVAL); 288 288 289 289 if (attr->max_entries)
+2 -1
kernel/bpf/lpm_trie.c
··· 538 538 #define LPM_KEY_SIZE_MIN LPM_KEY_SIZE(LPM_DATA_SIZE_MIN) 539 539 540 540 #define LPM_CREATE_FLAG_MASK (BPF_F_NO_PREALLOC | BPF_F_NUMA_NODE | \ 541 - BPF_F_RDONLY | BPF_F_WRONLY) 541 + BPF_F_ACCESS_MASK) 542 542 543 543 static struct bpf_map *trie_alloc(union bpf_attr *attr) 544 544 { ··· 553 553 if (attr->max_entries == 0 || 554 554 !(attr->map_flags & BPF_F_NO_PREALLOC) || 555 555 attr->map_flags & ~LPM_CREATE_FLAG_MASK || 556 + !bpf_map_flags_access_ok(attr->map_flags) || 556 557 attr->key_size < LPM_KEY_SIZE_MIN || 557 558 attr->key_size > LPM_KEY_SIZE_MAX || 558 559 attr->value_size < LPM_VAL_SIZE_MIN ||
+3 -3
kernel/bpf/queue_stack_maps.c
··· 11 11 #include "percpu_freelist.h" 12 12 13 13 #define QUEUE_STACK_CREATE_FLAG_MASK \ 14 - (BPF_F_NUMA_NODE | BPF_F_RDONLY | BPF_F_WRONLY) 15 - 14 + (BPF_F_NUMA_NODE | BPF_F_ACCESS_MASK) 16 15 17 16 struct bpf_queue_stack { 18 17 struct bpf_map map; ··· 51 52 /* check sanity of attributes */ 52 53 if (attr->max_entries == 0 || attr->key_size != 0 || 53 54 attr->value_size == 0 || 54 - attr->map_flags & ~QUEUE_STACK_CREATE_FLAG_MASK) 55 + attr->map_flags & ~QUEUE_STACK_CREATE_FLAG_MASK || 56 + !bpf_map_flags_access_ok(attr->map_flags)) 55 57 return -EINVAL; 56 58 57 59 if (attr->value_size > KMALLOC_MAX_SIZE)
+115 -29
kernel/bpf/syscall.c
··· 166 166 kvfree(area); 167 167 } 168 168 169 + static u32 bpf_map_flags_retain_permanent(u32 flags) 170 + { 171 + /* Some map creation flags are not tied to the map object but 172 + * rather to the map fd instead, so they have no meaning upon 173 + * map object inspection since multiple file descriptors with 174 + * different (access) properties can exist here. Thus, given 175 + * this has zero meaning for the map itself, lets clear these 176 + * from here. 177 + */ 178 + return flags & ~(BPF_F_RDONLY | BPF_F_WRONLY); 179 + } 180 + 169 181 void bpf_map_init_from_attr(struct bpf_map *map, union bpf_attr *attr) 170 182 { 171 183 map->map_type = attr->map_type; 172 184 map->key_size = attr->key_size; 173 185 map->value_size = attr->value_size; 174 186 map->max_entries = attr->max_entries; 175 - map->map_flags = attr->map_flags; 187 + map->map_flags = bpf_map_flags_retain_permanent(attr->map_flags); 176 188 map->numa_node = bpf_map_attr_numa_node(attr); 177 189 } 178 190 ··· 355 343 return 0; 356 344 } 357 345 346 + static fmode_t map_get_sys_perms(struct bpf_map *map, struct fd f) 347 + { 348 + fmode_t mode = f.file->f_mode; 349 + 350 + /* Our file permissions may have been overridden by global 351 + * map permissions facing syscall side. 352 + */ 353 + if (READ_ONCE(map->frozen)) 354 + mode &= ~FMODE_CAN_WRITE; 355 + return mode; 356 + } 357 + 358 358 #ifdef CONFIG_PROC_FS 359 359 static void bpf_map_show_fdinfo(struct seq_file *m, struct file *filp) 360 360 { ··· 388 364 "max_entries:\t%u\n" 389 365 "map_flags:\t%#x\n" 390 366 "memlock:\t%llu\n" 391 - "map_id:\t%u\n", 367 + "map_id:\t%u\n" 368 + "frozen:\t%u\n", 392 369 map->map_type, 393 370 map->key_size, 394 371 map->value_size, 395 372 map->max_entries, 396 373 map->map_flags, 397 374 map->pages * 1ULL << PAGE_SHIFT, 398 - map->id); 375 + map->id, 376 + READ_ONCE(map->frozen)); 399 377 400 378 if (owner_prog_type) { 401 379 seq_printf(m, "owner_prog_type:\t%u\n", ··· 474 448 const char *end = src + BPF_OBJ_NAME_LEN; 475 449 476 450 memset(dst, 0, BPF_OBJ_NAME_LEN); 477 - 478 - /* Copy all isalnum() and '_' char */ 451 + /* Copy all isalnum(), '_' and '.' chars. */ 479 452 while (src < end && *src) { 480 - if (!isalnum(*src) && *src != '_') 453 + if (!isalnum(*src) && 454 + *src != '_' && *src != '.') 481 455 return -EINVAL; 482 456 *dst++ = *src++; 483 457 } ··· 504 478 u32 key_size, value_size; 505 479 int ret = 0; 506 480 507 - key_type = btf_type_id_size(btf, &btf_key_id, &key_size); 508 - if (!key_type || key_size != map->key_size) 509 - return -EINVAL; 481 + /* Some maps allow key to be unspecified. */ 482 + if (btf_key_id) { 483 + key_type = btf_type_id_size(btf, &btf_key_id, &key_size); 484 + if (!key_type || key_size != map->key_size) 485 + return -EINVAL; 486 + } else { 487 + key_type = btf_type_by_id(btf, 0); 488 + if (!map->ops->map_check_btf) 489 + return -EINVAL; 490 + } 510 491 511 492 value_type = btf_type_id_size(btf, &btf_value_id, &value_size); 512 493 if (!value_type || value_size != map->value_size) ··· 522 489 map->spin_lock_off = btf_find_spin_lock(btf, value_type); 523 490 524 491 if (map_value_has_spin_lock(map)) { 492 + if (map->map_flags & BPF_F_RDONLY_PROG) 493 + return -EACCES; 525 494 if (map->map_type != BPF_MAP_TYPE_HASH && 526 495 map->map_type != BPF_MAP_TYPE_ARRAY && 527 496 map->map_type != BPF_MAP_TYPE_CGROUP_STORAGE) ··· 580 545 if (attr->btf_key_type_id || attr->btf_value_type_id) { 581 546 struct btf *btf; 582 547 583 - if (!attr->btf_key_type_id || !attr->btf_value_type_id) { 548 + if (!attr->btf_value_type_id) { 584 549 err = -EINVAL; 585 550 goto free_map_nouncharge; 586 551 } ··· 748 713 map = __bpf_map_get(f); 749 714 if (IS_ERR(map)) 750 715 return PTR_ERR(map); 751 - 752 - if (!(f.file->f_mode & FMODE_CAN_READ)) { 716 + if (!(map_get_sys_perms(map, f) & FMODE_CAN_READ)) { 753 717 err = -EPERM; 754 718 goto err_put; 755 719 } ··· 877 843 map = __bpf_map_get(f); 878 844 if (IS_ERR(map)) 879 845 return PTR_ERR(map); 880 - 881 - if (!(f.file->f_mode & FMODE_CAN_WRITE)) { 846 + if (!(map_get_sys_perms(map, f) & FMODE_CAN_WRITE)) { 882 847 err = -EPERM; 883 848 goto err_put; 884 849 } ··· 988 955 map = __bpf_map_get(f); 989 956 if (IS_ERR(map)) 990 957 return PTR_ERR(map); 991 - 992 - if (!(f.file->f_mode & FMODE_CAN_WRITE)) { 958 + if (!(map_get_sys_perms(map, f) & FMODE_CAN_WRITE)) { 993 959 err = -EPERM; 994 960 goto err_put; 995 961 } ··· 1039 1007 map = __bpf_map_get(f); 1040 1008 if (IS_ERR(map)) 1041 1009 return PTR_ERR(map); 1042 - 1043 - if (!(f.file->f_mode & FMODE_CAN_READ)) { 1010 + if (!(map_get_sys_perms(map, f) & FMODE_CAN_READ)) { 1044 1011 err = -EPERM; 1045 1012 goto err_put; 1046 1013 } ··· 1106 1075 map = __bpf_map_get(f); 1107 1076 if (IS_ERR(map)) 1108 1077 return PTR_ERR(map); 1109 - 1110 - if (!(f.file->f_mode & FMODE_CAN_WRITE)) { 1078 + if (!(map_get_sys_perms(map, f) & FMODE_CAN_WRITE)) { 1111 1079 err = -EPERM; 1112 1080 goto err_put; 1113 1081 } ··· 1143 1113 kfree(value); 1144 1114 free_key: 1145 1115 kfree(key); 1116 + err_put: 1117 + fdput(f); 1118 + return err; 1119 + } 1120 + 1121 + #define BPF_MAP_FREEZE_LAST_FIELD map_fd 1122 + 1123 + static int map_freeze(const union bpf_attr *attr) 1124 + { 1125 + int err = 0, ufd = attr->map_fd; 1126 + struct bpf_map *map; 1127 + struct fd f; 1128 + 1129 + if (CHECK_ATTR(BPF_MAP_FREEZE)) 1130 + return -EINVAL; 1131 + 1132 + f = fdget(ufd); 1133 + map = __bpf_map_get(f); 1134 + if (IS_ERR(map)) 1135 + return PTR_ERR(map); 1136 + if (READ_ONCE(map->frozen)) { 1137 + err = -EBUSY; 1138 + goto err_put; 1139 + } 1140 + if (!capable(CAP_SYS_ADMIN)) { 1141 + err = -EPERM; 1142 + goto err_put; 1143 + } 1144 + 1145 + WRITE_ONCE(map->frozen, true); 1146 1146 err_put: 1147 1147 fdput(f); 1148 1148 return err; ··· 1617 1557 /* eBPF programs must be GPL compatible to use GPL-ed functions */ 1618 1558 is_gpl = license_is_gpl_compatible(license); 1619 1559 1620 - if (attr->insn_cnt == 0 || attr->insn_cnt > BPF_MAXINSNS) 1560 + if (attr->insn_cnt == 0 || 1561 + attr->insn_cnt > (capable(CAP_SYS_ADMIN) ? BPF_COMPLEXITY_LIMIT_INSNS : BPF_MAXINSNS)) 1621 1562 return -E2BIG; 1622 1563 if (type != BPF_PROG_TYPE_SOCKET_FILTER && 1623 1564 type != BPF_PROG_TYPE_CGROUP_SKB && ··· 2009 1948 return cgroup_bpf_prog_query(attr, uattr); 2010 1949 } 2011 1950 2012 - #define BPF_PROG_TEST_RUN_LAST_FIELD test.duration 1951 + #define BPF_PROG_TEST_RUN_LAST_FIELD test.ctx_out 2013 1952 2014 1953 static int bpf_prog_test_run(const union bpf_attr *attr, 2015 1954 union bpf_attr __user *uattr) ··· 2020 1959 if (!capable(CAP_SYS_ADMIN)) 2021 1960 return -EPERM; 2022 1961 if (CHECK_ATTR(BPF_PROG_TEST_RUN)) 1962 + return -EINVAL; 1963 + 1964 + if ((attr->test.ctx_size_in && !attr->test.ctx_in) || 1965 + (!attr->test.ctx_size_in && attr->test.ctx_in)) 1966 + return -EINVAL; 1967 + 1968 + if ((attr->test.ctx_size_out && !attr->test.ctx_out) || 1969 + (!attr->test.ctx_size_out && attr->test.ctx_out)) 2023 1970 return -EINVAL; 2024 1971 2025 1972 prog = bpf_prog_get(attr->test.prog_fd); ··· 2140 2071 } 2141 2072 2142 2073 static const struct bpf_map *bpf_map_from_imm(const struct bpf_prog *prog, 2143 - unsigned long addr) 2074 + unsigned long addr, u32 *off, 2075 + u32 *type) 2144 2076 { 2077 + const struct bpf_map *map; 2145 2078 int i; 2146 2079 2147 - for (i = 0; i < prog->aux->used_map_cnt; i++) 2148 - if (prog->aux->used_maps[i] == (void *)addr) 2149 - return prog->aux->used_maps[i]; 2080 + for (i = 0, *off = 0; i < prog->aux->used_map_cnt; i++) { 2081 + map = prog->aux->used_maps[i]; 2082 + if (map == (void *)addr) { 2083 + *type = BPF_PSEUDO_MAP_FD; 2084 + return map; 2085 + } 2086 + if (!map->ops->map_direct_value_meta) 2087 + continue; 2088 + if (!map->ops->map_direct_value_meta(map, addr, off)) { 2089 + *type = BPF_PSEUDO_MAP_VALUE; 2090 + return map; 2091 + } 2092 + } 2093 + 2150 2094 return NULL; 2151 2095 } 2152 2096 ··· 2167 2085 { 2168 2086 const struct bpf_map *map; 2169 2087 struct bpf_insn *insns; 2088 + u32 off, type; 2170 2089 u64 imm; 2171 2090 int i; 2172 2091 ··· 2195 2112 continue; 2196 2113 2197 2114 imm = ((u64)insns[i + 1].imm << 32) | (u32)insns[i].imm; 2198 - map = bpf_map_from_imm(prog, imm); 2115 + map = bpf_map_from_imm(prog, imm, &off, &type); 2199 2116 if (map) { 2200 - insns[i].src_reg = BPF_PSEUDO_MAP_FD; 2117 + insns[i].src_reg = type; 2201 2118 insns[i].imm = map->id; 2202 - insns[i + 1].imm = 0; 2119 + insns[i + 1].imm = off; 2203 2120 continue; 2204 2121 } 2205 2122 } ··· 2788 2705 break; 2789 2706 case BPF_MAP_GET_NEXT_KEY: 2790 2707 err = map_get_next_key(&attr); 2708 + break; 2709 + case BPF_MAP_FREEZE: 2710 + err = map_freeze(&attr); 2791 2711 break; 2792 2712 case BPF_PROG_LOAD: 2793 2713 err = bpf_prog_load(&attr, uattr);
+317 -80
kernel/bpf/verifier.c
··· 176 176 struct bpf_verifier_stack_elem *next; 177 177 }; 178 178 179 - #define BPF_COMPLEXITY_LIMIT_INSNS 131072 180 179 #define BPF_COMPLEXITY_LIMIT_STACK 1024 181 180 #define BPF_COMPLEXITY_LIMIT_STATES 64 182 181 ··· 1091 1092 */ 1092 1093 subprog[env->subprog_cnt].start = insn_cnt; 1093 1094 1094 - if (env->log.level > 1) 1095 + if (env->log.level & BPF_LOG_LEVEL2) 1095 1096 for (i = 0; i < env->subprog_cnt; i++) 1096 1097 verbose(env, "func#%d @%d\n", i, subprog[i].start); 1097 1098 ··· 1138 1139 struct bpf_reg_state *parent) 1139 1140 { 1140 1141 bool writes = parent == state->parent; /* Observe write marks */ 1142 + int cnt = 0; 1141 1143 1142 1144 while (parent) { 1143 1145 /* if read wasn't screened by an earlier write ... */ ··· 1150 1150 parent->var_off.value, parent->off); 1151 1151 return -EFAULT; 1152 1152 } 1153 + if (parent->live & REG_LIVE_READ) 1154 + /* The parentage chain never changes and 1155 + * this parent was already marked as LIVE_READ. 1156 + * There is no need to keep walking the chain again and 1157 + * keep re-marking all parents as LIVE_READ. 1158 + * This case happens when the same register is read 1159 + * multiple times without writes into it in-between. 1160 + */ 1161 + break; 1153 1162 /* ... then we depend on parent's value */ 1154 1163 parent->live |= REG_LIVE_READ; 1155 1164 state = parent; 1156 1165 parent = state->parent; 1157 1166 writes = true; 1167 + cnt++; 1158 1168 } 1169 + 1170 + if (env->longest_mark_read_walk < cnt) 1171 + env->longest_mark_read_walk = cnt; 1159 1172 return 0; 1160 1173 } 1161 1174 ··· 1426 1413 char tn_buf[48]; 1427 1414 1428 1415 tnum_strn(tn_buf, sizeof(tn_buf), reg->var_off); 1429 - verbose(env, "variable stack access var_off=%s off=%d size=%d", 1416 + verbose(env, "variable stack access var_off=%s off=%d size=%d\n", 1430 1417 tn_buf, off, size); 1431 1418 return -EACCES; 1432 1419 } 1433 1420 1434 1421 if (off >= 0 || off < -MAX_BPF_STACK) { 1435 1422 verbose(env, "invalid stack off=%d size=%d\n", off, size); 1423 + return -EACCES; 1424 + } 1425 + 1426 + return 0; 1427 + } 1428 + 1429 + static int check_map_access_type(struct bpf_verifier_env *env, u32 regno, 1430 + int off, int size, enum bpf_access_type type) 1431 + { 1432 + struct bpf_reg_state *regs = cur_regs(env); 1433 + struct bpf_map *map = regs[regno].map_ptr; 1434 + u32 cap = bpf_map_flags_to_cap(map); 1435 + 1436 + if (type == BPF_WRITE && !(cap & BPF_MAP_CAN_WRITE)) { 1437 + verbose(env, "write into map forbidden, value_size=%d off=%d size=%d\n", 1438 + map->value_size, off, size); 1439 + return -EACCES; 1440 + } 1441 + 1442 + if (type == BPF_READ && !(cap & BPF_MAP_CAN_READ)) { 1443 + verbose(env, "read from map forbidden, value_size=%d off=%d size=%d\n", 1444 + map->value_size, off, size); 1436 1445 return -EACCES; 1437 1446 } 1438 1447 ··· 1490 1455 * need to try adding each of min_value and max_value to off 1491 1456 * to make sure our theoretical access will be safe. 1492 1457 */ 1493 - if (env->log.level) 1458 + if (env->log.level & BPF_LOG_LEVEL) 1494 1459 print_verifier_state(env, state); 1495 1460 1496 1461 /* The minimum value is only important with signed ··· 2047 2012 verbose(env, "R%d leaks addr into map\n", value_regno); 2048 2013 return -EACCES; 2049 2014 } 2050 - 2015 + err = check_map_access_type(env, regno, off, size, t); 2016 + if (err) 2017 + return err; 2051 2018 err = check_map_access(env, regno, off, size, false); 2052 2019 if (!err && t == BPF_READ && value_regno >= 0) 2053 2020 mark_reg_unknown(env, regs, value_regno); ··· 2195 2158 BPF_SIZE(insn->code), BPF_WRITE, -1, true); 2196 2159 } 2197 2160 2161 + static int __check_stack_boundary(struct bpf_verifier_env *env, u32 regno, 2162 + int off, int access_size, 2163 + bool zero_size_allowed) 2164 + { 2165 + struct bpf_reg_state *reg = reg_state(env, regno); 2166 + 2167 + if (off >= 0 || off < -MAX_BPF_STACK || off + access_size > 0 || 2168 + access_size < 0 || (access_size == 0 && !zero_size_allowed)) { 2169 + if (tnum_is_const(reg->var_off)) { 2170 + verbose(env, "invalid stack type R%d off=%d access_size=%d\n", 2171 + regno, off, access_size); 2172 + } else { 2173 + char tn_buf[48]; 2174 + 2175 + tnum_strn(tn_buf, sizeof(tn_buf), reg->var_off); 2176 + verbose(env, "invalid stack type R%d var_off=%s access_size=%d\n", 2177 + regno, tn_buf, access_size); 2178 + } 2179 + return -EACCES; 2180 + } 2181 + return 0; 2182 + } 2183 + 2198 2184 /* when register 'regno' is passed into function that will read 'access_size' 2199 2185 * bytes from that pointer, make sure that it's within stack boundary 2200 2186 * and all elements of stack are initialized. ··· 2230 2170 { 2231 2171 struct bpf_reg_state *reg = reg_state(env, regno); 2232 2172 struct bpf_func_state *state = func(env, reg); 2233 - int off, i, slot, spi; 2173 + int err, min_off, max_off, i, slot, spi; 2234 2174 2235 2175 if (reg->type != PTR_TO_STACK) { 2236 2176 /* Allow zero-byte read from NULL, regardless of pointer type */ ··· 2244 2184 return -EACCES; 2245 2185 } 2246 2186 2247 - /* Only allow fixed-offset stack reads */ 2248 - if (!tnum_is_const(reg->var_off)) { 2249 - char tn_buf[48]; 2187 + if (tnum_is_const(reg->var_off)) { 2188 + min_off = max_off = reg->var_off.value + reg->off; 2189 + err = __check_stack_boundary(env, regno, min_off, access_size, 2190 + zero_size_allowed); 2191 + if (err) 2192 + return err; 2193 + } else { 2194 + /* Variable offset is prohibited for unprivileged mode for 2195 + * simplicity since it requires corresponding support in 2196 + * Spectre masking for stack ALU. 2197 + * See also retrieve_ptr_limit(). 2198 + */ 2199 + if (!env->allow_ptr_leaks) { 2200 + char tn_buf[48]; 2250 2201 2251 - tnum_strn(tn_buf, sizeof(tn_buf), reg->var_off); 2252 - verbose(env, "invalid variable stack read R%d var_off=%s\n", 2253 - regno, tn_buf); 2254 - return -EACCES; 2255 - } 2256 - off = reg->off + reg->var_off.value; 2257 - if (off >= 0 || off < -MAX_BPF_STACK || off + access_size > 0 || 2258 - access_size < 0 || (access_size == 0 && !zero_size_allowed)) { 2259 - verbose(env, "invalid stack type R%d off=%d access_size=%d\n", 2260 - regno, off, access_size); 2261 - return -EACCES; 2202 + tnum_strn(tn_buf, sizeof(tn_buf), reg->var_off); 2203 + verbose(env, "R%d indirect variable offset stack access prohibited for !root, var_off=%s\n", 2204 + regno, tn_buf); 2205 + return -EACCES; 2206 + } 2207 + /* Only initialized buffer on stack is allowed to be accessed 2208 + * with variable offset. With uninitialized buffer it's hard to 2209 + * guarantee that whole memory is marked as initialized on 2210 + * helper return since specific bounds are unknown what may 2211 + * cause uninitialized stack leaking. 2212 + */ 2213 + if (meta && meta->raw_mode) 2214 + meta = NULL; 2215 + 2216 + if (reg->smax_value >= BPF_MAX_VAR_OFF || 2217 + reg->smax_value <= -BPF_MAX_VAR_OFF) { 2218 + verbose(env, "R%d unbounded indirect variable offset stack access\n", 2219 + regno); 2220 + return -EACCES; 2221 + } 2222 + min_off = reg->smin_value + reg->off; 2223 + max_off = reg->smax_value + reg->off; 2224 + err = __check_stack_boundary(env, regno, min_off, access_size, 2225 + zero_size_allowed); 2226 + if (err) { 2227 + verbose(env, "R%d min value is outside of stack bound\n", 2228 + regno); 2229 + return err; 2230 + } 2231 + err = __check_stack_boundary(env, regno, max_off, access_size, 2232 + zero_size_allowed); 2233 + if (err) { 2234 + verbose(env, "R%d max value is outside of stack bound\n", 2235 + regno); 2236 + return err; 2237 + } 2262 2238 } 2263 2239 2264 2240 if (meta && meta->raw_mode) { ··· 2303 2207 return 0; 2304 2208 } 2305 2209 2306 - for (i = 0; i < access_size; i++) { 2210 + for (i = min_off; i < max_off + access_size; i++) { 2307 2211 u8 *stype; 2308 2212 2309 - slot = -(off + i) - 1; 2213 + slot = -i - 1; 2310 2214 spi = slot / BPF_REG_SIZE; 2311 2215 if (state->allocated_stack <= slot) 2312 2216 goto err; ··· 2319 2223 goto mark; 2320 2224 } 2321 2225 err: 2322 - verbose(env, "invalid indirect read from stack off %d+%d size %d\n", 2323 - off, i, access_size); 2226 + if (tnum_is_const(reg->var_off)) { 2227 + verbose(env, "invalid indirect read from stack off %d+%d size %d\n", 2228 + min_off, i - min_off, access_size); 2229 + } else { 2230 + char tn_buf[48]; 2231 + 2232 + tnum_strn(tn_buf, sizeof(tn_buf), reg->var_off); 2233 + verbose(env, "invalid indirect read from stack var_off %s+%d size %d\n", 2234 + tn_buf, i - min_off, access_size); 2235 + } 2324 2236 return -EACCES; 2325 2237 mark: 2326 2238 /* reading any byte out of 8-byte 'spill_slot' will cause ··· 2337 2233 mark_reg_read(env, &state->stack[spi].spilled_ptr, 2338 2234 state->stack[spi].spilled_ptr.parent); 2339 2235 } 2340 - return update_stack_depth(env, state, off); 2236 + return update_stack_depth(env, state, min_off); 2341 2237 } 2342 2238 2343 2239 static int check_helper_mem_access(struct bpf_verifier_env *env, int regno, ··· 2352 2248 return check_packet_access(env, regno, reg->off, access_size, 2353 2249 zero_size_allowed); 2354 2250 case PTR_TO_MAP_VALUE: 2251 + if (check_map_access_type(env, regno, reg->off, access_size, 2252 + meta && meta->raw_mode ? BPF_WRITE : 2253 + BPF_READ)) 2254 + return -EACCES; 2355 2255 return check_map_access(env, regno, reg->off, access_size, 2356 2256 zero_size_allowed); 2357 2257 default: /* scalar_value|ptr_to_stack or invalid ptr */ ··· 3014 2906 /* and go analyze first insn of the callee */ 3015 2907 *insn_idx = target_insn; 3016 2908 3017 - if (env->log.level) { 2909 + if (env->log.level & BPF_LOG_LEVEL) { 3018 2910 verbose(env, "caller:\n"); 3019 2911 print_verifier_state(env, caller); 3020 2912 verbose(env, "callee:\n"); ··· 3054 2946 return err; 3055 2947 3056 2948 *insn_idx = callee->callsite + 1; 3057 - if (env->log.level) { 2949 + if (env->log.level & BPF_LOG_LEVEL) { 3058 2950 verbose(env, "returning from callee:\n"); 3059 2951 print_verifier_state(env, callee); 3060 2952 verbose(env, "to caller at %d:\n", *insn_idx); ··· 3088 2980 int func_id, int insn_idx) 3089 2981 { 3090 2982 struct bpf_insn_aux_data *aux = &env->insn_aux_data[insn_idx]; 2983 + struct bpf_map *map = meta->map_ptr; 3091 2984 3092 2985 if (func_id != BPF_FUNC_tail_call && 3093 2986 func_id != BPF_FUNC_map_lookup_elem && ··· 3099 2990 func_id != BPF_FUNC_map_peek_elem) 3100 2991 return 0; 3101 2992 3102 - if (meta->map_ptr == NULL) { 2993 + if (map == NULL) { 3103 2994 verbose(env, "kernel subsystem misconfigured verifier\n"); 3104 2995 return -EINVAL; 2996 + } 2997 + 2998 + /* In case of read-only, some additional restrictions 2999 + * need to be applied in order to prevent altering the 3000 + * state of the map from program side. 3001 + */ 3002 + if ((map->map_flags & BPF_F_RDONLY_PROG) && 3003 + (func_id == BPF_FUNC_map_delete_elem || 3004 + func_id == BPF_FUNC_map_update_elem || 3005 + func_id == BPF_FUNC_map_push_elem || 3006 + func_id == BPF_FUNC_map_pop_elem)) { 3007 + verbose(env, "write into map forbidden\n"); 3008 + return -EACCES; 3105 3009 } 3106 3010 3107 3011 if (!BPF_MAP_PTR(aux->map_state)) ··· 3407 3285 3408 3286 switch (ptr_reg->type) { 3409 3287 case PTR_TO_STACK: 3288 + /* Indirect variable offset stack access is prohibited in 3289 + * unprivileged mode so it's not handled here. 3290 + */ 3410 3291 off = ptr_reg->off + ptr_reg->var_off.value; 3411 3292 if (mask_to_left) 3412 3293 *ptr_limit = MAX_BPF_STACK + off; ··· 5094 4969 insn->dst_reg); 5095 4970 return -EACCES; 5096 4971 } 5097 - if (env->log.level) 4972 + if (env->log.level & BPF_LOG_LEVEL) 5098 4973 print_verifier_state(env, this_branch->frame[this_branch->curframe]); 5099 4974 return 0; 5100 - } 5101 - 5102 - /* return the map pointer stored inside BPF_LD_IMM64 instruction */ 5103 - static struct bpf_map *ld_imm64_to_map_ptr(struct bpf_insn *insn) 5104 - { 5105 - u64 imm64 = ((u64) (u32) insn[0].imm) | ((u64) (u32) insn[1].imm) << 32; 5106 - 5107 - return (struct bpf_map *) (unsigned long) imm64; 5108 4975 } 5109 4976 5110 4977 /* verify BPF_LD_IMM64 instruction */ 5111 4978 static int check_ld_imm(struct bpf_verifier_env *env, struct bpf_insn *insn) 5112 4979 { 4980 + struct bpf_insn_aux_data *aux = cur_aux(env); 5113 4981 struct bpf_reg_state *regs = cur_regs(env); 4982 + struct bpf_map *map; 5114 4983 int err; 5115 4984 5116 4985 if (BPF_SIZE(insn->code) != BPF_DW) { ··· 5128 5009 return 0; 5129 5010 } 5130 5011 5131 - /* replace_map_fd_with_map_ptr() should have caught bad ld_imm64 */ 5132 - BUG_ON(insn->src_reg != BPF_PSEUDO_MAP_FD); 5012 + map = env->used_maps[aux->map_index]; 5013 + mark_reg_known_zero(env, regs, insn->dst_reg); 5014 + regs[insn->dst_reg].map_ptr = map; 5133 5015 5134 - regs[insn->dst_reg].type = CONST_PTR_TO_MAP; 5135 - regs[insn->dst_reg].map_ptr = ld_imm64_to_map_ptr(insn); 5016 + if (insn->src_reg == BPF_PSEUDO_MAP_VALUE) { 5017 + regs[insn->dst_reg].type = PTR_TO_MAP_VALUE; 5018 + regs[insn->dst_reg].off = aux->map_off; 5019 + if (map_value_has_spin_lock(map)) 5020 + regs[insn->dst_reg].id = ++env->id_gen; 5021 + } else if (insn->src_reg == BPF_PSEUDO_MAP_FD) { 5022 + regs[insn->dst_reg].type = CONST_PTR_TO_MAP; 5023 + } else { 5024 + verbose(env, "bpf verifier is misconfigured\n"); 5025 + return -EINVAL; 5026 + } 5027 + 5136 5028 return 0; 5137 5029 } 5138 5030 ··· 5397 5267 int ret = 0; 5398 5268 int i, t; 5399 5269 5400 - insn_state = kcalloc(insn_cnt, sizeof(int), GFP_KERNEL); 5270 + insn_state = kvcalloc(insn_cnt, sizeof(int), GFP_KERNEL); 5401 5271 if (!insn_state) 5402 5272 return -ENOMEM; 5403 5273 5404 - insn_stack = kcalloc(insn_cnt, sizeof(int), GFP_KERNEL); 5274 + insn_stack = kvcalloc(insn_cnt, sizeof(int), GFP_KERNEL); 5405 5275 if (!insn_stack) { 5406 - kfree(insn_state); 5276 + kvfree(insn_state); 5407 5277 return -ENOMEM; 5408 5278 } 5409 5279 ··· 5501 5371 ret = 0; /* cfg looks good */ 5502 5372 5503 5373 err_free: 5504 - kfree(insn_state); 5505 - kfree(insn_stack); 5374 + kvfree(insn_state); 5375 + kvfree(insn_stack); 5506 5376 return ret; 5507 5377 } 5508 5378 ··· 6245 6115 static int is_state_visited(struct bpf_verifier_env *env, int insn_idx) 6246 6116 { 6247 6117 struct bpf_verifier_state_list *new_sl; 6248 - struct bpf_verifier_state_list *sl; 6118 + struct bpf_verifier_state_list *sl, **pprev; 6249 6119 struct bpf_verifier_state *cur = env->cur_state, *new; 6250 6120 int i, j, err, states_cnt = 0; 6251 6121 6252 - sl = env->explored_states[insn_idx]; 6122 + pprev = &env->explored_states[insn_idx]; 6123 + sl = *pprev; 6124 + 6253 6125 if (!sl) 6254 6126 /* this 'insn_idx' instruction wasn't marked, so we will not 6255 6127 * be doing state search here ··· 6262 6130 6263 6131 while (sl != STATE_LIST_MARK) { 6264 6132 if (states_equal(env, &sl->state, cur)) { 6133 + sl->hit_cnt++; 6265 6134 /* reached equivalent register/stack state, 6266 6135 * prune the search. 6267 6136 * Registers read by the continuation are read by us. ··· 6278 6145 return err; 6279 6146 return 1; 6280 6147 } 6281 - sl = sl->next; 6282 6148 states_cnt++; 6149 + sl->miss_cnt++; 6150 + /* heuristic to determine whether this state is beneficial 6151 + * to keep checking from state equivalence point of view. 6152 + * Higher numbers increase max_states_per_insn and verification time, 6153 + * but do not meaningfully decrease insn_processed. 6154 + */ 6155 + if (sl->miss_cnt > sl->hit_cnt * 3 + 3) { 6156 + /* the state is unlikely to be useful. Remove it to 6157 + * speed up verification 6158 + */ 6159 + *pprev = sl->next; 6160 + if (sl->state.frame[0]->regs[0].live & REG_LIVE_DONE) { 6161 + free_verifier_state(&sl->state, false); 6162 + kfree(sl); 6163 + env->peak_states--; 6164 + } else { 6165 + /* cannot free this state, since parentage chain may 6166 + * walk it later. Add it for free_list instead to 6167 + * be freed at the end of verification 6168 + */ 6169 + sl->next = env->free_list; 6170 + env->free_list = sl; 6171 + } 6172 + sl = *pprev; 6173 + continue; 6174 + } 6175 + pprev = &sl->next; 6176 + sl = *pprev; 6283 6177 } 6178 + 6179 + if (env->max_states_per_insn < states_cnt) 6180 + env->max_states_per_insn = states_cnt; 6284 6181 6285 6182 if (!env->allow_ptr_leaks && states_cnt > BPF_COMPLEXITY_LIMIT_STATES) 6286 6183 return 0; ··· 6325 6162 new_sl = kzalloc(sizeof(struct bpf_verifier_state_list), GFP_KERNEL); 6326 6163 if (!new_sl) 6327 6164 return -ENOMEM; 6165 + env->total_states++; 6166 + env->peak_states++; 6328 6167 6329 6168 /* add new state to the head of linked list */ 6330 6169 new = &new_sl->state; ··· 6411 6246 struct bpf_verifier_state *state; 6412 6247 struct bpf_insn *insns = env->prog->insnsi; 6413 6248 struct bpf_reg_state *regs; 6414 - int insn_cnt = env->prog->len, i; 6415 - int insn_processed = 0; 6249 + int insn_cnt = env->prog->len; 6416 6250 bool do_print_state = false; 6417 6251 6418 6252 env->prev_linfo = NULL; ··· 6446 6282 insn = &insns[env->insn_idx]; 6447 6283 class = BPF_CLASS(insn->code); 6448 6284 6449 - if (++insn_processed > BPF_COMPLEXITY_LIMIT_INSNS) { 6285 + if (++env->insn_processed > BPF_COMPLEXITY_LIMIT_INSNS) { 6450 6286 verbose(env, 6451 6287 "BPF program is too large. Processed %d insn\n", 6452 - insn_processed); 6288 + env->insn_processed); 6453 6289 return -E2BIG; 6454 6290 } 6455 6291 ··· 6458 6294 return err; 6459 6295 if (err == 1) { 6460 6296 /* found equivalent state, can prune the search */ 6461 - if (env->log.level) { 6297 + if (env->log.level & BPF_LOG_LEVEL) { 6462 6298 if (do_print_state) 6463 6299 verbose(env, "\nfrom %d to %d%s: safe\n", 6464 6300 env->prev_insn_idx, env->insn_idx, ··· 6476 6312 if (need_resched()) 6477 6313 cond_resched(); 6478 6314 6479 - if (env->log.level > 1 || (env->log.level && do_print_state)) { 6480 - if (env->log.level > 1) 6315 + if (env->log.level & BPF_LOG_LEVEL2 || 6316 + (env->log.level & BPF_LOG_LEVEL && do_print_state)) { 6317 + if (env->log.level & BPF_LOG_LEVEL2) 6481 6318 verbose(env, "%d:", env->insn_idx); 6482 6319 else 6483 6320 verbose(env, "\nfrom %d to %d%s:", ··· 6489 6324 do_print_state = false; 6490 6325 } 6491 6326 6492 - if (env->log.level) { 6327 + if (env->log.level & BPF_LOG_LEVEL) { 6493 6328 const struct bpf_insn_cbs cbs = { 6494 6329 .cb_print = verbose, 6495 6330 .private_data = env, ··· 6754 6589 env->insn_idx++; 6755 6590 } 6756 6591 6757 - verbose(env, "processed %d insns (limit %d), stack depth ", 6758 - insn_processed, BPF_COMPLEXITY_LIMIT_INSNS); 6759 - for (i = 0; i < env->subprog_cnt; i++) { 6760 - u32 depth = env->subprog_info[i].stack_depth; 6761 - 6762 - verbose(env, "%d", depth); 6763 - if (i + 1 < env->subprog_cnt) 6764 - verbose(env, "+"); 6765 - } 6766 - verbose(env, "\n"); 6767 6592 env->prog->aux->stack_depth = env->subprog_info[0].stack_depth; 6768 6593 return 0; 6769 6594 } ··· 6851 6696 } 6852 6697 6853 6698 if (insn[0].code == (BPF_LD | BPF_IMM | BPF_DW)) { 6699 + struct bpf_insn_aux_data *aux; 6854 6700 struct bpf_map *map; 6855 6701 struct fd f; 6702 + u64 addr; 6856 6703 6857 6704 if (i == insn_cnt - 1 || insn[1].code != 0 || 6858 6705 insn[1].dst_reg != 0 || insn[1].src_reg != 0 || ··· 6863 6706 return -EINVAL; 6864 6707 } 6865 6708 6866 - if (insn->src_reg == 0) 6709 + if (insn[0].src_reg == 0) 6867 6710 /* valid generic load 64-bit imm */ 6868 6711 goto next_insn; 6869 6712 6870 - if (insn[0].src_reg != BPF_PSEUDO_MAP_FD || 6871 - insn[1].imm != 0) { 6872 - verbose(env, "unrecognized bpf_ld_imm64 insn\n"); 6713 + /* In final convert_pseudo_ld_imm64() step, this is 6714 + * converted into regular 64-bit imm load insn. 6715 + */ 6716 + if ((insn[0].src_reg != BPF_PSEUDO_MAP_FD && 6717 + insn[0].src_reg != BPF_PSEUDO_MAP_VALUE) || 6718 + (insn[0].src_reg == BPF_PSEUDO_MAP_FD && 6719 + insn[1].imm != 0)) { 6720 + verbose(env, 6721 + "unrecognized bpf_ld_imm64 insn\n"); 6873 6722 return -EINVAL; 6874 6723 } 6875 6724 ··· 6893 6730 return err; 6894 6731 } 6895 6732 6896 - /* store map pointer inside BPF_LD_IMM64 instruction */ 6897 - insn[0].imm = (u32) (unsigned long) map; 6898 - insn[1].imm = ((u64) (unsigned long) map) >> 32; 6733 + aux = &env->insn_aux_data[i]; 6734 + if (insn->src_reg == BPF_PSEUDO_MAP_FD) { 6735 + addr = (unsigned long)map; 6736 + } else { 6737 + u32 off = insn[1].imm; 6738 + 6739 + if (off >= BPF_MAX_VAR_OFF) { 6740 + verbose(env, "direct value offset of %u is not allowed\n", off); 6741 + fdput(f); 6742 + return -EINVAL; 6743 + } 6744 + 6745 + if (!map->ops->map_direct_value_addr) { 6746 + verbose(env, "no direct value access support for this map type\n"); 6747 + fdput(f); 6748 + return -EINVAL; 6749 + } 6750 + 6751 + err = map->ops->map_direct_value_addr(map, &addr, off); 6752 + if (err) { 6753 + verbose(env, "invalid access to map value pointer, value_size=%u off=%u\n", 6754 + map->value_size, off); 6755 + fdput(f); 6756 + return err; 6757 + } 6758 + 6759 + aux->map_off = off; 6760 + addr += off; 6761 + } 6762 + 6763 + insn[0].imm = (u32)addr; 6764 + insn[1].imm = addr >> 32; 6899 6765 6900 6766 /* check whether we recorded this map already */ 6901 - for (j = 0; j < env->used_map_cnt; j++) 6767 + for (j = 0; j < env->used_map_cnt; j++) { 6902 6768 if (env->used_maps[j] == map) { 6769 + aux->map_index = j; 6903 6770 fdput(f); 6904 6771 goto next_insn; 6905 6772 } 6773 + } 6906 6774 6907 6775 if (env->used_map_cnt >= MAX_USED_MAPS) { 6908 6776 fdput(f); ··· 6950 6756 fdput(f); 6951 6757 return PTR_ERR(map); 6952 6758 } 6759 + 6760 + aux->map_index = env->used_map_cnt; 6953 6761 env->used_maps[env->used_map_cnt++] = map; 6954 6762 6955 6763 if (bpf_map_is_cgroup_storage(map) && ··· 7057 6861 struct bpf_prog *new_prog; 7058 6862 7059 6863 new_prog = bpf_patch_insn_single(env->prog, off, patch, len); 7060 - if (!new_prog) 6864 + if (IS_ERR(new_prog)) { 6865 + if (PTR_ERR(new_prog) == -ERANGE) 6866 + verbose(env, 6867 + "insn %d cannot be patched due to 16-bit range\n", 6868 + env->insn_aux_data[off].orig_idx); 7061 6869 return NULL; 6870 + } 7062 6871 if (adjust_insn_aux_data(env, new_prog->len, off, len)) 7063 6872 return NULL; 7064 6873 adjust_subprog_starts(env, off, len); ··· 8005 7804 struct bpf_verifier_state_list *sl, *sln; 8006 7805 int i; 8007 7806 7807 + sl = env->free_list; 7808 + while (sl) { 7809 + sln = sl->next; 7810 + free_verifier_state(&sl->state, false); 7811 + kfree(sl); 7812 + sl = sln; 7813 + } 7814 + 8008 7815 if (!env->explored_states) 8009 7816 return; 8010 7817 ··· 8028 7819 } 8029 7820 } 8030 7821 8031 - kfree(env->explored_states); 7822 + kvfree(env->explored_states); 7823 + } 7824 + 7825 + static void print_verification_stats(struct bpf_verifier_env *env) 7826 + { 7827 + int i; 7828 + 7829 + if (env->log.level & BPF_LOG_STATS) { 7830 + verbose(env, "verification time %lld usec\n", 7831 + div_u64(env->verification_time, 1000)); 7832 + verbose(env, "stack depth "); 7833 + for (i = 0; i < env->subprog_cnt; i++) { 7834 + u32 depth = env->subprog_info[i].stack_depth; 7835 + 7836 + verbose(env, "%d", depth); 7837 + if (i + 1 < env->subprog_cnt) 7838 + verbose(env, "+"); 7839 + } 7840 + verbose(env, "\n"); 7841 + } 7842 + verbose(env, "processed %d insns (limit %d) max_states_per_insn %d " 7843 + "total_states %d peak_states %d mark_read %d\n", 7844 + env->insn_processed, BPF_COMPLEXITY_LIMIT_INSNS, 7845 + env->max_states_per_insn, env->total_states, 7846 + env->peak_states, env->longest_mark_read_walk); 8032 7847 } 8033 7848 8034 7849 int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, 8035 7850 union bpf_attr __user *uattr) 8036 7851 { 7852 + u64 start_time = ktime_get_ns(); 8037 7853 struct bpf_verifier_env *env; 8038 7854 struct bpf_verifier_log *log; 8039 7855 int i, len, ret = -EINVAL; ··· 8100 7866 8101 7867 ret = -EINVAL; 8102 7868 /* log attributes have to be sane */ 8103 - if (log->len_total < 128 || log->len_total > UINT_MAX >> 8 || 8104 - !log->level || !log->ubuf) 7869 + if (log->len_total < 128 || log->len_total > UINT_MAX >> 2 || 7870 + !log->level || !log->ubuf || log->level & ~BPF_LOG_MASK) 8105 7871 goto err_unlock; 8106 7872 } 8107 7873 ··· 8124 7890 goto skip_full_check; 8125 7891 } 8126 7892 8127 - env->explored_states = kcalloc(env->prog->len, 7893 + env->explored_states = kvcalloc(env->prog->len, 8128 7894 sizeof(struct bpf_verifier_state_list *), 8129 7895 GFP_USER); 8130 7896 ret = -ENOMEM; ··· 8181 7947 8182 7948 if (ret == 0) 8183 7949 ret = fixup_call_args(env); 7950 + 7951 + env->verification_time = ktime_get_ns() - start_time; 7952 + print_verification_stats(env); 8184 7953 8185 7954 if (log->level && bpf_verifier_log_full(log)) 8186 7955 ret = -ENOSPC;
+8
lib/Kconfig.debug
··· 219 219 But it significantly improves the success of resolving 220 220 variables in gdb on optimized code. 221 221 222 + config DEBUG_INFO_BTF 223 + bool "Generate BTF typeinfo" 224 + depends on DEBUG_INFO 225 + help 226 + Generate deduplicated BTF type information from DWARF debug info. 227 + Turning this on expects presence of pahole tool, which will convert 228 + DWARF type info into equivalent deduplicated BTF type info. 229 + 222 230 config GDB_SCRIPTS 223 231 bool "Provide GDB scripts for kernel debugging" 224 232 depends on DEBUG_INFO
+1 -1
net/bpf/Makefile
··· 1 - obj-y := test_run.o 1 + obj-$(CONFIG_BPF_SYSCALL) := test_run.o
+141 -8
net/bpf/test_run.c
··· 123 123 return data; 124 124 } 125 125 126 + static void *bpf_ctx_init(const union bpf_attr *kattr, u32 max_size) 127 + { 128 + void __user *data_in = u64_to_user_ptr(kattr->test.ctx_in); 129 + void __user *data_out = u64_to_user_ptr(kattr->test.ctx_out); 130 + u32 size = kattr->test.ctx_size_in; 131 + void *data; 132 + int err; 133 + 134 + if (!data_in && !data_out) 135 + return NULL; 136 + 137 + data = kzalloc(max_size, GFP_USER); 138 + if (!data) 139 + return ERR_PTR(-ENOMEM); 140 + 141 + if (data_in) { 142 + err = bpf_check_uarg_tail_zero(data_in, max_size, size); 143 + if (err) { 144 + kfree(data); 145 + return ERR_PTR(err); 146 + } 147 + 148 + size = min_t(u32, max_size, size); 149 + if (copy_from_user(data, data_in, size)) { 150 + kfree(data); 151 + return ERR_PTR(-EFAULT); 152 + } 153 + } 154 + return data; 155 + } 156 + 157 + static int bpf_ctx_finish(const union bpf_attr *kattr, 158 + union bpf_attr __user *uattr, const void *data, 159 + u32 size) 160 + { 161 + void __user *data_out = u64_to_user_ptr(kattr->test.ctx_out); 162 + int err = -EFAULT; 163 + u32 copy_size = size; 164 + 165 + if (!data || !data_out) 166 + return 0; 167 + 168 + if (copy_size > kattr->test.ctx_size_out) { 169 + copy_size = kattr->test.ctx_size_out; 170 + err = -ENOSPC; 171 + } 172 + 173 + if (copy_to_user(data_out, data, copy_size)) 174 + goto out; 175 + if (copy_to_user(&uattr->test.ctx_size_out, &size, sizeof(size))) 176 + goto out; 177 + if (err != -ENOSPC) 178 + err = 0; 179 + out: 180 + return err; 181 + } 182 + 183 + /** 184 + * range_is_zero - test whether buffer is initialized 185 + * @buf: buffer to check 186 + * @from: check from this position 187 + * @to: check up until (excluding) this position 188 + * 189 + * This function returns true if the there is a non-zero byte 190 + * in the buf in the range [from,to). 191 + */ 192 + static inline bool range_is_zero(void *buf, size_t from, size_t to) 193 + { 194 + return !memchr_inv((u8 *)buf + from, 0, to - from); 195 + } 196 + 197 + static int convert___skb_to_skb(struct sk_buff *skb, struct __sk_buff *__skb) 198 + { 199 + struct qdisc_skb_cb *cb = (struct qdisc_skb_cb *)skb->cb; 200 + 201 + if (!__skb) 202 + return 0; 203 + 204 + /* make sure the fields we don't use are zeroed */ 205 + if (!range_is_zero(__skb, 0, offsetof(struct __sk_buff, priority))) 206 + return -EINVAL; 207 + 208 + /* priority is allowed */ 209 + 210 + if (!range_is_zero(__skb, offsetof(struct __sk_buff, priority) + 211 + FIELD_SIZEOF(struct __sk_buff, priority), 212 + offsetof(struct __sk_buff, cb))) 213 + return -EINVAL; 214 + 215 + /* cb is allowed */ 216 + 217 + if (!range_is_zero(__skb, offsetof(struct __sk_buff, cb) + 218 + FIELD_SIZEOF(struct __sk_buff, cb), 219 + sizeof(struct __sk_buff))) 220 + return -EINVAL; 221 + 222 + skb->priority = __skb->priority; 223 + memcpy(&cb->data, __skb->cb, QDISC_CB_PRIV_LEN); 224 + 225 + return 0; 226 + } 227 + 228 + static void convert_skb_to___skb(struct sk_buff *skb, struct __sk_buff *__skb) 229 + { 230 + struct qdisc_skb_cb *cb = (struct qdisc_skb_cb *)skb->cb; 231 + 232 + if (!__skb) 233 + return; 234 + 235 + __skb->priority = skb->priority; 236 + memcpy(__skb->cb, &cb->data, QDISC_CB_PRIV_LEN); 237 + } 238 + 126 239 int bpf_prog_test_run_skb(struct bpf_prog *prog, const union bpf_attr *kattr, 127 240 union bpf_attr __user *uattr) 128 241 { 129 242 bool is_l2 = false, is_direct_pkt_access = false; 130 243 u32 size = kattr->test.data_size_in; 131 244 u32 repeat = kattr->test.repeat; 245 + struct __sk_buff *ctx = NULL; 132 246 u32 retval, duration; 133 247 int hh_len = ETH_HLEN; 134 248 struct sk_buff *skb; ··· 254 140 SKB_DATA_ALIGN(sizeof(struct skb_shared_info))); 255 141 if (IS_ERR(data)) 256 142 return PTR_ERR(data); 143 + 144 + ctx = bpf_ctx_init(kattr, sizeof(struct __sk_buff)); 145 + if (IS_ERR(ctx)) { 146 + kfree(data); 147 + return PTR_ERR(ctx); 148 + } 257 149 258 150 switch (prog->type) { 259 151 case BPF_PROG_TYPE_SCHED_CLS: ··· 278 158 sk = kzalloc(sizeof(struct sock), GFP_USER); 279 159 if (!sk) { 280 160 kfree(data); 161 + kfree(ctx); 281 162 return -ENOMEM; 282 163 } 283 164 sock_net_set(sk, current->nsproxy->net_ns); ··· 287 166 skb = build_skb(data, 0); 288 167 if (!skb) { 289 168 kfree(data); 169 + kfree(ctx); 290 170 kfree(sk); 291 171 return -ENOMEM; 292 172 } ··· 302 180 __skb_push(skb, hh_len); 303 181 if (is_direct_pkt_access) 304 182 bpf_compute_data_pointers(skb); 183 + ret = convert___skb_to_skb(skb, ctx); 184 + if (ret) 185 + goto out; 305 186 ret = bpf_test_run(prog, skb, repeat, &retval, &duration); 306 - if (ret) { 307 - kfree_skb(skb); 308 - kfree(sk); 309 - return ret; 310 - } 187 + if (ret) 188 + goto out; 311 189 if (!is_l2) { 312 190 if (skb_headroom(skb) < hh_len) { 313 191 int nhead = HH_DATA_ALIGN(hh_len - skb_headroom(skb)); 314 192 315 193 if (pskb_expand_head(skb, nhead, 0, GFP_USER)) { 316 - kfree_skb(skb); 317 - kfree(sk); 318 - return -ENOMEM; 194 + ret = -ENOMEM; 195 + goto out; 319 196 } 320 197 } 321 198 memset(__skb_push(skb, hh_len), 0, hh_len); 322 199 } 200 + convert_skb_to___skb(skb, ctx); 323 201 324 202 size = skb->len; 325 203 /* bpf program can never convert linear skb to non-linear */ 326 204 if (WARN_ON_ONCE(skb_is_nonlinear(skb))) 327 205 size = skb_headlen(skb); 328 206 ret = bpf_test_finish(kattr, uattr, skb->data, size, retval, duration); 207 + if (!ret) 208 + ret = bpf_ctx_finish(kattr, uattr, ctx, 209 + sizeof(struct __sk_buff)); 210 + out: 329 211 kfree_skb(skb); 330 212 kfree(sk); 213 + kfree(ctx); 331 214 return ret; 332 215 } 333 216 ··· 346 219 u32 retval, duration; 347 220 void *data; 348 221 int ret; 222 + 223 + if (kattr->test.ctx_in || kattr->test.ctx_out) 224 + return -EINVAL; 349 225 350 226 data = bpf_test_init(kattr, size, XDP_PACKET_HEADROOM + NET_IP_ALIGN, 0); 351 227 if (IS_ERR(data)) ··· 391 261 u32 i; 392 262 393 263 if (prog->type != BPF_PROG_TYPE_FLOW_DISSECTOR) 264 + return -EINVAL; 265 + 266 + if (kattr->test.ctx_in || kattr->test.ctx_out) 394 267 return -EINVAL; 395 268 396 269 data = bpf_test_init(kattr, size, NET_SKB_PAD + NET_IP_ALIGN,
+8 -4
net/core/filter.c
··· 2970 2970 #define BPF_F_ADJ_ROOM_MASK (BPF_F_ADJ_ROOM_FIXED_GSO | \ 2971 2971 BPF_F_ADJ_ROOM_ENCAP_L3_MASK | \ 2972 2972 BPF_F_ADJ_ROOM_ENCAP_L4_GRE | \ 2973 - BPF_F_ADJ_ROOM_ENCAP_L4_UDP) 2973 + BPF_F_ADJ_ROOM_ENCAP_L4_UDP | \ 2974 + BPF_F_ADJ_ROOM_ENCAP_L2( \ 2975 + BPF_ADJ_ROOM_ENCAP_L2_MASK)) 2974 2976 2975 2977 static int bpf_skb_net_grow(struct sk_buff *skb, u32 off, u32 len_diff, 2976 2978 u64 flags) 2977 2979 { 2980 + u8 inner_mac_len = flags >> BPF_ADJ_ROOM_ENCAP_L2_SHIFT; 2978 2981 bool encap = flags & BPF_F_ADJ_ROOM_ENCAP_L3_MASK; 2979 2982 u16 mac_len = 0, inner_net = 0, inner_trans = 0; 2980 2983 unsigned int gso_type = SKB_GSO_DODGY; ··· 3012 3009 3013 3010 mac_len = skb->network_header - skb->mac_header; 3014 3011 inner_net = skb->network_header; 3012 + if (inner_mac_len > len_diff) 3013 + return -EINVAL; 3015 3014 inner_trans = skb->transport_header; 3016 3015 } 3017 3016 ··· 3022 3017 return ret; 3023 3018 3024 3019 if (encap) { 3025 - /* inner mac == inner_net on l3 encap */ 3026 - skb->inner_mac_header = inner_net; 3020 + skb->inner_mac_header = inner_net - inner_mac_len; 3027 3021 skb->inner_network_header = inner_net; 3028 3022 skb->inner_transport_header = inner_trans; 3029 3023 skb_set_inner_protocol(skb, skb->protocol); ··· 3036 3032 gso_type |= SKB_GSO_GRE; 3037 3033 else if (flags & BPF_F_ADJ_ROOM_ENCAP_L3_IPV6) 3038 3034 gso_type |= SKB_GSO_IPXIP6; 3039 - else 3035 + else if (flags & BPF_F_ADJ_ROOM_ENCAP_L3_IPV4) 3040 3036 gso_type |= SKB_GSO_IPXIP4; 3041 3037 3042 3038 if (flags & BPF_F_ADJ_ROOM_ENCAP_L4_GRE ||
+1
samples/bpf/asm_goto_workaround.h
··· 13 13 #define asm_volatile_goto(x...) asm volatile("invalid use of asm_volatile_goto") 14 14 #endif 15 15 16 + #define volatile(x...) volatile("") 16 17 #endif
+5
samples/bpf/offwaketime_user.c
··· 28 28 if (!addr) 29 29 return; 30 30 sym = ksym_search(addr); 31 + if (!sym) { 32 + printf("ksym not found. Is kallsyms loaded?\n"); 33 + return; 34 + } 35 + 31 36 if (PRINT_RAW_ADDR) 32 37 printf("%s/%llx;", sym->name, addr); 33 38 else
+5
samples/bpf/sampleip_user.c
··· 109 109 for (i = 0; i < max; i++) { 110 110 if (counts[i].ip > PAGE_OFFSET) { 111 111 sym = ksym_search(counts[i].ip); 112 + if (!sym) { 113 + printf("ksym not found. Is kallsyms loaded?\n"); 114 + continue; 115 + } 116 + 112 117 printf("0x%-17llx %-32s %u\n", counts[i].ip, sym->name, 113 118 counts[i].count); 114 119 } else {
+6 -1
samples/bpf/spintest_user.c
··· 37 37 bpf_map_lookup_elem(map_fd[0], &next_key, &value); 38 38 assert(next_key == value); 39 39 sym = ksym_search(value); 40 - printf(" %s", sym->name); 41 40 key = next_key; 41 + if (!sym) { 42 + printf("ksym not found. Is kallsyms loaded?\n"); 43 + continue; 44 + } 45 + 46 + printf(" %s", sym->name); 42 47 } 43 48 if (key) 44 49 printf("\n");
+5
samples/bpf/trace_event_user.c
··· 34 34 if (!addr) 35 35 return; 36 36 sym = ksym_search(addr); 37 + if (!sym) { 38 + printf("ksym not found. Is kallsyms loaded?\n"); 39 + return; 40 + } 41 + 37 42 printf("%s;", sym->name); 38 43 if (!strcmp(sym->name, "sys_read")) 39 44 sys_read_seen = true;
+10
tools/arch/arm64/include/asm/barrier.h
··· 14 14 #define wmb() asm volatile("dmb ishst" ::: "memory") 15 15 #define rmb() asm volatile("dmb ishld" ::: "memory") 16 16 17 + /* 18 + * Kernel uses dmb variants on arm64 for smp_*() barriers. Pretty much the same 19 + * implementation as above mb()/wmb()/rmb(), though for the latter kernel uses 20 + * dsb. In any case, should above mb()/wmb()/rmb() change, make sure the below 21 + * smp_*() don't. 22 + */ 23 + #define smp_mb() asm volatile("dmb ish" ::: "memory") 24 + #define smp_wmb() asm volatile("dmb ishst" ::: "memory") 25 + #define smp_rmb() asm volatile("dmb ishld" ::: "memory") 26 + 17 27 #define smp_store_release(p, v) \ 18 28 do { \ 19 29 union { typeof(*p) __val; char __c[1]; } __u = \
+5 -2
tools/arch/x86/include/asm/barrier.h
··· 21 21 #define rmb() asm volatile("lock; addl $0,0(%%esp)" ::: "memory") 22 22 #define wmb() asm volatile("lock; addl $0,0(%%esp)" ::: "memory") 23 23 #elif defined(__x86_64__) 24 - #define mb() asm volatile("mfence":::"memory") 25 - #define rmb() asm volatile("lfence":::"memory") 24 + #define mb() asm volatile("mfence" ::: "memory") 25 + #define rmb() asm volatile("lfence" ::: "memory") 26 26 #define wmb() asm volatile("sfence" ::: "memory") 27 + #define smp_rmb() barrier() 28 + #define smp_wmb() barrier() 29 + #define smp_mb() asm volatile("lock; addl $0,-132(%%rsp)" ::: "memory", "cc") 27 30 #endif 28 31 29 32 #if defined(__x86_64__)
+59
tools/bpf/bpftool/btf_dumper.c
··· 309 309 return ret; 310 310 } 311 311 312 + static int btf_dumper_var(const struct btf_dumper *d, __u32 type_id, 313 + __u8 bit_offset, const void *data) 314 + { 315 + const struct btf_type *t = btf__type_by_id(d->btf, type_id); 316 + int ret; 317 + 318 + jsonw_start_object(d->jw); 319 + jsonw_name(d->jw, btf__name_by_offset(d->btf, t->name_off)); 320 + ret = btf_dumper_do_type(d, t->type, bit_offset, data); 321 + jsonw_end_object(d->jw); 322 + 323 + return ret; 324 + } 325 + 326 + static int btf_dumper_datasec(const struct btf_dumper *d, __u32 type_id, 327 + const void *data) 328 + { 329 + struct btf_var_secinfo *vsi; 330 + const struct btf_type *t; 331 + int ret = 0, i, vlen; 332 + 333 + t = btf__type_by_id(d->btf, type_id); 334 + if (!t) 335 + return -EINVAL; 336 + 337 + vlen = BTF_INFO_VLEN(t->info); 338 + vsi = (struct btf_var_secinfo *)(t + 1); 339 + 340 + jsonw_start_object(d->jw); 341 + jsonw_name(d->jw, btf__name_by_offset(d->btf, t->name_off)); 342 + jsonw_start_array(d->jw); 343 + for (i = 0; i < vlen; i++) { 344 + ret = btf_dumper_do_type(d, vsi[i].type, 0, data + vsi[i].offset); 345 + if (ret) 346 + break; 347 + } 348 + jsonw_end_array(d->jw); 349 + jsonw_end_object(d->jw); 350 + 351 + return ret; 352 + } 353 + 312 354 static int btf_dumper_do_type(const struct btf_dumper *d, __u32 type_id, 313 355 __u8 bit_offset, const void *data) 314 356 { ··· 383 341 case BTF_KIND_CONST: 384 342 case BTF_KIND_RESTRICT: 385 343 return btf_dumper_modifier(d, type_id, bit_offset, data); 344 + case BTF_KIND_VAR: 345 + return btf_dumper_var(d, type_id, bit_offset, data); 346 + case BTF_KIND_DATASEC: 347 + return btf_dumper_datasec(d, type_id, data); 386 348 default: 387 349 jsonw_printf(d->jw, "(unsupported-kind"); 388 350 return -EINVAL; ··· 423 377 { 424 378 const struct btf_type *proto_type; 425 379 const struct btf_array *array; 380 + const struct btf_var *var; 426 381 const struct btf_type *t; 427 382 428 383 if (!type_id) { ··· 486 439 pos = btf_dump_func(btf, func_sig, proto_type, t, pos, size); 487 440 if (pos == -1) 488 441 return -1; 442 + break; 443 + case BTF_KIND_VAR: 444 + var = (struct btf_var *)(t + 1); 445 + if (var->linkage == BTF_VAR_STATIC) 446 + BTF_PRINT_ARG("static "); 447 + BTF_PRINT_TYPE(t->type); 448 + BTF_PRINT_ARG(" %s", 449 + btf__name_by_offset(btf, t->name_off)); 450 + break; 451 + case BTF_KIND_DATASEC: 452 + BTF_PRINT_ARG("section (\"%s\") ", 453 + btf__name_by_offset(btf, t->name_off)); 489 454 break; 490 455 case BTF_KIND_UNKN: 491 456 default:
+6 -4
tools/bpf/bpftool/map.c
··· 153 153 /* start of key-value pair */ 154 154 jsonw_start_object(d->jw); 155 155 156 - jsonw_name(d->jw, "key"); 156 + if (map_info->btf_key_type_id) { 157 + jsonw_name(d->jw, "key"); 157 158 158 - ret = btf_dumper_type(d, map_info->btf_key_type_id, key); 159 - if (ret) 160 - goto err_end_obj; 159 + ret = btf_dumper_type(d, map_info->btf_key_type_id, key); 160 + if (ret) 161 + goto err_end_obj; 162 + } 161 163 162 164 if (!map_is_per_cpu(map_info->type)) { 163 165 jsonw_name(d->jw, "value");
+6
tools/bpf/bpftool/prog.c
··· 249 249 if (info->nr_map_ids) 250 250 show_prog_maps(fd, info->nr_map_ids); 251 251 252 + if (info->btf_id) 253 + jsonw_int_field(json_wtr, "btf_id", info->btf_id); 254 + 252 255 if (!hash_empty(prog_table.table)) { 253 256 struct pinned_obj *obj; 254 257 ··· 321 318 printf("\n\tpinned %s", obj->path); 322 319 } 323 320 } 321 + 322 + if (info->btf_id) 323 + printf("\n\tbtf_id %d\n", info->btf_id); 324 324 325 325 printf("\n"); 326 326 }
+3
tools/bpf/bpftool/xlated_dumper.c
··· 195 195 if (insn->src_reg == BPF_PSEUDO_MAP_FD) 196 196 snprintf(dd->scratch_buff, sizeof(dd->scratch_buff), 197 197 "map[id:%u]", insn->imm); 198 + else if (insn->src_reg == BPF_PSEUDO_MAP_VALUE) 199 + snprintf(dd->scratch_buff, sizeof(dd->scratch_buff), 200 + "map[id:%u][0]+%u", insn->imm, (insn + 1)->imm); 198 201 else 199 202 snprintf(dd->scratch_buff, sizeof(dd->scratch_buff), 200 203 "0x%llx", (unsigned long long)full_imm);
+20 -1
tools/include/linux/filter.h
··· 278 278 .off = 0, \ 279 279 .imm = ((__u64) (IMM)) >> 32 }) 280 280 281 + #define BPF_LD_IMM64_RAW_FULL(DST, SRC, OFF1, OFF2, IMM1, IMM2) \ 282 + ((struct bpf_insn) { \ 283 + .code = BPF_LD | BPF_DW | BPF_IMM, \ 284 + .dst_reg = DST, \ 285 + .src_reg = SRC, \ 286 + .off = OFF1, \ 287 + .imm = IMM1 }), \ 288 + ((struct bpf_insn) { \ 289 + .code = 0, /* zero is reserved opcode */ \ 290 + .dst_reg = 0, \ 291 + .src_reg = 0, \ 292 + .off = OFF2, \ 293 + .imm = IMM2 }) 294 + 281 295 /* pseudo BPF_LD_IMM64 insn used to refer to process-local map_fd */ 282 296 283 297 #define BPF_LD_MAP_FD(DST, MAP_FD) \ 284 - BPF_LD_IMM64_RAW(DST, BPF_PSEUDO_MAP_FD, MAP_FD) 298 + BPF_LD_IMM64_RAW_FULL(DST, BPF_PSEUDO_MAP_FD, 0, 0, \ 299 + MAP_FD, 0) 300 + 301 + #define BPF_LD_MAP_VALUE(DST, MAP_FD, VALUE_OFF) \ 302 + BPF_LD_IMM64_RAW_FULL(DST, BPF_PSEUDO_MAP_VALUE, 0, 0, \ 303 + MAP_FD, VALUE_OFF) 285 304 286 305 /* Relative call */ 287 306
+35 -2
tools/include/uapi/linux/bpf.h
··· 105 105 BPF_BTF_GET_FD_BY_ID, 106 106 BPF_TASK_FD_QUERY, 107 107 BPF_MAP_LOOKUP_AND_DELETE_ELEM, 108 + BPF_MAP_FREEZE, 108 109 }; 109 110 110 111 enum bpf_map_type { ··· 256 255 */ 257 256 #define BPF_F_ANY_ALIGNMENT (1U << 1) 258 257 259 - /* when bpf_ldimm64->src_reg == BPF_PSEUDO_MAP_FD, bpf_ldimm64->imm == fd */ 258 + /* When BPF ldimm64's insn[0].src_reg != 0 then this can have 259 + * two extensions: 260 + * 261 + * insn[0].src_reg: BPF_PSEUDO_MAP_FD BPF_PSEUDO_MAP_VALUE 262 + * insn[0].imm: map fd map fd 263 + * insn[1].imm: 0 offset into value 264 + * insn[0].off: 0 0 265 + * insn[1].off: 0 0 266 + * ldimm64 rewrite: address of map address of map[0]+offset 267 + * verifier type: CONST_PTR_TO_MAP PTR_TO_MAP_VALUE 268 + */ 260 269 #define BPF_PSEUDO_MAP_FD 1 270 + #define BPF_PSEUDO_MAP_VALUE 2 261 271 262 272 /* when bpf_call->src_reg == BPF_PSEUDO_CALL, bpf_call->imm == pc-relative 263 273 * offset to another bpf function ··· 295 283 296 284 #define BPF_OBJ_NAME_LEN 16U 297 285 298 - /* Flags for accessing BPF object */ 286 + /* Flags for accessing BPF object from syscall side. */ 299 287 #define BPF_F_RDONLY (1U << 3) 300 288 #define BPF_F_WRONLY (1U << 4) 301 289 ··· 304 292 305 293 /* Zero-initialize hash function seed. This should only be used for testing. */ 306 294 #define BPF_F_ZERO_SEED (1U << 6) 295 + 296 + /* Flags for accessing BPF object from program side. */ 297 + #define BPF_F_RDONLY_PROG (1U << 7) 298 + #define BPF_F_WRONLY_PROG (1U << 8) 307 299 308 300 /* flags for BPF_PROG_QUERY */ 309 301 #define BPF_F_QUERY_EFFECTIVE (1U << 0) ··· 412 396 __aligned_u64 data_out; 413 397 __u32 repeat; 414 398 __u32 duration; 399 + __u32 ctx_size_in; /* input: len of ctx_in */ 400 + __u32 ctx_size_out; /* input/output: len of ctx_out 401 + * returns ENOSPC if ctx_out 402 + * is too small. 403 + */ 404 + __aligned_u64 ctx_in; 405 + __aligned_u64 ctx_out; 415 406 } test; 416 407 417 408 struct { /* anonymous struct used by BPF_*_GET_*_ID */ ··· 1522 1499 * * **BPF_F_ADJ_ROOM_ENCAP_L4_GRE **: 1523 1500 * * **BPF_F_ADJ_ROOM_ENCAP_L4_UDP **: 1524 1501 * Use with ENCAP_L3 flags to further specify the tunnel type. 1502 + * 1503 + * * **BPF_F_ADJ_ROOM_ENCAP_L2(len) **: 1504 + * Use with ENCAP_L3/L4 flags to further specify the tunnel 1505 + * type; **len** is the length of the inner MAC header. 1525 1506 * 1526 1507 * A call to this helper is susceptible to change the underlaying 1527 1508 * packet buffer. Therefore, at load time, all checks on pointers ··· 2668 2641 /* BPF_FUNC_skb_adjust_room flags. */ 2669 2642 #define BPF_F_ADJ_ROOM_FIXED_GSO (1ULL << 0) 2670 2643 2644 + #define BPF_ADJ_ROOM_ENCAP_L2_MASK 0xff 2645 + #define BPF_ADJ_ROOM_ENCAP_L2_SHIFT 56 2646 + 2671 2647 #define BPF_F_ADJ_ROOM_ENCAP_L3_IPV4 (1ULL << 1) 2672 2648 #define BPF_F_ADJ_ROOM_ENCAP_L3_IPV6 (1ULL << 2) 2673 2649 #define BPF_F_ADJ_ROOM_ENCAP_L4_GRE (1ULL << 3) 2674 2650 #define BPF_F_ADJ_ROOM_ENCAP_L4_UDP (1ULL << 4) 2651 + #define BPF_F_ADJ_ROOM_ENCAP_L2(len) (((__u64)len & \ 2652 + BPF_ADJ_ROOM_ENCAP_L2_MASK) \ 2653 + << BPF_ADJ_ROOM_ENCAP_L2_SHIFT) 2675 2654 2676 2655 /* Mode for BPF_FUNC_skb_adjust_room helper. */ 2677 2656 enum bpf_adj_room_mode {
+28 -4
tools/include/uapi/linux/btf.h
··· 39 39 * struct, union and fwd 40 40 */ 41 41 __u32 info; 42 - /* "size" is used by INT, ENUM, STRUCT and UNION. 42 + /* "size" is used by INT, ENUM, STRUCT, UNION and DATASEC. 43 43 * "size" tells the size of the type it is describing. 44 44 * 45 45 * "type" is used by PTR, TYPEDEF, VOLATILE, CONST, RESTRICT, 46 - * FUNC and FUNC_PROTO. 46 + * FUNC, FUNC_PROTO and VAR. 47 47 * "type" is a type_id referring to another type. 48 48 */ 49 49 union { ··· 70 70 #define BTF_KIND_RESTRICT 11 /* Restrict */ 71 71 #define BTF_KIND_FUNC 12 /* Function */ 72 72 #define BTF_KIND_FUNC_PROTO 13 /* Function Proto */ 73 - #define BTF_KIND_MAX 13 74 - #define NR_BTF_KINDS 14 73 + #define BTF_KIND_VAR 14 /* Variable */ 74 + #define BTF_KIND_DATASEC 15 /* Section */ 75 + #define BTF_KIND_MAX BTF_KIND_DATASEC 76 + #define NR_BTF_KINDS (BTF_KIND_MAX + 1) 75 77 76 78 /* For some specific BTF_KIND, "struct btf_type" is immediately 77 79 * followed by extra data. ··· 138 136 struct btf_param { 139 137 __u32 name_off; 140 138 __u32 type; 139 + }; 140 + 141 + enum { 142 + BTF_VAR_STATIC = 0, 143 + BTF_VAR_GLOBAL_ALLOCATED, 144 + }; 145 + 146 + /* BTF_KIND_VAR is followed by a single "struct btf_var" to describe 147 + * additional information related to the variable such as its linkage. 148 + */ 149 + struct btf_var { 150 + __u32 linkage; 151 + }; 152 + 153 + /* BTF_KIND_DATASEC is followed by multiple "struct btf_var_secinfo" 154 + * to describe all BTF_KIND_VAR types it contains along with it's 155 + * in-section offset as well as size. 156 + */ 157 + struct btf_var_secinfo { 158 + __u32 type; 159 + __u32 offset; 160 + __u32 size; 141 161 }; 142 162 143 163 #endif /* _UAPI__LINUX_BTF_H__ */
+1
tools/lib/bpf/.gitignore
··· 1 1 libbpf_version.h 2 + libbpf.pc 2 3 FEATURE-DUMP.libbpf 3 4 test_libbpf
+16 -4
tools/lib/bpf/Makefile
··· 3 3 4 4 BPF_VERSION = 0 5 5 BPF_PATCHLEVEL = 0 6 - BPF_EXTRAVERSION = 2 6 + BPF_EXTRAVERSION = 3 7 7 8 8 MAKEFLAGS += --no-print-directory 9 9 ··· 90 90 91 91 LIB_TARGET = libbpf.a libbpf.so.$(LIBBPF_VERSION) 92 92 LIB_FILE = libbpf.a libbpf.so* 93 + PC_FILE = libbpf.pc 93 94 94 95 # Set compile option CFLAGS 95 96 ifdef EXTRA_CFLAGS ··· 135 134 136 135 LIB_TARGET := $(addprefix $(OUTPUT),$(LIB_TARGET)) 137 136 LIB_FILE := $(addprefix $(OUTPUT),$(LIB_FILE)) 137 + PC_FILE := $(addprefix $(OUTPUT),$(PC_FILE)) 138 138 139 139 GLOBAL_SYM_COUNT = $(shell readelf -s --wide $(BPF_IN) | \ 140 140 awk '/GLOBAL/ && /DEFAULT/ && !/UND/ {s++} END{print s}') 141 141 VERSIONED_SYM_COUNT = $(shell readelf -s --wide $(OUTPUT)libbpf.so | \ 142 142 grep -Eo '[^ ]+@LIBBPF_' | cut -d@ -f1 | sort -u | wc -l) 143 143 144 - CMD_TARGETS = $(LIB_TARGET) 144 + CMD_TARGETS = $(LIB_TARGET) $(PC_FILE) 145 145 146 146 CXX_TEST_TARGET = $(OUTPUT)test_libbpf 147 147 ··· 189 187 $(OUTPUT)test_libbpf: test_libbpf.cpp $(OUTPUT)libbpf.a 190 188 $(QUIET_LINK)$(CXX) $(INCLUDES) $^ -lelf -o $@ 191 189 190 + $(OUTPUT)libbpf.pc: 191 + $(QUIET_GEN)sed -e "s|@PREFIX@|$(prefix)|" \ 192 + -e "s|@LIBDIR@|$(libdir_SQ)|" \ 193 + -e "s|@VERSION@|$(LIBBPF_VERSION)|" \ 194 + < libbpf.pc.template > $@ 195 + 192 196 check: check_abi 193 197 194 198 check_abi: $(OUTPUT)libbpf.so ··· 232 224 $(call do_install,btf.h,$(prefix)/include/bpf,644); \ 233 225 $(call do_install,xsk.h,$(prefix)/include/bpf,644); 234 226 235 - install: install_lib 227 + install_pkgconfig: $(PC_FILE) 228 + $(call QUIET_INSTALL, $(PC_FILE)) \ 229 + $(call do_install,$(PC_FILE),$(libdir_SQ)/pkgconfig,644) 230 + 231 + install: install_lib install_pkgconfig 236 232 237 233 ### Cleaning rules 238 234 ··· 246 234 247 235 clean: 248 236 $(call QUIET_CLEAN, libbpf) $(RM) $(TARGETS) $(CXX_TEST_TARGET) \ 249 - *.o *~ *.a *.so *.so.$(VERSION) .*.d .*.cmd LIBBPF-CFLAGS 237 + *.o *~ *.a *.so *.so.$(VERSION) .*.d .*.cmd *.pc LIBBPF-CFLAGS 250 238 $(call QUIET_CLEAN, core-gen) $(RM) $(OUTPUT)FEATURE-DUMP.libbpf 251 239 252 240
+25 -11
tools/lib/bpf/bpf.c
··· 79 79 80 80 int bpf_create_map_xattr(const struct bpf_create_map_attr *create_attr) 81 81 { 82 - __u32 name_len = create_attr->name ? strlen(create_attr->name) : 0; 83 82 union bpf_attr attr; 84 83 85 84 memset(&attr, '\0', sizeof(attr)); ··· 88 89 attr.value_size = create_attr->value_size; 89 90 attr.max_entries = create_attr->max_entries; 90 91 attr.map_flags = create_attr->map_flags; 91 - memcpy(attr.map_name, create_attr->name, 92 - min(name_len, BPF_OBJ_NAME_LEN - 1)); 92 + if (create_attr->name) 93 + memcpy(attr.map_name, create_attr->name, 94 + min(strlen(create_attr->name), BPF_OBJ_NAME_LEN - 1)); 93 95 attr.numa_node = create_attr->numa_node; 94 96 attr.btf_fd = create_attr->btf_fd; 95 97 attr.btf_key_type_id = create_attr->btf_key_type_id; ··· 155 155 int key_size, int inner_map_fd, int max_entries, 156 156 __u32 map_flags, int node) 157 157 { 158 - __u32 name_len = name ? strlen(name) : 0; 159 158 union bpf_attr attr; 160 159 161 160 memset(&attr, '\0', sizeof(attr)); ··· 165 166 attr.inner_map_fd = inner_map_fd; 166 167 attr.max_entries = max_entries; 167 168 attr.map_flags = map_flags; 168 - memcpy(attr.map_name, name, min(name_len, BPF_OBJ_NAME_LEN - 1)); 169 + if (name) 170 + memcpy(attr.map_name, name, 171 + min(strlen(name), BPF_OBJ_NAME_LEN - 1)); 169 172 170 173 if (node >= 0) { 171 174 attr.map_flags |= BPF_F_NUMA_NODE; ··· 217 216 void *finfo = NULL, *linfo = NULL; 218 217 union bpf_attr attr; 219 218 __u32 log_level; 220 - __u32 name_len; 221 219 int fd; 222 220 223 221 if (!load_attr || !log_buf != !log_buf_sz) 224 222 return -EINVAL; 225 223 226 224 log_level = load_attr->log_level; 227 - if (log_level > 2 || (log_level && !log_buf)) 225 + if (log_level > (4 | 2 | 1) || (log_level && !log_buf)) 228 226 return -EINVAL; 229 - 230 - name_len = load_attr->name ? strlen(load_attr->name) : 0; 231 227 232 228 memset(&attr, 0, sizeof(attr)); 233 229 attr.prog_type = load_attr->prog_type; ··· 251 253 attr.line_info_rec_size = load_attr->line_info_rec_size; 252 254 attr.line_info_cnt = load_attr->line_info_cnt; 253 255 attr.line_info = ptr_to_u64(load_attr->line_info); 254 - memcpy(attr.prog_name, load_attr->name, 255 - min(name_len, BPF_OBJ_NAME_LEN - 1)); 256 + if (load_attr->name) 257 + memcpy(attr.prog_name, load_attr->name, 258 + min(strlen(load_attr->name), BPF_OBJ_NAME_LEN - 1)); 256 259 257 260 fd = sys_bpf_prog_load(&attr, sizeof(attr)); 258 261 if (fd >= 0) ··· 428 429 return sys_bpf(BPF_MAP_GET_NEXT_KEY, &attr, sizeof(attr)); 429 430 } 430 431 432 + int bpf_map_freeze(int fd) 433 + { 434 + union bpf_attr attr; 435 + 436 + memset(&attr, 0, sizeof(attr)); 437 + attr.map_fd = fd; 438 + 439 + return sys_bpf(BPF_MAP_FREEZE, &attr, sizeof(attr)); 440 + } 441 + 431 442 int bpf_obj_pin(int fd, const char *pathname) 432 443 { 433 444 union bpf_attr attr; ··· 554 545 attr.test.data_out = ptr_to_u64(test_attr->data_out); 555 546 attr.test.data_size_in = test_attr->data_size_in; 556 547 attr.test.data_size_out = test_attr->data_size_out; 548 + attr.test.ctx_in = ptr_to_u64(test_attr->ctx_in); 549 + attr.test.ctx_out = ptr_to_u64(test_attr->ctx_out); 550 + attr.test.ctx_size_in = test_attr->ctx_size_in; 551 + attr.test.ctx_size_out = test_attr->ctx_size_out; 557 552 attr.test.repeat = test_attr->repeat; 558 553 559 554 ret = sys_bpf(BPF_PROG_TEST_RUN, &attr, sizeof(attr)); 560 555 test_attr->data_size_out = attr.test.data_size_out; 556 + test_attr->ctx_size_out = attr.test.ctx_size_out; 561 557 test_attr->retval = attr.test.retval; 562 558 test_attr->duration = attr.test.duration; 563 559 return ret;
+7 -1
tools/lib/bpf/bpf.h
··· 92 92 #define MAPS_RELAX_COMPAT 0x01 93 93 94 94 /* Recommend log buffer size */ 95 - #define BPF_LOG_BUF_SIZE (256 * 1024) 95 + #define BPF_LOG_BUF_SIZE (16 * 1024 * 1024) /* verifier maximum in kernels <= 5.1 */ 96 96 LIBBPF_API int 97 97 bpf_load_program_xattr(const struct bpf_load_program_attr *load_attr, 98 98 char *log_buf, size_t log_buf_sz); ··· 117 117 void *value); 118 118 LIBBPF_API int bpf_map_delete_elem(int fd, const void *key); 119 119 LIBBPF_API int bpf_map_get_next_key(int fd, const void *key, void *next_key); 120 + LIBBPF_API int bpf_map_freeze(int fd); 120 121 LIBBPF_API int bpf_obj_pin(int fd, const char *pathname); 121 122 LIBBPF_API int bpf_obj_get(const char *pathname); 122 123 LIBBPF_API int bpf_prog_attach(int prog_fd, int attachable_fd, ··· 136 135 * out: length of data_out */ 137 136 __u32 retval; /* out: return code of the BPF program */ 138 137 __u32 duration; /* out: average per repetition in ns */ 138 + const void *ctx_in; /* optional */ 139 + __u32 ctx_size_in; 140 + void *ctx_out; /* optional */ 141 + __u32 ctx_size_out; /* in: max length of ctx_out 142 + * out: length of cxt_out */ 139 143 }; 140 144 141 145 LIBBPF_API int bpf_prog_test_run_xattr(struct bpf_prog_test_run_attr *test_attr);
+96 -1
tools/lib/bpf/btf.c
··· 24 24 ((k) == BTF_KIND_CONST) || \ 25 25 ((k) == BTF_KIND_RESTRICT)) 26 26 27 + #define IS_VAR(k) ((k) == BTF_KIND_VAR) 28 + 27 29 static struct btf_type btf_void; 28 30 29 31 struct btf { ··· 214 212 return base_size + vlen * sizeof(struct btf_member); 215 213 case BTF_KIND_FUNC_PROTO: 216 214 return base_size + vlen * sizeof(struct btf_param); 215 + case BTF_KIND_VAR: 216 + return base_size + sizeof(struct btf_var); 217 + case BTF_KIND_DATASEC: 218 + return base_size + vlen * sizeof(struct btf_var_secinfo); 217 219 default: 218 220 pr_debug("Unsupported BTF_KIND:%u\n", BTF_INFO_KIND(t->info)); 219 221 return -EINVAL; ··· 289 283 case BTF_KIND_STRUCT: 290 284 case BTF_KIND_UNION: 291 285 case BTF_KIND_ENUM: 286 + case BTF_KIND_DATASEC: 292 287 size = t->size; 293 288 goto done; 294 289 case BTF_KIND_PTR: ··· 299 292 case BTF_KIND_VOLATILE: 300 293 case BTF_KIND_CONST: 301 294 case BTF_KIND_RESTRICT: 295 + case BTF_KIND_VAR: 302 296 type_id = t->type; 303 297 break; 304 298 case BTF_KIND_ARRAY: ··· 334 326 t = btf__type_by_id(btf, type_id); 335 327 while (depth < MAX_RESOLVE_DEPTH && 336 328 !btf_type_is_void_or_null(t) && 337 - IS_MODIFIER(BTF_INFO_KIND(t->info))) { 329 + (IS_MODIFIER(BTF_INFO_KIND(t->info)) || 330 + IS_VAR(BTF_INFO_KIND(t->info)))) { 338 331 type_id = t->type; 339 332 t = btf__type_by_id(btf, type_id); 340 333 depth++; ··· 415 406 } 416 407 417 408 return btf; 409 + } 410 + 411 + static int compare_vsi_off(const void *_a, const void *_b) 412 + { 413 + const struct btf_var_secinfo *a = _a; 414 + const struct btf_var_secinfo *b = _b; 415 + 416 + return a->offset - b->offset; 417 + } 418 + 419 + static int btf_fixup_datasec(struct bpf_object *obj, struct btf *btf, 420 + struct btf_type *t) 421 + { 422 + __u32 size = 0, off = 0, i, vars = BTF_INFO_VLEN(t->info); 423 + const char *name = btf__name_by_offset(btf, t->name_off); 424 + const struct btf_type *t_var; 425 + struct btf_var_secinfo *vsi; 426 + struct btf_var *var; 427 + int ret; 428 + 429 + if (!name) { 430 + pr_debug("No name found in string section for DATASEC kind.\n"); 431 + return -ENOENT; 432 + } 433 + 434 + ret = bpf_object__section_size(obj, name, &size); 435 + if (ret || !size || (t->size && t->size != size)) { 436 + pr_debug("Invalid size for section %s: %u bytes\n", name, size); 437 + return -ENOENT; 438 + } 439 + 440 + t->size = size; 441 + 442 + for (i = 0, vsi = (struct btf_var_secinfo *)(t + 1); 443 + i < vars; i++, vsi++) { 444 + t_var = btf__type_by_id(btf, vsi->type); 445 + var = (struct btf_var *)(t_var + 1); 446 + 447 + if (BTF_INFO_KIND(t_var->info) != BTF_KIND_VAR) { 448 + pr_debug("Non-VAR type seen in section %s\n", name); 449 + return -EINVAL; 450 + } 451 + 452 + if (var->linkage == BTF_VAR_STATIC) 453 + continue; 454 + 455 + name = btf__name_by_offset(btf, t_var->name_off); 456 + if (!name) { 457 + pr_debug("No name found in string section for VAR kind\n"); 458 + return -ENOENT; 459 + } 460 + 461 + ret = bpf_object__variable_offset(obj, name, &off); 462 + if (ret) { 463 + pr_debug("No offset found in symbol table for VAR %s\n", name); 464 + return -ENOENT; 465 + } 466 + 467 + vsi->offset = off; 468 + } 469 + 470 + qsort(t + 1, vars, sizeof(*vsi), compare_vsi_off); 471 + return 0; 472 + } 473 + 474 + int btf__finalize_data(struct bpf_object *obj, struct btf *btf) 475 + { 476 + int err = 0; 477 + __u32 i; 478 + 479 + for (i = 1; i <= btf->nr_types; i++) { 480 + struct btf_type *t = btf->types[i]; 481 + 482 + /* Loader needs to fix up some of the things compiler 483 + * couldn't get its hands on while emitting BTF. This 484 + * is section size and global variable offset. We use 485 + * the info from the ELF itself for this purpose. 486 + */ 487 + if (BTF_INFO_KIND(t->info) == BTF_KIND_DATASEC) { 488 + err = btf_fixup_datasec(obj, btf, t); 489 + if (err) 490 + break; 491 + } 492 + } 493 + 494 + return err; 418 495 } 419 496 420 497 int btf__load(struct btf *btf)
+3
tools/lib/bpf/btf.h
··· 21 21 struct btf_ext; 22 22 struct btf_type; 23 23 24 + struct bpf_object; 25 + 24 26 /* 25 27 * The .BTF.ext ELF section layout defined as 26 28 * struct btf_ext_header ··· 59 57 60 58 LIBBPF_API void btf__free(struct btf *btf); 61 59 LIBBPF_API struct btf *btf__new(__u8 *data, __u32 size); 60 + LIBBPF_API int btf__finalize_data(struct bpf_object *obj, struct btf *btf); 62 61 LIBBPF_API int btf__load(struct btf *btf); 63 62 LIBBPF_API __s32 btf__find_by_name(const struct btf *btf, 64 63 const char *type_name);
+473 -94
tools/lib/bpf/libbpf.c
··· 7 7 * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com> 8 8 * Copyright (C) 2015 Huawei Inc. 9 9 * Copyright (C) 2017 Nicira, Inc. 10 + * Copyright (C) 2019 Isovalent, Inc. 10 11 */ 11 12 12 13 #ifndef _GNU_SOURCE ··· 52 51 #ifndef BPF_FS_MAGIC 53 52 #define BPF_FS_MAGIC 0xcafe4a11 54 53 #endif 54 + 55 + /* vsprintf() in __base_pr() uses nonliteral format string. It may break 56 + * compilation if user enables corresponding warning. Disable it explicitly. 57 + */ 58 + #pragma GCC diagnostic ignored "-Wformat-nonliteral" 55 59 56 60 #define __printf(a, b) __attribute__((format(printf, a, b))) 57 61 ··· 150 144 enum { 151 145 RELO_LD64, 152 146 RELO_CALL, 147 + RELO_DATA, 153 148 } type; 154 149 int insn_idx; 155 150 union { ··· 159 152 }; 160 153 } *reloc_desc; 161 154 int nr_reloc; 155 + int log_level; 162 156 163 157 struct { 164 158 int nr; ··· 184 176 __u32 line_info_cnt; 185 177 }; 186 178 179 + enum libbpf_map_type { 180 + LIBBPF_MAP_UNSPEC, 181 + LIBBPF_MAP_DATA, 182 + LIBBPF_MAP_BSS, 183 + LIBBPF_MAP_RODATA, 184 + }; 185 + 186 + static const char * const libbpf_type_to_btf_name[] = { 187 + [LIBBPF_MAP_DATA] = ".data", 188 + [LIBBPF_MAP_BSS] = ".bss", 189 + [LIBBPF_MAP_RODATA] = ".rodata", 190 + }; 191 + 187 192 struct bpf_map { 188 193 int fd; 189 194 char *name; ··· 208 187 __u32 btf_value_type_id; 209 188 void *priv; 210 189 bpf_map_clear_priv_t clear_priv; 190 + enum libbpf_map_type libbpf_type; 191 + }; 192 + 193 + struct bpf_secdata { 194 + void *rodata; 195 + void *data; 211 196 }; 212 197 213 198 static LIST_HEAD(bpf_objects_list); 214 199 215 200 struct bpf_object { 201 + char name[BPF_OBJ_NAME_LEN]; 216 202 char license[64]; 217 203 __u32 kern_version; 218 204 ··· 227 199 size_t nr_programs; 228 200 struct bpf_map *maps; 229 201 size_t nr_maps; 202 + struct bpf_secdata sections; 230 203 231 204 bool loaded; 232 205 bool has_pseudo_calls; ··· 243 214 Elf *elf; 244 215 GElf_Ehdr ehdr; 245 216 Elf_Data *symbols; 217 + Elf_Data *data; 218 + Elf_Data *rodata; 219 + Elf_Data *bss; 246 220 size_t strtabidx; 247 221 struct { 248 222 GElf_Shdr shdr; ··· 254 222 int nr_reloc; 255 223 int maps_shndx; 256 224 int text_shndx; 225 + int data_shndx; 226 + int rodata_shndx; 227 + int bss_shndx; 257 228 } efile; 258 229 /* 259 230 * All loaded bpf_object is linked in a list, which is ··· 478 443 size_t obj_buf_sz) 479 444 { 480 445 struct bpf_object *obj; 446 + char *end; 481 447 482 448 obj = calloc(1, sizeof(struct bpf_object) + strlen(path) + 1); 483 449 if (!obj) { ··· 487 451 } 488 452 489 453 strcpy(obj->path, path); 490 - obj->efile.fd = -1; 454 + /* Using basename() GNU version which doesn't modify arg. */ 455 + strncpy(obj->name, basename((void *)path), 456 + sizeof(obj->name) - 1); 457 + end = strchr(obj->name, '.'); 458 + if (end) 459 + *end = 0; 491 460 461 + obj->efile.fd = -1; 492 462 /* 493 463 * Caller of this function should also calls 494 464 * bpf_object__elf_finish() after data collection to return ··· 504 462 obj->efile.obj_buf = obj_buf; 505 463 obj->efile.obj_buf_sz = obj_buf_sz; 506 464 obj->efile.maps_shndx = -1; 465 + obj->efile.data_shndx = -1; 466 + obj->efile.rodata_shndx = -1; 467 + obj->efile.bss_shndx = -1; 507 468 508 469 obj->loaded = false; 509 470 ··· 525 480 obj->efile.elf = NULL; 526 481 } 527 482 obj->efile.symbols = NULL; 483 + obj->efile.data = NULL; 484 + obj->efile.rodata = NULL; 485 + obj->efile.bss = NULL; 528 486 529 487 zfree(&obj->efile.reloc); 530 488 obj->efile.nr_reloc = 0; ··· 669 621 return false; 670 622 } 671 623 624 + static int bpf_object_search_section_size(const struct bpf_object *obj, 625 + const char *name, size_t *d_size) 626 + { 627 + const GElf_Ehdr *ep = &obj->efile.ehdr; 628 + Elf *elf = obj->efile.elf; 629 + Elf_Scn *scn = NULL; 630 + int idx = 0; 631 + 632 + while ((scn = elf_nextscn(elf, scn)) != NULL) { 633 + const char *sec_name; 634 + Elf_Data *data; 635 + GElf_Shdr sh; 636 + 637 + idx++; 638 + if (gelf_getshdr(scn, &sh) != &sh) { 639 + pr_warning("failed to get section(%d) header from %s\n", 640 + idx, obj->path); 641 + return -EIO; 642 + } 643 + 644 + sec_name = elf_strptr(elf, ep->e_shstrndx, sh.sh_name); 645 + if (!sec_name) { 646 + pr_warning("failed to get section(%d) name from %s\n", 647 + idx, obj->path); 648 + return -EIO; 649 + } 650 + 651 + if (strcmp(name, sec_name)) 652 + continue; 653 + 654 + data = elf_getdata(scn, 0); 655 + if (!data) { 656 + pr_warning("failed to get section(%d) data from %s(%s)\n", 657 + idx, name, obj->path); 658 + return -EIO; 659 + } 660 + 661 + *d_size = data->d_size; 662 + return 0; 663 + } 664 + 665 + return -ENOENT; 666 + } 667 + 668 + int bpf_object__section_size(const struct bpf_object *obj, const char *name, 669 + __u32 *size) 670 + { 671 + int ret = -ENOENT; 672 + size_t d_size; 673 + 674 + *size = 0; 675 + if (!name) { 676 + return -EINVAL; 677 + } else if (!strcmp(name, ".data")) { 678 + if (obj->efile.data) 679 + *size = obj->efile.data->d_size; 680 + } else if (!strcmp(name, ".bss")) { 681 + if (obj->efile.bss) 682 + *size = obj->efile.bss->d_size; 683 + } else if (!strcmp(name, ".rodata")) { 684 + if (obj->efile.rodata) 685 + *size = obj->efile.rodata->d_size; 686 + } else { 687 + ret = bpf_object_search_section_size(obj, name, &d_size); 688 + if (!ret) 689 + *size = d_size; 690 + } 691 + 692 + return *size ? 0 : ret; 693 + } 694 + 695 + int bpf_object__variable_offset(const struct bpf_object *obj, const char *name, 696 + __u32 *off) 697 + { 698 + Elf_Data *symbols = obj->efile.symbols; 699 + const char *sname; 700 + size_t si; 701 + 702 + if (!name || !off) 703 + return -EINVAL; 704 + 705 + for (si = 0; si < symbols->d_size / sizeof(GElf_Sym); si++) { 706 + GElf_Sym sym; 707 + 708 + if (!gelf_getsym(symbols, si, &sym)) 709 + continue; 710 + if (GELF_ST_BIND(sym.st_info) != STB_GLOBAL || 711 + GELF_ST_TYPE(sym.st_info) != STT_OBJECT) 712 + continue; 713 + 714 + sname = elf_strptr(obj->efile.elf, obj->efile.strtabidx, 715 + sym.st_name); 716 + if (!sname) { 717 + pr_warning("failed to get sym name string for var %s\n", 718 + name); 719 + return -EIO; 720 + } 721 + if (strcmp(name, sname) == 0) { 722 + *off = sym.st_value; 723 + return 0; 724 + } 725 + } 726 + 727 + return -ENOENT; 728 + } 729 + 730 + static bool bpf_object__has_maps(const struct bpf_object *obj) 731 + { 732 + return obj->efile.maps_shndx >= 0 || 733 + obj->efile.data_shndx >= 0 || 734 + obj->efile.rodata_shndx >= 0 || 735 + obj->efile.bss_shndx >= 0; 736 + } 737 + 738 + static int 739 + bpf_object__init_internal_map(struct bpf_object *obj, struct bpf_map *map, 740 + enum libbpf_map_type type, Elf_Data *data, 741 + void **data_buff) 742 + { 743 + struct bpf_map_def *def = &map->def; 744 + char map_name[BPF_OBJ_NAME_LEN]; 745 + 746 + map->libbpf_type = type; 747 + map->offset = ~(typeof(map->offset))0; 748 + snprintf(map_name, sizeof(map_name), "%.8s%.7s", obj->name, 749 + libbpf_type_to_btf_name[type]); 750 + map->name = strdup(map_name); 751 + if (!map->name) { 752 + pr_warning("failed to alloc map name\n"); 753 + return -ENOMEM; 754 + } 755 + 756 + def->type = BPF_MAP_TYPE_ARRAY; 757 + def->key_size = sizeof(int); 758 + def->value_size = data->d_size; 759 + def->max_entries = 1; 760 + def->map_flags = type == LIBBPF_MAP_RODATA ? 761 + BPF_F_RDONLY_PROG : 0; 762 + if (data_buff) { 763 + *data_buff = malloc(data->d_size); 764 + if (!*data_buff) { 765 + zfree(&map->name); 766 + pr_warning("failed to alloc map content buffer\n"); 767 + return -ENOMEM; 768 + } 769 + memcpy(*data_buff, data->d_buf, data->d_size); 770 + } 771 + 772 + pr_debug("map %ld is \"%s\"\n", map - obj->maps, map->name); 773 + return 0; 774 + } 775 + 672 776 static int 673 777 bpf_object__init_maps(struct bpf_object *obj, int flags) 674 778 { 779 + int i, map_idx, map_def_sz = 0, nr_syms, nr_maps = 0, nr_maps_glob = 0; 675 780 bool strict = !(flags & MAPS_RELAX_COMPAT); 676 - int i, map_idx, map_def_sz, nr_maps = 0; 677 - Elf_Scn *scn; 678 - Elf_Data *data = NULL; 679 781 Elf_Data *symbols = obj->efile.symbols; 782 + Elf_Data *data = NULL; 783 + int ret = 0; 680 784 681 - if (obj->efile.maps_shndx < 0) 682 - return -EINVAL; 683 785 if (!symbols) 684 786 return -EINVAL; 787 + nr_syms = symbols->d_size / sizeof(GElf_Sym); 685 788 686 - scn = elf_getscn(obj->efile.elf, obj->efile.maps_shndx); 687 - if (scn) 688 - data = elf_getdata(scn, NULL); 689 - if (!scn || !data) { 690 - pr_warning("failed to get Elf_Data from map section %d\n", 691 - obj->efile.maps_shndx); 692 - return -EINVAL; 789 + if (obj->efile.maps_shndx >= 0) { 790 + Elf_Scn *scn = elf_getscn(obj->efile.elf, 791 + obj->efile.maps_shndx); 792 + 793 + if (scn) 794 + data = elf_getdata(scn, NULL); 795 + if (!scn || !data) { 796 + pr_warning("failed to get Elf_Data from map section %d\n", 797 + obj->efile.maps_shndx); 798 + return -EINVAL; 799 + } 693 800 } 694 801 695 802 /* ··· 854 651 * 855 652 * TODO: Detect array of map and report error. 856 653 */ 857 - for (i = 0; i < symbols->d_size / sizeof(GElf_Sym); i++) { 654 + if (obj->efile.data_shndx >= 0) 655 + nr_maps_glob++; 656 + if (obj->efile.rodata_shndx >= 0) 657 + nr_maps_glob++; 658 + if (obj->efile.bss_shndx >= 0) 659 + nr_maps_glob++; 660 + for (i = 0; data && i < nr_syms; i++) { 858 661 GElf_Sym sym; 859 662 860 663 if (!gelf_getsym(symbols, i, &sym)) ··· 873 664 /* Alloc obj->maps and fill nr_maps. */ 874 665 pr_debug("maps in %s: %d maps in %zd bytes\n", obj->path, 875 666 nr_maps, data->d_size); 876 - 877 - if (!nr_maps) 667 + if (!nr_maps && !nr_maps_glob) 878 668 return 0; 879 669 880 670 /* Assume equally sized map definitions */ 881 - map_def_sz = data->d_size / nr_maps; 882 - if (!data->d_size || (data->d_size % nr_maps) != 0) { 883 - pr_warning("unable to determine map definition size " 884 - "section %s, %d maps in %zd bytes\n", 885 - obj->path, nr_maps, data->d_size); 886 - return -EINVAL; 671 + if (data) { 672 + map_def_sz = data->d_size / nr_maps; 673 + if (!data->d_size || (data->d_size % nr_maps) != 0) { 674 + pr_warning("unable to determine map definition size " 675 + "section %s, %d maps in %zd bytes\n", 676 + obj->path, nr_maps, data->d_size); 677 + return -EINVAL; 678 + } 887 679 } 888 680 681 + nr_maps += nr_maps_glob; 889 682 obj->maps = calloc(nr_maps, sizeof(obj->maps[0])); 890 683 if (!obj->maps) { 891 684 pr_warning("alloc maps for object failed\n"); ··· 908 697 /* 909 698 * Fill obj->maps using data in "maps" section. 910 699 */ 911 - for (i = 0, map_idx = 0; i < symbols->d_size / sizeof(GElf_Sym); i++) { 700 + for (i = 0, map_idx = 0; data && i < nr_syms; i++) { 912 701 GElf_Sym sym; 913 702 const char *map_name; 914 703 struct bpf_map_def *def; ··· 921 710 map_name = elf_strptr(obj->efile.elf, 922 711 obj->efile.strtabidx, 923 712 sym.st_name); 713 + 714 + obj->maps[map_idx].libbpf_type = LIBBPF_MAP_UNSPEC; 924 715 obj->maps[map_idx].offset = sym.st_value; 925 716 if (sym.st_value + map_def_sz > data->d_size) { 926 717 pr_warning("corrupted maps section in %s: last map \"%s\" too small\n", ··· 971 758 map_idx++; 972 759 } 973 760 974 - qsort(obj->maps, obj->nr_maps, sizeof(obj->maps[0]), compare_bpf_map); 975 - return 0; 761 + /* 762 + * Populate rest of obj->maps with libbpf internal maps. 763 + */ 764 + if (obj->efile.data_shndx >= 0) 765 + ret = bpf_object__init_internal_map(obj, &obj->maps[map_idx++], 766 + LIBBPF_MAP_DATA, 767 + obj->efile.data, 768 + &obj->sections.data); 769 + if (!ret && obj->efile.rodata_shndx >= 0) 770 + ret = bpf_object__init_internal_map(obj, &obj->maps[map_idx++], 771 + LIBBPF_MAP_RODATA, 772 + obj->efile.rodata, 773 + &obj->sections.rodata); 774 + if (!ret && obj->efile.bss_shndx >= 0) 775 + ret = bpf_object__init_internal_map(obj, &obj->maps[map_idx++], 776 + LIBBPF_MAP_BSS, 777 + obj->efile.bss, NULL); 778 + if (!ret) 779 + qsort(obj->maps, obj->nr_maps, sizeof(obj->maps[0]), 780 + compare_bpf_map); 781 + return ret; 976 782 } 977 783 978 784 static bool section_have_execinstr(struct bpf_object *obj, int idx) ··· 1017 785 Elf *elf = obj->efile.elf; 1018 786 GElf_Ehdr *ep = &obj->efile.ehdr; 1019 787 Elf_Data *btf_ext_data = NULL; 788 + Elf_Data *btf_data = NULL; 1020 789 Elf_Scn *scn = NULL; 1021 790 int idx = 0, err = 0; 1022 791 ··· 1061 828 (int)sh.sh_link, (unsigned long)sh.sh_flags, 1062 829 (int)sh.sh_type); 1063 830 1064 - if (strcmp(name, "license") == 0) 831 + if (strcmp(name, "license") == 0) { 1065 832 err = bpf_object__init_license(obj, 1066 833 data->d_buf, 1067 834 data->d_size); 1068 - else if (strcmp(name, "version") == 0) 835 + } else if (strcmp(name, "version") == 0) { 1069 836 err = bpf_object__init_kversion(obj, 1070 837 data->d_buf, 1071 838 data->d_size); 1072 - else if (strcmp(name, "maps") == 0) 839 + } else if (strcmp(name, "maps") == 0) { 1073 840 obj->efile.maps_shndx = idx; 1074 - else if (strcmp(name, BTF_ELF_SEC) == 0) { 1075 - obj->btf = btf__new(data->d_buf, data->d_size); 1076 - if (IS_ERR(obj->btf)) { 1077 - pr_warning("Error loading ELF section %s: %ld. Ignored and continue.\n", 1078 - BTF_ELF_SEC, PTR_ERR(obj->btf)); 1079 - obj->btf = NULL; 1080 - continue; 1081 - } 1082 - err = btf__load(obj->btf); 1083 - if (err) { 1084 - pr_warning("Error loading %s into kernel: %d. Ignored and continue.\n", 1085 - BTF_ELF_SEC, err); 1086 - btf__free(obj->btf); 1087 - obj->btf = NULL; 1088 - err = 0; 1089 - } 841 + } else if (strcmp(name, BTF_ELF_SEC) == 0) { 842 + btf_data = data; 1090 843 } else if (strcmp(name, BTF_EXT_ELF_SEC) == 0) { 1091 844 btf_ext_data = data; 1092 845 } else if (sh.sh_type == SHT_SYMTAB) { ··· 1084 865 obj->efile.symbols = data; 1085 866 obj->efile.strtabidx = sh.sh_link; 1086 867 } 1087 - } else if ((sh.sh_type == SHT_PROGBITS) && 1088 - (sh.sh_flags & SHF_EXECINSTR) && 1089 - (data->d_size > 0)) { 1090 - if (strcmp(name, ".text") == 0) 1091 - obj->efile.text_shndx = idx; 1092 - err = bpf_object__add_program(obj, data->d_buf, 1093 - data->d_size, name, idx); 1094 - if (err) { 1095 - char errmsg[STRERR_BUFSIZE]; 1096 - char *cp = libbpf_strerror_r(-err, errmsg, 1097 - sizeof(errmsg)); 868 + } else if (sh.sh_type == SHT_PROGBITS && data->d_size > 0) { 869 + if (sh.sh_flags & SHF_EXECINSTR) { 870 + if (strcmp(name, ".text") == 0) 871 + obj->efile.text_shndx = idx; 872 + err = bpf_object__add_program(obj, data->d_buf, 873 + data->d_size, name, idx); 874 + if (err) { 875 + char errmsg[STRERR_BUFSIZE]; 876 + char *cp = libbpf_strerror_r(-err, errmsg, 877 + sizeof(errmsg)); 1098 878 1099 - pr_warning("failed to alloc program %s (%s): %s", 1100 - name, obj->path, cp); 879 + pr_warning("failed to alloc program %s (%s): %s", 880 + name, obj->path, cp); 881 + } 882 + } else if (strcmp(name, ".data") == 0) { 883 + obj->efile.data = data; 884 + obj->efile.data_shndx = idx; 885 + } else if (strcmp(name, ".rodata") == 0) { 886 + obj->efile.rodata = data; 887 + obj->efile.rodata_shndx = idx; 888 + } else { 889 + pr_debug("skip section(%d) %s\n", idx, name); 1101 890 } 1102 891 } else if (sh.sh_type == SHT_REL) { 1103 892 void *reloc = obj->efile.reloc; ··· 1133 906 obj->efile.reloc[n].shdr = sh; 1134 907 obj->efile.reloc[n].data = data; 1135 908 } 909 + } else if (sh.sh_type == SHT_NOBITS && strcmp(name, ".bss") == 0) { 910 + obj->efile.bss = data; 911 + obj->efile.bss_shndx = idx; 1136 912 } else { 1137 913 pr_debug("skip section(%d) %s\n", idx, name); 1138 914 } ··· 1146 916 if (!obj->efile.strtabidx || obj->efile.strtabidx >= idx) { 1147 917 pr_warning("Corrupted ELF file: index of strtab invalid\n"); 1148 918 return LIBBPF_ERRNO__FORMAT; 919 + } 920 + if (btf_data) { 921 + obj->btf = btf__new(btf_data->d_buf, btf_data->d_size); 922 + if (IS_ERR(obj->btf)) { 923 + pr_warning("Error loading ELF section %s: %ld. Ignored and continue.\n", 924 + BTF_ELF_SEC, PTR_ERR(obj->btf)); 925 + obj->btf = NULL; 926 + } else { 927 + err = btf__finalize_data(obj, obj->btf); 928 + if (!err) 929 + err = btf__load(obj->btf); 930 + if (err) { 931 + pr_warning("Error finalizing and loading %s into kernel: %d. Ignored and continue.\n", 932 + BTF_ELF_SEC, err); 933 + btf__free(obj->btf); 934 + obj->btf = NULL; 935 + err = 0; 936 + } 937 + } 1149 938 } 1150 939 if (btf_ext_data) { 1151 940 if (!obj->btf) { ··· 1181 932 } 1182 933 } 1183 934 } 1184 - if (obj->efile.maps_shndx >= 0) { 935 + if (bpf_object__has_maps(obj)) { 1185 936 err = bpf_object__init_maps(obj, flags); 1186 937 if (err) 1187 938 goto out; ··· 1217 968 return NULL; 1218 969 } 1219 970 971 + static bool bpf_object__shndx_is_data(const struct bpf_object *obj, 972 + int shndx) 973 + { 974 + return shndx == obj->efile.data_shndx || 975 + shndx == obj->efile.bss_shndx || 976 + shndx == obj->efile.rodata_shndx; 977 + } 978 + 979 + static bool bpf_object__shndx_is_maps(const struct bpf_object *obj, 980 + int shndx) 981 + { 982 + return shndx == obj->efile.maps_shndx; 983 + } 984 + 985 + static bool bpf_object__relo_in_known_section(const struct bpf_object *obj, 986 + int shndx) 987 + { 988 + return shndx == obj->efile.text_shndx || 989 + bpf_object__shndx_is_maps(obj, shndx) || 990 + bpf_object__shndx_is_data(obj, shndx); 991 + } 992 + 993 + static enum libbpf_map_type 994 + bpf_object__section_to_libbpf_map_type(const struct bpf_object *obj, int shndx) 995 + { 996 + if (shndx == obj->efile.data_shndx) 997 + return LIBBPF_MAP_DATA; 998 + else if (shndx == obj->efile.bss_shndx) 999 + return LIBBPF_MAP_BSS; 1000 + else if (shndx == obj->efile.rodata_shndx) 1001 + return LIBBPF_MAP_RODATA; 1002 + else 1003 + return LIBBPF_MAP_UNSPEC; 1004 + } 1005 + 1220 1006 static int 1221 1007 bpf_program__collect_reloc(struct bpf_program *prog, GElf_Shdr *shdr, 1222 1008 Elf_Data *data, struct bpf_object *obj) 1223 1009 { 1224 1010 Elf_Data *symbols = obj->efile.symbols; 1225 - int text_shndx = obj->efile.text_shndx; 1226 - int maps_shndx = obj->efile.maps_shndx; 1227 1011 struct bpf_map *maps = obj->maps; 1228 1012 size_t nr_maps = obj->nr_maps; 1229 1013 int i, nrels; ··· 1276 994 GElf_Sym sym; 1277 995 GElf_Rel rel; 1278 996 unsigned int insn_idx; 997 + unsigned int shdr_idx; 1279 998 struct bpf_insn *insns = prog->insns; 999 + enum libbpf_map_type type; 1000 + const char *name; 1280 1001 size_t map_idx; 1281 1002 1282 1003 if (!gelf_getrel(data, i, &rel)) { ··· 1294 1009 GELF_R_SYM(rel.r_info)); 1295 1010 return -LIBBPF_ERRNO__FORMAT; 1296 1011 } 1297 - pr_debug("relo for %lld value %lld name %d\n", 1298 - (long long) (rel.r_info >> 32), 1299 - (long long) sym.st_value, sym.st_name); 1300 1012 1301 - if (sym.st_shndx != maps_shndx && sym.st_shndx != text_shndx) { 1302 - pr_warning("Program '%s' contains non-map related relo data pointing to section %u\n", 1303 - prog->section_name, sym.st_shndx); 1013 + name = elf_strptr(obj->efile.elf, obj->efile.strtabidx, 1014 + sym.st_name) ? : "<?>"; 1015 + 1016 + pr_debug("relo for %lld value %lld name %d (\'%s\')\n", 1017 + (long long) (rel.r_info >> 32), 1018 + (long long) sym.st_value, sym.st_name, name); 1019 + 1020 + shdr_idx = sym.st_shndx; 1021 + if (!bpf_object__relo_in_known_section(obj, shdr_idx)) { 1022 + pr_warning("Program '%s' contains unrecognized relo data pointing to section %u\n", 1023 + prog->section_name, shdr_idx); 1304 1024 return -LIBBPF_ERRNO__RELOC; 1305 1025 } 1306 1026 ··· 1330 1040 return -LIBBPF_ERRNO__RELOC; 1331 1041 } 1332 1042 1333 - /* TODO: 'maps' is sorted. We can use bsearch to make it faster. */ 1334 - for (map_idx = 0; map_idx < nr_maps; map_idx++) { 1335 - if (maps[map_idx].offset == sym.st_value) { 1336 - pr_debug("relocation: find map %zd (%s) for insn %u\n", 1337 - map_idx, maps[map_idx].name, insn_idx); 1338 - break; 1043 + if (bpf_object__shndx_is_maps(obj, shdr_idx) || 1044 + bpf_object__shndx_is_data(obj, shdr_idx)) { 1045 + type = bpf_object__section_to_libbpf_map_type(obj, shdr_idx); 1046 + if (type != LIBBPF_MAP_UNSPEC && 1047 + GELF_ST_BIND(sym.st_info) == STB_GLOBAL) { 1048 + pr_warning("bpf: relocation: not yet supported relo for non-static global \'%s\' variable found in insns[%d].code 0x%x\n", 1049 + name, insn_idx, insns[insn_idx].code); 1050 + return -LIBBPF_ERRNO__RELOC; 1339 1051 } 1340 - } 1341 1052 1342 - if (map_idx >= nr_maps) { 1343 - pr_warning("bpf relocation: map_idx %d large than %d\n", 1344 - (int)map_idx, (int)nr_maps - 1); 1345 - return -LIBBPF_ERRNO__RELOC; 1346 - } 1053 + for (map_idx = 0; map_idx < nr_maps; map_idx++) { 1054 + if (maps[map_idx].libbpf_type != type) 1055 + continue; 1056 + if (type != LIBBPF_MAP_UNSPEC || 1057 + (type == LIBBPF_MAP_UNSPEC && 1058 + maps[map_idx].offset == sym.st_value)) { 1059 + pr_debug("relocation: find map %zd (%s) for insn %u\n", 1060 + map_idx, maps[map_idx].name, insn_idx); 1061 + break; 1062 + } 1063 + } 1347 1064 1348 - prog->reloc_desc[i].type = RELO_LD64; 1349 - prog->reloc_desc[i].insn_idx = insn_idx; 1350 - prog->reloc_desc[i].map_idx = map_idx; 1065 + if (map_idx >= nr_maps) { 1066 + pr_warning("bpf relocation: map_idx %d large than %d\n", 1067 + (int)map_idx, (int)nr_maps - 1); 1068 + return -LIBBPF_ERRNO__RELOC; 1069 + } 1070 + 1071 + prog->reloc_desc[i].type = type != LIBBPF_MAP_UNSPEC ? 1072 + RELO_DATA : RELO_LD64; 1073 + prog->reloc_desc[i].insn_idx = insn_idx; 1074 + prog->reloc_desc[i].map_idx = map_idx; 1075 + } 1351 1076 } 1352 1077 return 0; 1353 1078 } ··· 1370 1065 static int bpf_map_find_btf_info(struct bpf_map *map, const struct btf *btf) 1371 1066 { 1372 1067 struct bpf_map_def *def = &map->def; 1373 - __u32 key_type_id, value_type_id; 1068 + __u32 key_type_id = 0, value_type_id = 0; 1374 1069 int ret; 1375 1070 1376 - ret = btf__get_map_kv_tids(btf, map->name, def->key_size, 1377 - def->value_size, &key_type_id, 1378 - &value_type_id); 1379 - if (ret) 1071 + if (!bpf_map__is_internal(map)) { 1072 + ret = btf__get_map_kv_tids(btf, map->name, def->key_size, 1073 + def->value_size, &key_type_id, 1074 + &value_type_id); 1075 + } else { 1076 + /* 1077 + * LLVM annotates global data differently in BTF, that is, 1078 + * only as '.data', '.bss' or '.rodata'. 1079 + */ 1080 + ret = btf__find_by_name(btf, 1081 + libbpf_type_to_btf_name[map->libbpf_type]); 1082 + } 1083 + if (ret < 0) 1380 1084 return ret; 1381 1085 1382 1086 map->btf_key_type_id = key_type_id; 1383 - map->btf_value_type_id = value_type_id; 1384 - 1087 + map->btf_value_type_id = bpf_map__is_internal(map) ? 1088 + ret : value_type_id; 1385 1089 return 0; 1386 1090 } 1387 1091 ··· 1502 1188 } 1503 1189 1504 1190 static int 1191 + bpf_object__populate_internal_map(struct bpf_object *obj, struct bpf_map *map) 1192 + { 1193 + char *cp, errmsg[STRERR_BUFSIZE]; 1194 + int err, zero = 0; 1195 + __u8 *data; 1196 + 1197 + /* Nothing to do here since kernel already zero-initializes .bss map. */ 1198 + if (map->libbpf_type == LIBBPF_MAP_BSS) 1199 + return 0; 1200 + 1201 + data = map->libbpf_type == LIBBPF_MAP_DATA ? 1202 + obj->sections.data : obj->sections.rodata; 1203 + 1204 + err = bpf_map_update_elem(map->fd, &zero, data, 0); 1205 + /* Freeze .rodata map as read-only from syscall side. */ 1206 + if (!err && map->libbpf_type == LIBBPF_MAP_RODATA) { 1207 + err = bpf_map_freeze(map->fd); 1208 + if (err) { 1209 + cp = libbpf_strerror_r(errno, errmsg, sizeof(errmsg)); 1210 + pr_warning("Error freezing map(%s) as read-only: %s\n", 1211 + map->name, cp); 1212 + err = 0; 1213 + } 1214 + } 1215 + return err; 1216 + } 1217 + 1218 + static int 1505 1219 bpf_object__create_maps(struct bpf_object *obj) 1506 1220 { 1507 1221 struct bpf_create_map_attr create_attr = {}; ··· 1586 1244 size_t j; 1587 1245 1588 1246 err = *pfd; 1247 + err_out: 1589 1248 cp = libbpf_strerror_r(errno, errmsg, sizeof(errmsg)); 1590 1249 pr_warning("failed to create map (name: '%s'): %s\n", 1591 1250 map->name, cp); ··· 1594 1251 zclose(obj->maps[j].fd); 1595 1252 return err; 1596 1253 } 1254 + 1255 + if (bpf_map__is_internal(map)) { 1256 + err = bpf_object__populate_internal_map(obj, map); 1257 + if (err < 0) { 1258 + zclose(*pfd); 1259 + goto err_out; 1260 + } 1261 + } 1262 + 1597 1263 pr_debug("create map %s: fd=%d\n", map->name, *pfd); 1598 1264 } 1599 1265 ··· 1757 1405 return 0; 1758 1406 1759 1407 for (i = 0; i < prog->nr_reloc; i++) { 1760 - if (prog->reloc_desc[i].type == RELO_LD64) { 1408 + if (prog->reloc_desc[i].type == RELO_LD64 || 1409 + prog->reloc_desc[i].type == RELO_DATA) { 1410 + bool relo_data = prog->reloc_desc[i].type == RELO_DATA; 1761 1411 struct bpf_insn *insns = prog->insns; 1762 1412 int insn_idx, map_idx; 1763 1413 1764 1414 insn_idx = prog->reloc_desc[i].insn_idx; 1765 1415 map_idx = prog->reloc_desc[i].map_idx; 1766 1416 1767 - if (insn_idx >= (int)prog->insns_cnt) { 1417 + if (insn_idx + 1 >= (int)prog->insns_cnt) { 1768 1418 pr_warning("relocation out of range: '%s'\n", 1769 1419 prog->section_name); 1770 1420 return -LIBBPF_ERRNO__RELOC; 1771 1421 } 1772 - insns[insn_idx].src_reg = BPF_PSEUDO_MAP_FD; 1422 + 1423 + if (!relo_data) { 1424 + insns[insn_idx].src_reg = BPF_PSEUDO_MAP_FD; 1425 + } else { 1426 + insns[insn_idx].src_reg = BPF_PSEUDO_MAP_VALUE; 1427 + insns[insn_idx + 1].imm = insns[insn_idx].imm; 1428 + } 1773 1429 insns[insn_idx].imm = obj->maps[map_idx].fd; 1774 - } else { 1430 + } else if (prog->reloc_desc[i].type == RELO_CALL) { 1775 1431 err = bpf_program__reloc_text(prog, obj, 1776 1432 &prog->reloc_desc[i]); 1777 1433 if (err) ··· 1854 1494 { 1855 1495 struct bpf_load_program_attr load_attr; 1856 1496 char *cp, errmsg[STRERR_BUFSIZE]; 1497 + int log_buf_size = BPF_LOG_BUF_SIZE; 1857 1498 char *log_buf; 1858 1499 int ret; 1859 1500 ··· 1875 1514 load_attr.line_info = prog->line_info; 1876 1515 load_attr.line_info_rec_size = prog->line_info_rec_size; 1877 1516 load_attr.line_info_cnt = prog->line_info_cnt; 1517 + load_attr.log_level = prog->log_level; 1878 1518 if (!load_attr.insns || !load_attr.insns_cnt) 1879 1519 return -EINVAL; 1880 1520 1881 - log_buf = malloc(BPF_LOG_BUF_SIZE); 1521 + retry_load: 1522 + log_buf = malloc(log_buf_size); 1882 1523 if (!log_buf) 1883 1524 pr_warning("Alloc log buffer for bpf loader error, continue without log\n"); 1884 1525 1885 - ret = bpf_load_program_xattr(&load_attr, log_buf, BPF_LOG_BUF_SIZE); 1526 + ret = bpf_load_program_xattr(&load_attr, log_buf, log_buf_size); 1886 1527 1887 1528 if (ret >= 0) { 1529 + if (load_attr.log_level) 1530 + pr_debug("verifier log:\n%s", log_buf); 1888 1531 *pfd = ret; 1889 1532 ret = 0; 1890 1533 goto out; 1891 1534 } 1892 1535 1536 + if (errno == ENOSPC) { 1537 + log_buf_size <<= 1; 1538 + free(log_buf); 1539 + goto retry_load; 1540 + } 1893 1541 ret = -LIBBPF_ERRNO__LOAD; 1894 1542 cp = libbpf_strerror_r(errno, errmsg, sizeof(errmsg)); 1895 1543 pr_warning("load bpf program failed: %s\n", cp); ··· 2673 2303 obj->maps[i].priv = NULL; 2674 2304 obj->maps[i].clear_priv = NULL; 2675 2305 } 2306 + 2307 + zfree(&obj->sections.rodata); 2308 + zfree(&obj->sections.data); 2676 2309 zfree(&obj->maps); 2677 2310 obj->nr_maps = 0; 2678 2311 ··· 3153 2780 return map->def.type == BPF_MAP_TYPE_PERF_EVENT_ARRAY; 3154 2781 } 3155 2782 2783 + bool bpf_map__is_internal(struct bpf_map *map) 2784 + { 2785 + return map->libbpf_type != LIBBPF_MAP_UNSPEC; 2786 + } 2787 + 3156 2788 void bpf_map__set_ifindex(struct bpf_map *map, __u32 ifindex) 3157 2789 { 3158 2790 map->map_ifindex = ifindex; ··· 3316 2938 bpf_program__set_expected_attach_type(prog, 3317 2939 expected_attach_type); 3318 2940 2941 + prog->log_level = attr->log_level; 3319 2942 if (!first_prog) 3320 2943 first_prog = prog; 3321 2944 }
+6
tools/lib/bpf/libbpf.h
··· 75 75 LIBBPF_API struct bpf_object *bpf_object__open_buffer(void *obj_buf, 76 76 size_t obj_buf_sz, 77 77 const char *name); 78 + int bpf_object__section_size(const struct bpf_object *obj, const char *name, 79 + __u32 *size); 80 + int bpf_object__variable_offset(const struct bpf_object *obj, const char *name, 81 + __u32 *off); 78 82 LIBBPF_API int bpf_object__pin_maps(struct bpf_object *obj, const char *path); 79 83 LIBBPF_API int bpf_object__unpin_maps(struct bpf_object *obj, 80 84 const char *path); ··· 305 301 LIBBPF_API int bpf_map__reuse_fd(struct bpf_map *map, int fd); 306 302 LIBBPF_API int bpf_map__resize(struct bpf_map *map, __u32 max_entries); 307 303 LIBBPF_API bool bpf_map__is_offload_neutral(struct bpf_map *map); 304 + LIBBPF_API bool bpf_map__is_internal(struct bpf_map *map); 308 305 LIBBPF_API void bpf_map__set_ifindex(struct bpf_map *map, __u32 ifindex); 309 306 LIBBPF_API int bpf_map__pin(struct bpf_map *map, const char *path); 310 307 LIBBPF_API int bpf_map__unpin(struct bpf_map *map, const char *path); ··· 319 314 enum bpf_prog_type prog_type; 320 315 enum bpf_attach_type expected_attach_type; 321 316 int ifindex; 317 + int log_level; 322 318 }; 323 319 324 320 LIBBPF_API int bpf_prog_load_xattr(const struct bpf_prog_load_attr *attr,
+7
tools/lib/bpf/libbpf.map
··· 157 157 bpf_program__bpil_addr_to_offs; 158 158 bpf_program__bpil_offs_to_addr; 159 159 } LIBBPF_0.0.1; 160 + 161 + LIBBPF_0.0.3 { 162 + global: 163 + bpf_map__is_internal; 164 + bpf_map_freeze; 165 + btf__finalize_data; 166 + } LIBBPF_0.0.2;
+12
tools/lib/bpf/libbpf.pc.template
··· 1 + # SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) 2 + 3 + prefix=@PREFIX@ 4 + libdir=@LIBDIR@ 5 + includedir=${prefix}/include 6 + 7 + Name: libbpf 8 + Description: BPF library 9 + Version: @VERSION@ 10 + Libs: -L${libdir} -lbpf 11 + Requires.private: libelf 12 + Cflags: -I${includedir}
+5 -4
tools/lib/bpf/xsk.c
··· 259 259 260 260 static int xsk_load_xdp_prog(struct xsk_socket *xsk) 261 261 { 262 - char bpf_log_buf[BPF_LOG_BUF_SIZE]; 262 + static const int log_buf_size = 16 * 1024; 263 + char log_buf[log_buf_size]; 263 264 int err, prog_fd; 264 265 265 266 /* This is the C-program: ··· 309 308 size_t insns_cnt = sizeof(prog) / sizeof(struct bpf_insn); 310 309 311 310 prog_fd = bpf_load_program(BPF_PROG_TYPE_XDP, prog, insns_cnt, 312 - "LGPL-2.1 or BSD-2-Clause", 0, bpf_log_buf, 313 - BPF_LOG_BUF_SIZE); 311 + "LGPL-2.1 or BSD-2-Clause", 0, log_buf, 312 + log_buf_size); 314 313 if (prog_fd < 0) { 315 - pr_warning("BPF log buffer:\n%s", bpf_log_buf); 314 + pr_warning("BPF log buffer:\n%s", log_buf); 316 315 return prog_fd; 317 316 } 318 317
+2 -2
tools/testing/selftests/bpf/Makefile
··· 209 209 endif 210 210 211 211 PROG_TESTS_H := $(OUTPUT)/prog_tests/tests.h 212 - $(OUTPUT)/test_progs: $(PROG_TESTS_H) 212 + test_progs.c: $(PROG_TESTS_H) 213 213 $(OUTPUT)/test_progs: CFLAGS += $(TEST_PROGS_CFLAGS) 214 214 $(OUTPUT)/test_progs: prog_tests/*.c 215 215 ··· 232 232 ) > $(PROG_TESTS_H)) 233 233 234 234 VERIFIER_TESTS_H := $(OUTPUT)/verifier/tests.h 235 - $(OUTPUT)/test_verifier: $(VERIFIER_TESTS_H) 235 + test_verifier.c: $(VERIFIER_TESTS_H) 236 236 $(OUTPUT)/test_verifier: CFLAGS += $(TEST_VERIFIER_CFLAGS) 237 237 238 238 VERIFIER_TESTS_DIR = $(OUTPUT)/verifier
+4 -4
tools/testing/selftests/bpf/bpf_helpers.h
··· 9 9 #define SEC(NAME) __attribute__((section(NAME), used)) 10 10 11 11 /* helper functions called from eBPF programs written in C */ 12 - static void *(*bpf_map_lookup_elem)(void *map, void *key) = 12 + static void *(*bpf_map_lookup_elem)(void *map, const void *key) = 13 13 (void *) BPF_FUNC_map_lookup_elem; 14 - static int (*bpf_map_update_elem)(void *map, void *key, void *value, 14 + static int (*bpf_map_update_elem)(void *map, const void *key, const void *value, 15 15 unsigned long long flags) = 16 16 (void *) BPF_FUNC_map_update_elem; 17 - static int (*bpf_map_delete_elem)(void *map, void *key) = 17 + static int (*bpf_map_delete_elem)(void *map, const void *key) = 18 18 (void *) BPF_FUNC_map_delete_elem; 19 - static int (*bpf_map_push_elem)(void *map, void *value, 19 + static int (*bpf_map_push_elem)(void *map, const void *value, 20 20 unsigned long long flags) = 21 21 (void *) BPF_FUNC_map_push_elem; 22 22 static int (*bpf_map_pop_elem)(void *map, void *value) =
+8
tools/testing/selftests/bpf/config
··· 25 25 CONFIG_FTRACE_SYSCALLS=y 26 26 CONFIG_IPV6_TUNNEL=y 27 27 CONFIG_IPV6_GRE=y 28 + CONFIG_NET_FOU=m 29 + CONFIG_NET_FOU_IP_TUNNELS=y 30 + CONFIG_IPV6_FOU=m 31 + CONFIG_IPV6_FOU_TUNNEL=m 32 + CONFIG_MPLS=y 33 + CONFIG_NET_MPLS_GSO=m 34 + CONFIG_MPLS_ROUTING=m 35 + CONFIG_MPLS_IPTUNNEL=m
+1 -1
tools/testing/selftests/bpf/flow_dissector_load.c
··· 52 52 sprintf(command, "rm -r %s", cfg_pin_path); 53 53 ret = system(command); 54 54 if (ret) 55 - error(1, errno, command); 55 + error(1, errno, "%s", command); 56 56 } 57 57 58 58 static void parse_opts(int argc, char **argv)
+4 -4
tools/testing/selftests/bpf/prog_tests/bpf_obj_id.c
··· 73 73 info_len != sizeof(struct bpf_map_info) || 74 74 strcmp((char *)map_infos[i].name, expected_map_name), 75 75 "get-map-info(fd)", 76 - "err %d errno %d type %d(%d) info_len %u(%Zu) key_size %u value_size %u max_entries %u map_flags %X name %s(%s)\n", 76 + "err %d errno %d type %d(%d) info_len %u(%zu) key_size %u value_size %u max_entries %u map_flags %X name %s(%s)\n", 77 77 err, errno, 78 78 map_infos[i].type, BPF_MAP_TYPE_ARRAY, 79 79 info_len, sizeof(struct bpf_map_info), ··· 117 117 *(int *)(long)prog_infos[i].map_ids != map_infos[i].id || 118 118 strcmp((char *)prog_infos[i].name, expected_prog_name), 119 119 "get-prog-info(fd)", 120 - "err %d errno %d i %d type %d(%d) info_len %u(%Zu) jit_enabled %d jited_prog_len %u xlated_prog_len %u jited_prog %d xlated_prog %d load_time %lu(%lu) uid %u(%u) nr_map_ids %u(%u) map_id %u(%u) name %s(%s)\n", 120 + "err %d errno %d i %d type %d(%d) info_len %u(%zu) jit_enabled %d jited_prog_len %u xlated_prog_len %u jited_prog %d xlated_prog %d load_time %lu(%lu) uid %u(%u) nr_map_ids %u(%u) map_id %u(%u) name %s(%s)\n", 121 121 err, errno, i, 122 122 prog_infos[i].type, BPF_PROG_TYPE_SOCKET_FILTER, 123 123 info_len, sizeof(struct bpf_prog_info), ··· 185 185 memcmp(&prog_info, &prog_infos[i], info_len) || 186 186 *(int *)(long)prog_info.map_ids != saved_map_id, 187 187 "get-prog-info(next_id->fd)", 188 - "err %d errno %d info_len %u(%Zu) memcmp %d map_id %u(%u)\n", 188 + "err %d errno %d info_len %u(%zu) memcmp %d map_id %u(%u)\n", 189 189 err, errno, info_len, sizeof(struct bpf_prog_info), 190 190 memcmp(&prog_info, &prog_infos[i], info_len), 191 191 *(int *)(long)prog_info.map_ids, saved_map_id); ··· 231 231 memcmp(&map_info, &map_infos[i], info_len) || 232 232 array_value != array_magic_value, 233 233 "check get-map-info(next_id->fd)", 234 - "err %d errno %d info_len %u(%Zu) memcmp %d array_value %llu(%llu)\n", 234 + "err %d errno %d info_len %u(%zu) memcmp %d array_value %llu(%llu)\n", 235 235 err, errno, info_len, sizeof(struct bpf_map_info), 236 236 memcmp(&map_info, &map_infos[i], info_len), 237 237 array_value, array_magic_value);
+49
tools/testing/selftests/bpf/prog_tests/bpf_verif_scale.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Copyright (c) 2019 Facebook 3 + #include <test_progs.h> 4 + static int libbpf_debug_print(enum libbpf_print_level level, 5 + const char *format, va_list args) 6 + { 7 + if (level != LIBBPF_DEBUG) 8 + return 0; 9 + 10 + if (!strstr(format, "verifier log")) 11 + return 0; 12 + return vfprintf(stderr, "%s", args); 13 + } 14 + 15 + static int check_load(const char *file) 16 + { 17 + struct bpf_prog_load_attr attr; 18 + struct bpf_object *obj; 19 + int err, prog_fd; 20 + 21 + memset(&attr, 0, sizeof(struct bpf_prog_load_attr)); 22 + attr.file = file; 23 + attr.prog_type = BPF_PROG_TYPE_SCHED_CLS; 24 + attr.log_level = 4; 25 + err = bpf_prog_load_xattr(&attr, &obj, &prog_fd); 26 + bpf_object__close(obj); 27 + if (err) 28 + error_cnt++; 29 + return err; 30 + } 31 + 32 + void test_bpf_verif_scale(void) 33 + { 34 + const char *file1 = "./test_verif_scale1.o"; 35 + const char *file2 = "./test_verif_scale2.o"; 36 + const char *file3 = "./test_verif_scale3.o"; 37 + int err; 38 + 39 + if (verifier_stats) 40 + libbpf_set_print(libbpf_debug_print); 41 + 42 + err = check_load(file1); 43 + err |= check_load(file2); 44 + err |= check_load(file3); 45 + if (!err) 46 + printf("test_verif_scale:OK\n"); 47 + else 48 + printf("test_verif_scale:FAIL\n"); 49 + }
+2 -2
tools/testing/selftests/bpf/prog_tests/get_stack_raw_tp.c
··· 39 39 } else { 40 40 for (i = 0; i < num_stack; i++) { 41 41 ks = ksym_search(raw_data[i]); 42 - if (strcmp(ks->name, nonjit_func) == 0) { 42 + if (ks && (strcmp(ks->name, nonjit_func) == 0)) { 43 43 found = true; 44 44 break; 45 45 } ··· 56 56 } else { 57 57 for (i = 0; i < num_stack; i++) { 58 58 ks = ksym_search(e->kern_stack[i]); 59 - if (strcmp(ks->name, nonjit_func) == 0) { 59 + if (ks && (strcmp(ks->name, nonjit_func) == 0)) { 60 60 good_kern_stack = true; 61 61 break; 62 62 }
+157
tools/testing/selftests/bpf/prog_tests/global_data.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + #include <test_progs.h> 3 + 4 + static void test_global_data_number(struct bpf_object *obj, __u32 duration) 5 + { 6 + int i, err, map_fd; 7 + uint64_t num; 8 + 9 + map_fd = bpf_find_map(__func__, obj, "result_number"); 10 + if (map_fd < 0) { 11 + error_cnt++; 12 + return; 13 + } 14 + 15 + struct { 16 + char *name; 17 + uint32_t key; 18 + uint64_t num; 19 + } tests[] = { 20 + { "relocate .bss reference", 0, 0 }, 21 + { "relocate .data reference", 1, 42 }, 22 + { "relocate .rodata reference", 2, 24 }, 23 + { "relocate .bss reference", 3, 0 }, 24 + { "relocate .data reference", 4, 0xffeeff }, 25 + { "relocate .rodata reference", 5, 0xabab }, 26 + { "relocate .bss reference", 6, 1234 }, 27 + { "relocate .bss reference", 7, 0 }, 28 + { "relocate .rodata reference", 8, 0xab }, 29 + { "relocate .rodata reference", 9, 0x1111111111111111 }, 30 + { "relocate .rodata reference", 10, ~0 }, 31 + }; 32 + 33 + for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { 34 + err = bpf_map_lookup_elem(map_fd, &tests[i].key, &num); 35 + CHECK(err || num != tests[i].num, tests[i].name, 36 + "err %d result %lx expected %lx\n", 37 + err, num, tests[i].num); 38 + } 39 + } 40 + 41 + static void test_global_data_string(struct bpf_object *obj, __u32 duration) 42 + { 43 + int i, err, map_fd; 44 + char str[32]; 45 + 46 + map_fd = bpf_find_map(__func__, obj, "result_string"); 47 + if (map_fd < 0) { 48 + error_cnt++; 49 + return; 50 + } 51 + 52 + struct { 53 + char *name; 54 + uint32_t key; 55 + char str[32]; 56 + } tests[] = { 57 + { "relocate .rodata reference", 0, "abcdefghijklmnopqrstuvwxyz" }, 58 + { "relocate .data reference", 1, "abcdefghijklmnopqrstuvwxyz" }, 59 + { "relocate .bss reference", 2, "" }, 60 + { "relocate .data reference", 3, "abcdexghijklmnopqrstuvwxyz" }, 61 + { "relocate .bss reference", 4, "\0\0hello" }, 62 + }; 63 + 64 + for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { 65 + err = bpf_map_lookup_elem(map_fd, &tests[i].key, str); 66 + CHECK(err || memcmp(str, tests[i].str, sizeof(str)), 67 + tests[i].name, "err %d result \'%s\' expected \'%s\'\n", 68 + err, str, tests[i].str); 69 + } 70 + } 71 + 72 + struct foo { 73 + __u8 a; 74 + __u32 b; 75 + __u64 c; 76 + }; 77 + 78 + static void test_global_data_struct(struct bpf_object *obj, __u32 duration) 79 + { 80 + int i, err, map_fd; 81 + struct foo val; 82 + 83 + map_fd = bpf_find_map(__func__, obj, "result_struct"); 84 + if (map_fd < 0) { 85 + error_cnt++; 86 + return; 87 + } 88 + 89 + struct { 90 + char *name; 91 + uint32_t key; 92 + struct foo val; 93 + } tests[] = { 94 + { "relocate .rodata reference", 0, { 42, 0xfefeefef, 0x1111111111111111ULL, } }, 95 + { "relocate .bss reference", 1, { } }, 96 + { "relocate .rodata reference", 2, { } }, 97 + { "relocate .data reference", 3, { 41, 0xeeeeefef, 0x2111111111111111ULL, } }, 98 + }; 99 + 100 + for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { 101 + err = bpf_map_lookup_elem(map_fd, &tests[i].key, &val); 102 + CHECK(err || memcmp(&val, &tests[i].val, sizeof(val)), 103 + tests[i].name, "err %d result { %u, %u, %llu } expected { %u, %u, %llu }\n", 104 + err, val.a, val.b, val.c, tests[i].val.a, tests[i].val.b, tests[i].val.c); 105 + } 106 + } 107 + 108 + static void test_global_data_rdonly(struct bpf_object *obj, __u32 duration) 109 + { 110 + int err = -ENOMEM, map_fd, zero = 0; 111 + struct bpf_map *map; 112 + __u8 *buff; 113 + 114 + map = bpf_object__find_map_by_name(obj, "test_glo.rodata"); 115 + if (!map || !bpf_map__is_internal(map)) { 116 + error_cnt++; 117 + return; 118 + } 119 + 120 + map_fd = bpf_map__fd(map); 121 + if (map_fd < 0) { 122 + error_cnt++; 123 + return; 124 + } 125 + 126 + buff = malloc(bpf_map__def(map)->value_size); 127 + if (buff) 128 + err = bpf_map_update_elem(map_fd, &zero, buff, 0); 129 + free(buff); 130 + CHECK(!err || errno != EPERM, "test .rodata read-only map", 131 + "err %d errno %d\n", err, errno); 132 + } 133 + 134 + void test_global_data(void) 135 + { 136 + const char *file = "./test_global_data.o"; 137 + __u32 duration = 0, retval; 138 + struct bpf_object *obj; 139 + int err, prog_fd; 140 + 141 + err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd); 142 + if (CHECK(err, "load program", "error %d loading %s\n", err, file)) 143 + return; 144 + 145 + err = bpf_prog_test_run(prog_fd, 1, &pkt_v4, sizeof(pkt_v4), 146 + NULL, NULL, &retval, &duration); 147 + CHECK(err || retval, "pass global data run", 148 + "err %d errno %d retval %d duration %d\n", 149 + err, errno, retval, duration); 150 + 151 + test_global_data_number(obj, duration); 152 + test_global_data_string(obj, duration); 153 + test_global_data_struct(obj, duration); 154 + test_global_data_rdonly(obj, duration); 155 + 156 + bpf_object__close(obj); 157 + }
+89
tools/testing/selftests/bpf/prog_tests/skb_ctx.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + #include <test_progs.h> 3 + 4 + void test_skb_ctx(void) 5 + { 6 + struct __sk_buff skb = { 7 + .cb[0] = 1, 8 + .cb[1] = 2, 9 + .cb[2] = 3, 10 + .cb[3] = 4, 11 + .cb[4] = 5, 12 + .priority = 6, 13 + }; 14 + struct bpf_prog_test_run_attr tattr = { 15 + .data_in = &pkt_v4, 16 + .data_size_in = sizeof(pkt_v4), 17 + .ctx_in = &skb, 18 + .ctx_size_in = sizeof(skb), 19 + .ctx_out = &skb, 20 + .ctx_size_out = sizeof(skb), 21 + }; 22 + struct bpf_object *obj; 23 + int err; 24 + int i; 25 + 26 + err = bpf_prog_load("./test_skb_ctx.o", BPF_PROG_TYPE_SCHED_CLS, &obj, 27 + &tattr.prog_fd); 28 + if (CHECK_ATTR(err, "load", "err %d errno %d\n", err, errno)) 29 + return; 30 + 31 + /* ctx_in != NULL, ctx_size_in == 0 */ 32 + 33 + tattr.ctx_size_in = 0; 34 + err = bpf_prog_test_run_xattr(&tattr); 35 + CHECK_ATTR(err == 0, "ctx_size_in", "err %d errno %d\n", err, errno); 36 + tattr.ctx_size_in = sizeof(skb); 37 + 38 + /* ctx_out != NULL, ctx_size_out == 0 */ 39 + 40 + tattr.ctx_size_out = 0; 41 + err = bpf_prog_test_run_xattr(&tattr); 42 + CHECK_ATTR(err == 0, "ctx_size_out", "err %d errno %d\n", err, errno); 43 + tattr.ctx_size_out = sizeof(skb); 44 + 45 + /* non-zero [len, tc_index] fields should be rejected*/ 46 + 47 + skb.len = 1; 48 + err = bpf_prog_test_run_xattr(&tattr); 49 + CHECK_ATTR(err == 0, "len", "err %d errno %d\n", err, errno); 50 + skb.len = 0; 51 + 52 + skb.tc_index = 1; 53 + err = bpf_prog_test_run_xattr(&tattr); 54 + CHECK_ATTR(err == 0, "tc_index", "err %d errno %d\n", err, errno); 55 + skb.tc_index = 0; 56 + 57 + /* non-zero [hash, sk] fields should be rejected */ 58 + 59 + skb.hash = 1; 60 + err = bpf_prog_test_run_xattr(&tattr); 61 + CHECK_ATTR(err == 0, "hash", "err %d errno %d\n", err, errno); 62 + skb.hash = 0; 63 + 64 + skb.sk = (struct bpf_sock *)1; 65 + err = bpf_prog_test_run_xattr(&tattr); 66 + CHECK_ATTR(err == 0, "sk", "err %d errno %d\n", err, errno); 67 + skb.sk = 0; 68 + 69 + err = bpf_prog_test_run_xattr(&tattr); 70 + CHECK_ATTR(err != 0 || tattr.retval, 71 + "run", 72 + "err %d errno %d retval %d\n", 73 + err, errno, tattr.retval); 74 + 75 + CHECK_ATTR(tattr.ctx_size_out != sizeof(skb), 76 + "ctx_size_out", 77 + "incorrect output size, want %lu have %u\n", 78 + sizeof(skb), tattr.ctx_size_out); 79 + 80 + for (i = 0; i < 5; i++) 81 + CHECK_ATTR(skb.cb[i] != i + 2, 82 + "ctx_out_cb", 83 + "skb->cb[i] == %d, expected %d\n", 84 + skb.cb[i], i + 2); 85 + CHECK_ATTR(skb.priority != 7, 86 + "ctx_out_priority", 87 + "skb->priority == %d, expected %d\n", 88 + skb.priority, 7); 89 + }
+106
tools/testing/selftests/bpf/progs/test_global_data.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Copyright (c) 2019 Isovalent, Inc. 3 + 4 + #include <linux/bpf.h> 5 + #include <linux/pkt_cls.h> 6 + #include <string.h> 7 + 8 + #include "bpf_helpers.h" 9 + 10 + struct bpf_map_def SEC("maps") result_number = { 11 + .type = BPF_MAP_TYPE_ARRAY, 12 + .key_size = sizeof(__u32), 13 + .value_size = sizeof(__u64), 14 + .max_entries = 11, 15 + }; 16 + 17 + struct bpf_map_def SEC("maps") result_string = { 18 + .type = BPF_MAP_TYPE_ARRAY, 19 + .key_size = sizeof(__u32), 20 + .value_size = 32, 21 + .max_entries = 5, 22 + }; 23 + 24 + struct foo { 25 + __u8 a; 26 + __u32 b; 27 + __u64 c; 28 + }; 29 + 30 + struct bpf_map_def SEC("maps") result_struct = { 31 + .type = BPF_MAP_TYPE_ARRAY, 32 + .key_size = sizeof(__u32), 33 + .value_size = sizeof(struct foo), 34 + .max_entries = 5, 35 + }; 36 + 37 + /* Relocation tests for __u64s. */ 38 + static __u64 num0; 39 + static __u64 num1 = 42; 40 + static const __u64 num2 = 24; 41 + static __u64 num3 = 0; 42 + static __u64 num4 = 0xffeeff; 43 + static const __u64 num5 = 0xabab; 44 + static const __u64 num6 = 0xab; 45 + 46 + /* Relocation tests for strings. */ 47 + static const char str0[32] = "abcdefghijklmnopqrstuvwxyz"; 48 + static char str1[32] = "abcdefghijklmnopqrstuvwxyz"; 49 + static char str2[32]; 50 + 51 + /* Relocation tests for structs. */ 52 + static const struct foo struct0 = { 53 + .a = 42, 54 + .b = 0xfefeefef, 55 + .c = 0x1111111111111111ULL, 56 + }; 57 + static struct foo struct1; 58 + static const struct foo struct2; 59 + static struct foo struct3 = { 60 + .a = 41, 61 + .b = 0xeeeeefef, 62 + .c = 0x2111111111111111ULL, 63 + }; 64 + 65 + #define test_reloc(map, num, var) \ 66 + do { \ 67 + __u32 key = num; \ 68 + bpf_map_update_elem(&result_##map, &key, var, 0); \ 69 + } while (0) 70 + 71 + SEC("static_data_load") 72 + int load_static_data(struct __sk_buff *skb) 73 + { 74 + static const __u64 bar = ~0; 75 + 76 + test_reloc(number, 0, &num0); 77 + test_reloc(number, 1, &num1); 78 + test_reloc(number, 2, &num2); 79 + test_reloc(number, 3, &num3); 80 + test_reloc(number, 4, &num4); 81 + test_reloc(number, 5, &num5); 82 + num4 = 1234; 83 + test_reloc(number, 6, &num4); 84 + test_reloc(number, 7, &num0); 85 + test_reloc(number, 8, &num6); 86 + 87 + test_reloc(string, 0, str0); 88 + test_reloc(string, 1, str1); 89 + test_reloc(string, 2, str2); 90 + str1[5] = 'x'; 91 + test_reloc(string, 3, str1); 92 + __builtin_memcpy(&str2[2], "hello", sizeof("hello")); 93 + test_reloc(string, 4, str2); 94 + 95 + test_reloc(struct, 0, &struct0); 96 + test_reloc(struct, 1, &struct1); 97 + test_reloc(struct, 2, &struct2); 98 + test_reloc(struct, 3, &struct3); 99 + 100 + test_reloc(number, 9, &struct0.c); 101 + test_reloc(number, 10, &bar); 102 + 103 + return TC_ACT_OK; 104 + } 105 + 106 + char _license[] SEC("license") = "GPL";
+70
tools/testing/selftests/bpf/progs/test_jhash.h
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Copyright (c) 2019 Facebook 3 + 4 + typedef unsigned int u32; 5 + 6 + static __attribute__((always_inline)) u32 rol32(u32 word, unsigned int shift) 7 + { 8 + return (word << shift) | (word >> ((-shift) & 31)); 9 + } 10 + 11 + #define __jhash_mix(a, b, c) \ 12 + { \ 13 + a -= c; a ^= rol32(c, 4); c += b; \ 14 + b -= a; b ^= rol32(a, 6); a += c; \ 15 + c -= b; c ^= rol32(b, 8); b += a; \ 16 + a -= c; a ^= rol32(c, 16); c += b; \ 17 + b -= a; b ^= rol32(a, 19); a += c; \ 18 + c -= b; c ^= rol32(b, 4); b += a; \ 19 + } 20 + 21 + #define __jhash_final(a, b, c) \ 22 + { \ 23 + c ^= b; c -= rol32(b, 14); \ 24 + a ^= c; a -= rol32(c, 11); \ 25 + b ^= a; b -= rol32(a, 25); \ 26 + c ^= b; c -= rol32(b, 16); \ 27 + a ^= c; a -= rol32(c, 4); \ 28 + b ^= a; b -= rol32(a, 14); \ 29 + c ^= b; c -= rol32(b, 24); \ 30 + } 31 + 32 + #define JHASH_INITVAL 0xdeadbeef 33 + 34 + static ATTR 35 + u32 jhash(const void *key, u32 length, u32 initval) 36 + { 37 + u32 a, b, c; 38 + const unsigned char *k = key; 39 + 40 + a = b = c = JHASH_INITVAL + length + initval; 41 + 42 + while (length > 12) { 43 + a += *(volatile u32 *)(k); 44 + b += *(volatile u32 *)(k + 4); 45 + c += *(volatile u32 *)(k + 8); 46 + __jhash_mix(a, b, c); 47 + length -= 12; 48 + k += 12; 49 + } 50 + switch (length) { 51 + case 12: c += (u32)k[11]<<24; 52 + case 11: c += (u32)k[10]<<16; 53 + case 10: c += (u32)k[9]<<8; 54 + case 9: c += k[8]; 55 + case 8: b += (u32)k[7]<<24; 56 + case 7: b += (u32)k[6]<<16; 57 + case 6: b += (u32)k[5]<<8; 58 + case 5: b += k[4]; 59 + case 4: a += (u32)k[3]<<24; 60 + case 3: a += (u32)k[2]<<16; 61 + case 2: a += (u32)k[1]<<8; 62 + case 1: a += k[0]; 63 + c ^= a; 64 + __jhash_final(a, b, c); 65 + case 0: /* Nothing left to add */ 66 + break; 67 + } 68 + 69 + return c; 70 + }
+21
tools/testing/selftests/bpf/progs/test_skb_ctx.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + #include <linux/bpf.h> 4 + #include "bpf_helpers.h" 5 + 6 + int _version SEC("version") = 1; 7 + char _license[] SEC("license") = "GPL"; 8 + 9 + SEC("skb_ctx") 10 + int process(struct __sk_buff *skb) 11 + { 12 + #pragma clang loop unroll(full) 13 + for (int i = 0; i < 5; i++) { 14 + if (skb->cb[i] != i + 1) 15 + return 1; 16 + skb->cb[i]++; 17 + } 18 + skb->priority++; 19 + 20 + return 0; 21 + }
+272 -53
tools/testing/selftests/bpf/progs/test_tc_tunnel.c
··· 11 11 #include <linux/in.h> 12 12 #include <linux/ip.h> 13 13 #include <linux/ipv6.h> 14 + #include <linux/mpls.h> 14 15 #include <linux/tcp.h> 16 + #include <linux/udp.h> 15 17 #include <linux/pkt_cls.h> 16 18 #include <linux/types.h> 17 19 ··· 22 20 23 21 static const int cfg_port = 8000; 24 22 25 - struct grev4hdr { 26 - struct iphdr ip; 23 + static const int cfg_udp_src = 20000; 24 + 25 + #define UDP_PORT 5555 26 + #define MPLS_OVER_UDP_PORT 6635 27 + #define ETH_OVER_UDP_PORT 7777 28 + 29 + /* MPLS label 1000 with S bit (last label) set and ttl of 255. */ 30 + static const __u32 mpls_label = __bpf_constant_htonl(1000 << 12 | 31 + MPLS_LS_S_MASK | 0xff); 32 + 33 + struct gre_hdr { 27 34 __be16 flags; 28 35 __be16 protocol; 29 36 } __attribute__((packed)); 30 37 31 - struct grev6hdr { 38 + union l4hdr { 39 + struct udphdr udp; 40 + struct gre_hdr gre; 41 + }; 42 + 43 + struct v4hdr { 44 + struct iphdr ip; 45 + union l4hdr l4hdr; 46 + __u8 pad[16]; /* enough space for L2 header */ 47 + } __attribute__((packed)); 48 + 49 + struct v6hdr { 32 50 struct ipv6hdr ip; 33 - __be16 flags; 34 - __be16 protocol; 51 + union l4hdr l4hdr; 52 + __u8 pad[16]; /* enough space for L2 header */ 35 53 } __attribute__((packed)); 36 54 37 55 static __always_inline void set_ipv4_csum(struct iphdr *iph) ··· 69 47 iph->check = ~((csum & 0xffff) + (csum >> 16)); 70 48 } 71 49 72 - static __always_inline int encap_ipv4(struct __sk_buff *skb, bool with_gre) 50 + static __always_inline int encap_ipv4(struct __sk_buff *skb, __u8 encap_proto, 51 + __u16 l2_proto) 73 52 { 74 - struct grev4hdr h_outer; 53 + __u16 udp_dst = UDP_PORT; 75 54 struct iphdr iph_inner; 55 + struct v4hdr h_outer; 76 56 struct tcphdr tcph; 57 + int olen, l2_len; 77 58 __u64 flags; 78 - int olen; 79 59 80 60 if (bpf_skb_load_bytes(skb, ETH_HLEN, &iph_inner, 81 61 sizeof(iph_inner)) < 0) ··· 94 70 if (tcph.dest != __bpf_constant_htons(cfg_port)) 95 71 return TC_ACT_OK; 96 72 73 + olen = sizeof(h_outer.ip); 74 + l2_len = 0; 75 + 97 76 flags = BPF_F_ADJ_ROOM_FIXED_GSO | BPF_F_ADJ_ROOM_ENCAP_L3_IPV4; 98 - if (with_gre) { 99 - flags |= BPF_F_ADJ_ROOM_ENCAP_L4_GRE; 100 - olen = sizeof(h_outer); 101 - } else { 102 - olen = sizeof(h_outer.ip); 77 + 78 + switch (l2_proto) { 79 + case ETH_P_MPLS_UC: 80 + l2_len = sizeof(mpls_label); 81 + udp_dst = MPLS_OVER_UDP_PORT; 82 + break; 83 + case ETH_P_TEB: 84 + l2_len = ETH_HLEN; 85 + udp_dst = ETH_OVER_UDP_PORT; 86 + break; 103 87 } 88 + flags |= BPF_F_ADJ_ROOM_ENCAP_L2(l2_len); 89 + 90 + switch (encap_proto) { 91 + case IPPROTO_GRE: 92 + flags |= BPF_F_ADJ_ROOM_ENCAP_L4_GRE; 93 + olen += sizeof(h_outer.l4hdr.gre); 94 + h_outer.l4hdr.gre.protocol = bpf_htons(l2_proto); 95 + h_outer.l4hdr.gre.flags = 0; 96 + break; 97 + case IPPROTO_UDP: 98 + flags |= BPF_F_ADJ_ROOM_ENCAP_L4_UDP; 99 + olen += sizeof(h_outer.l4hdr.udp); 100 + h_outer.l4hdr.udp.source = __bpf_constant_htons(cfg_udp_src); 101 + h_outer.l4hdr.udp.dest = bpf_htons(udp_dst); 102 + h_outer.l4hdr.udp.check = 0; 103 + h_outer.l4hdr.udp.len = bpf_htons(bpf_ntohs(iph_inner.tot_len) + 104 + sizeof(h_outer.l4hdr.udp) + 105 + l2_len); 106 + break; 107 + case IPPROTO_IPIP: 108 + break; 109 + default: 110 + return TC_ACT_OK; 111 + } 112 + 113 + /* add L2 encap (if specified) */ 114 + switch (l2_proto) { 115 + case ETH_P_MPLS_UC: 116 + *((__u32 *)((__u8 *)&h_outer + olen)) = mpls_label; 117 + break; 118 + case ETH_P_TEB: 119 + if (bpf_skb_load_bytes(skb, 0, (__u8 *)&h_outer + olen, 120 + ETH_HLEN)) 121 + return TC_ACT_SHOT; 122 + break; 123 + } 124 + olen += l2_len; 104 125 105 126 /* add room between mac and network header */ 106 127 if (bpf_skb_adjust_room(skb, olen, BPF_ADJ_ROOM_MAC, flags)) ··· 154 85 /* prepare new outer network header */ 155 86 h_outer.ip = iph_inner; 156 87 h_outer.ip.tot_len = bpf_htons(olen + 157 - bpf_htons(h_outer.ip.tot_len)); 158 - if (with_gre) { 159 - h_outer.ip.protocol = IPPROTO_GRE; 160 - h_outer.protocol = bpf_htons(ETH_P_IP); 161 - h_outer.flags = 0; 162 - } else { 163 - h_outer.ip.protocol = IPPROTO_IPIP; 164 - } 88 + bpf_ntohs(h_outer.ip.tot_len)); 89 + h_outer.ip.protocol = encap_proto; 165 90 166 - set_ipv4_csum((void *)&h_outer.ip); 91 + set_ipv4_csum(&h_outer.ip); 167 92 168 93 /* store new outer network header */ 169 94 if (bpf_skb_store_bytes(skb, ETH_HLEN, &h_outer, olen, ··· 167 104 return TC_ACT_OK; 168 105 } 169 106 170 - static __always_inline int encap_ipv6(struct __sk_buff *skb, bool with_gre) 107 + static __always_inline int encap_ipv6(struct __sk_buff *skb, __u8 encap_proto, 108 + __u16 l2_proto) 171 109 { 110 + __u16 udp_dst = UDP_PORT; 172 111 struct ipv6hdr iph_inner; 173 - struct grev6hdr h_outer; 112 + struct v6hdr h_outer; 174 113 struct tcphdr tcph; 114 + int olen, l2_len; 115 + __u16 tot_len; 175 116 __u64 flags; 176 - int olen; 177 117 178 118 if (bpf_skb_load_bytes(skb, ETH_HLEN, &iph_inner, 179 119 sizeof(iph_inner)) < 0) ··· 190 124 if (tcph.dest != __bpf_constant_htons(cfg_port)) 191 125 return TC_ACT_OK; 192 126 127 + olen = sizeof(h_outer.ip); 128 + l2_len = 0; 129 + 193 130 flags = BPF_F_ADJ_ROOM_FIXED_GSO | BPF_F_ADJ_ROOM_ENCAP_L3_IPV6; 194 - if (with_gre) { 131 + 132 + switch (l2_proto) { 133 + case ETH_P_MPLS_UC: 134 + l2_len = sizeof(mpls_label); 135 + udp_dst = MPLS_OVER_UDP_PORT; 136 + break; 137 + case ETH_P_TEB: 138 + l2_len = ETH_HLEN; 139 + udp_dst = ETH_OVER_UDP_PORT; 140 + break; 141 + } 142 + flags |= BPF_F_ADJ_ROOM_ENCAP_L2(l2_len); 143 + 144 + switch (encap_proto) { 145 + case IPPROTO_GRE: 195 146 flags |= BPF_F_ADJ_ROOM_ENCAP_L4_GRE; 196 - olen = sizeof(h_outer); 197 - } else { 198 - olen = sizeof(h_outer.ip); 147 + olen += sizeof(h_outer.l4hdr.gre); 148 + h_outer.l4hdr.gre.protocol = bpf_htons(l2_proto); 149 + h_outer.l4hdr.gre.flags = 0; 150 + break; 151 + case IPPROTO_UDP: 152 + flags |= BPF_F_ADJ_ROOM_ENCAP_L4_UDP; 153 + olen += sizeof(h_outer.l4hdr.udp); 154 + h_outer.l4hdr.udp.source = __bpf_constant_htons(cfg_udp_src); 155 + h_outer.l4hdr.udp.dest = bpf_htons(udp_dst); 156 + tot_len = bpf_ntohs(iph_inner.payload_len) + sizeof(iph_inner) + 157 + sizeof(h_outer.l4hdr.udp); 158 + h_outer.l4hdr.udp.check = 0; 159 + h_outer.l4hdr.udp.len = bpf_htons(tot_len); 160 + break; 161 + case IPPROTO_IPV6: 162 + break; 163 + default: 164 + return TC_ACT_OK; 199 165 } 200 166 167 + /* add L2 encap (if specified) */ 168 + switch (l2_proto) { 169 + case ETH_P_MPLS_UC: 170 + *((__u32 *)((__u8 *)&h_outer + olen)) = mpls_label; 171 + break; 172 + case ETH_P_TEB: 173 + if (bpf_skb_load_bytes(skb, 0, (__u8 *)&h_outer + olen, 174 + ETH_HLEN)) 175 + return TC_ACT_SHOT; 176 + break; 177 + } 178 + olen += l2_len; 201 179 202 180 /* add room between mac and network header */ 203 181 if (bpf_skb_adjust_room(skb, olen, BPF_ADJ_ROOM_MAC, flags)) ··· 251 141 h_outer.ip = iph_inner; 252 142 h_outer.ip.payload_len = bpf_htons(olen + 253 143 bpf_ntohs(h_outer.ip.payload_len)); 254 - if (with_gre) { 255 - h_outer.ip.nexthdr = IPPROTO_GRE; 256 - h_outer.protocol = bpf_htons(ETH_P_IPV6); 257 - h_outer.flags = 0; 258 - } else { 259 - h_outer.ip.nexthdr = IPPROTO_IPV6; 260 - } 144 + 145 + h_outer.ip.nexthdr = encap_proto; 261 146 262 147 /* store new outer network header */ 263 148 if (bpf_skb_store_bytes(skb, ETH_HLEN, &h_outer, olen, ··· 262 157 return TC_ACT_OK; 263 158 } 264 159 265 - SEC("encap_ipip") 266 - int __encap_ipip(struct __sk_buff *skb) 160 + SEC("encap_ipip_none") 161 + int __encap_ipip_none(struct __sk_buff *skb) 267 162 { 268 163 if (skb->protocol == __bpf_constant_htons(ETH_P_IP)) 269 - return encap_ipv4(skb, false); 164 + return encap_ipv4(skb, IPPROTO_IPIP, ETH_P_IP); 270 165 else 271 166 return TC_ACT_OK; 272 167 } 273 168 274 - SEC("encap_gre") 275 - int __encap_gre(struct __sk_buff *skb) 169 + SEC("encap_gre_none") 170 + int __encap_gre_none(struct __sk_buff *skb) 276 171 { 277 172 if (skb->protocol == __bpf_constant_htons(ETH_P_IP)) 278 - return encap_ipv4(skb, true); 173 + return encap_ipv4(skb, IPPROTO_GRE, ETH_P_IP); 279 174 else 280 175 return TC_ACT_OK; 281 176 } 282 177 283 - SEC("encap_ip6tnl") 284 - int __encap_ip6tnl(struct __sk_buff *skb) 178 + SEC("encap_gre_mpls") 179 + int __encap_gre_mpls(struct __sk_buff *skb) 285 180 { 286 - if (skb->protocol == __bpf_constant_htons(ETH_P_IPV6)) 287 - return encap_ipv6(skb, false); 181 + if (skb->protocol == __bpf_constant_htons(ETH_P_IP)) 182 + return encap_ipv4(skb, IPPROTO_GRE, ETH_P_MPLS_UC); 288 183 else 289 184 return TC_ACT_OK; 290 185 } 291 186 292 - SEC("encap_ip6gre") 293 - int __encap_ip6gre(struct __sk_buff *skb) 187 + SEC("encap_gre_eth") 188 + int __encap_gre_eth(struct __sk_buff *skb) 189 + { 190 + if (skb->protocol == __bpf_constant_htons(ETH_P_IP)) 191 + return encap_ipv4(skb, IPPROTO_GRE, ETH_P_TEB); 192 + else 193 + return TC_ACT_OK; 194 + } 195 + 196 + SEC("encap_udp_none") 197 + int __encap_udp_none(struct __sk_buff *skb) 198 + { 199 + if (skb->protocol == __bpf_constant_htons(ETH_P_IP)) 200 + return encap_ipv4(skb, IPPROTO_UDP, ETH_P_IP); 201 + else 202 + return TC_ACT_OK; 203 + } 204 + 205 + SEC("encap_udp_mpls") 206 + int __encap_udp_mpls(struct __sk_buff *skb) 207 + { 208 + if (skb->protocol == __bpf_constant_htons(ETH_P_IP)) 209 + return encap_ipv4(skb, IPPROTO_UDP, ETH_P_MPLS_UC); 210 + else 211 + return TC_ACT_OK; 212 + } 213 + 214 + SEC("encap_udp_eth") 215 + int __encap_udp_eth(struct __sk_buff *skb) 216 + { 217 + if (skb->protocol == __bpf_constant_htons(ETH_P_IP)) 218 + return encap_ipv4(skb, IPPROTO_UDP, ETH_P_TEB); 219 + else 220 + return TC_ACT_OK; 221 + } 222 + 223 + SEC("encap_ip6tnl_none") 224 + int __encap_ip6tnl_none(struct __sk_buff *skb) 294 225 { 295 226 if (skb->protocol == __bpf_constant_htons(ETH_P_IPV6)) 296 - return encap_ipv6(skb, true); 227 + return encap_ipv6(skb, IPPROTO_IPV6, ETH_P_IPV6); 228 + else 229 + return TC_ACT_OK; 230 + } 231 + 232 + SEC("encap_ip6gre_none") 233 + int __encap_ip6gre_none(struct __sk_buff *skb) 234 + { 235 + if (skb->protocol == __bpf_constant_htons(ETH_P_IPV6)) 236 + return encap_ipv6(skb, IPPROTO_GRE, ETH_P_IPV6); 237 + else 238 + return TC_ACT_OK; 239 + } 240 + 241 + SEC("encap_ip6gre_mpls") 242 + int __encap_ip6gre_mpls(struct __sk_buff *skb) 243 + { 244 + if (skb->protocol == __bpf_constant_htons(ETH_P_IPV6)) 245 + return encap_ipv6(skb, IPPROTO_GRE, ETH_P_MPLS_UC); 246 + else 247 + return TC_ACT_OK; 248 + } 249 + 250 + SEC("encap_ip6gre_eth") 251 + int __encap_ip6gre_eth(struct __sk_buff *skb) 252 + { 253 + if (skb->protocol == __bpf_constant_htons(ETH_P_IPV6)) 254 + return encap_ipv6(skb, IPPROTO_GRE, ETH_P_TEB); 255 + else 256 + return TC_ACT_OK; 257 + } 258 + 259 + SEC("encap_ip6udp_none") 260 + int __encap_ip6udp_none(struct __sk_buff *skb) 261 + { 262 + if (skb->protocol == __bpf_constant_htons(ETH_P_IPV6)) 263 + return encap_ipv6(skb, IPPROTO_UDP, ETH_P_IPV6); 264 + else 265 + return TC_ACT_OK; 266 + } 267 + 268 + SEC("encap_ip6udp_mpls") 269 + int __encap_ip6udp_mpls(struct __sk_buff *skb) 270 + { 271 + if (skb->protocol == __bpf_constant_htons(ETH_P_IPV6)) 272 + return encap_ipv6(skb, IPPROTO_UDP, ETH_P_MPLS_UC); 273 + else 274 + return TC_ACT_OK; 275 + } 276 + 277 + SEC("encap_ip6udp_eth") 278 + int __encap_ip6udp_eth(struct __sk_buff *skb) 279 + { 280 + if (skb->protocol == __bpf_constant_htons(ETH_P_IPV6)) 281 + return encap_ipv6(skb, IPPROTO_UDP, ETH_P_TEB); 297 282 else 298 283 return TC_ACT_OK; 299 284 } 300 285 301 286 static int decap_internal(struct __sk_buff *skb, int off, int len, char proto) 302 287 { 303 - char buf[sizeof(struct grev6hdr)]; 304 - int olen; 288 + char buf[sizeof(struct v6hdr)]; 289 + struct gre_hdr greh; 290 + struct udphdr udph; 291 + int olen = len; 305 292 306 293 switch (proto) { 307 294 case IPPROTO_IPIP: 308 295 case IPPROTO_IPV6: 309 - olen = len; 310 296 break; 311 297 case IPPROTO_GRE: 312 - olen = len + 4 /* gre hdr */; 298 + olen += sizeof(struct gre_hdr); 299 + if (bpf_skb_load_bytes(skb, off + len, &greh, sizeof(greh)) < 0) 300 + return TC_ACT_OK; 301 + switch (bpf_ntohs(greh.protocol)) { 302 + case ETH_P_MPLS_UC: 303 + olen += sizeof(mpls_label); 304 + break; 305 + case ETH_P_TEB: 306 + olen += ETH_HLEN; 307 + break; 308 + } 309 + break; 310 + case IPPROTO_UDP: 311 + olen += sizeof(struct udphdr); 312 + if (bpf_skb_load_bytes(skb, off + len, &udph, sizeof(udph)) < 0) 313 + return TC_ACT_OK; 314 + switch (bpf_ntohs(udph.dest)) { 315 + case MPLS_OVER_UDP_PORT: 316 + olen += sizeof(mpls_label); 317 + break; 318 + case ETH_OVER_UDP_PORT: 319 + olen += ETH_HLEN; 320 + break; 321 + } 313 322 break; 314 323 default: 315 324 return TC_ACT_OK;
+30
tools/testing/selftests/bpf/progs/test_verif_scale1.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Copyright (c) 2019 Facebook 3 + #include <linux/bpf.h> 4 + #include "bpf_helpers.h" 5 + #define ATTR __attribute__((noinline)) 6 + #include "test_jhash.h" 7 + 8 + SEC("scale90_noinline") 9 + int balancer_ingress(struct __sk_buff *ctx) 10 + { 11 + void *data_end = (void *)(long)ctx->data_end; 12 + void *data = (void *)(long)ctx->data; 13 + void *ptr; 14 + int ret = 0, nh_off, i = 0; 15 + 16 + nh_off = 14; 17 + 18 + /* pragma unroll doesn't work on large loops */ 19 + 20 + #define C do { \ 21 + ptr = data + i; \ 22 + if (ptr + nh_off > data_end) \ 23 + break; \ 24 + ctx->tc_index = jhash(ptr, nh_off, ctx->cb[0] + i++); \ 25 + } while (0); 26 + #define C30 C;C;C;C;C;C;C;C;C;C;C;C;C;C;C;C;C;C;C;C;C;C;C;C;C;C;C;C;C;C; 27 + C30;C30;C30; /* 90 calls */ 28 + return 0; 29 + } 30 + char _license[] SEC("license") = "GPL";
+30
tools/testing/selftests/bpf/progs/test_verif_scale2.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Copyright (c) 2019 Facebook 3 + #include <linux/bpf.h> 4 + #include "bpf_helpers.h" 5 + #define ATTR __attribute__((always_inline)) 6 + #include "test_jhash.h" 7 + 8 + SEC("scale90_inline") 9 + int balancer_ingress(struct __sk_buff *ctx) 10 + { 11 + void *data_end = (void *)(long)ctx->data_end; 12 + void *data = (void *)(long)ctx->data; 13 + void *ptr; 14 + int ret = 0, nh_off, i = 0; 15 + 16 + nh_off = 14; 17 + 18 + /* pragma unroll doesn't work on large loops */ 19 + 20 + #define C do { \ 21 + ptr = data + i; \ 22 + if (ptr + nh_off > data_end) \ 23 + break; \ 24 + ctx->tc_index = jhash(ptr, nh_off, ctx->cb[0] + i++); \ 25 + } while (0); 26 + #define C30 C;C;C;C;C;C;C;C;C;C;C;C;C;C;C;C;C;C;C;C;C;C;C;C;C;C;C;C;C;C; 27 + C30;C30;C30; /* 90 calls */ 28 + return 0; 29 + } 30 + char _license[] SEC("license") = "GPL";
+30
tools/testing/selftests/bpf/progs/test_verif_scale3.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Copyright (c) 2019 Facebook 3 + #include <linux/bpf.h> 4 + #include "bpf_helpers.h" 5 + #define ATTR __attribute__((noinline)) 6 + #include "test_jhash.h" 7 + 8 + SEC("scale90_noinline32") 9 + int balancer_ingress(struct __sk_buff *ctx) 10 + { 11 + void *data_end = (void *)(long)ctx->data_end; 12 + void *data = (void *)(long)ctx->data; 13 + void *ptr; 14 + int ret = 0, nh_off, i = 0; 15 + 16 + nh_off = 32; 17 + 18 + /* pragma unroll doesn't work on large loops */ 19 + 20 + #define C do { \ 21 + ptr = data + i; \ 22 + if (ptr + nh_off > data_end) \ 23 + break; \ 24 + ctx->tc_index = jhash(ptr, nh_off, ctx->cb[0] + i++); \ 25 + } while (0); 26 + #define C30 C;C;C;C;C;C;C;C;C;C;C;C;C;C;C;C;C;C;C;C;C;C;C;C;C;C;C;C;C;C; 27 + C30;C30;C30; /* 90 calls */ 28 + return 0; 29 + } 30 + char _license[] SEC("license") = "GPL";
+687 -10
tools/testing/selftests/bpf/test_btf.c
··· 85 85 #define BTF_UNION_ENC(name, nr_elems, sz) \ 86 86 BTF_TYPE_ENC(name, BTF_INFO_ENC(BTF_KIND_UNION, 0, nr_elems), sz) 87 87 88 + #define BTF_VAR_ENC(name, type, linkage) \ 89 + BTF_TYPE_ENC(name, BTF_INFO_ENC(BTF_KIND_VAR, 0, 0), type), (linkage) 90 + #define BTF_VAR_SECINFO_ENC(type, offset, size) \ 91 + (type), (offset), (size) 92 + 88 93 #define BTF_MEMBER_ENC(name, type, bits_offset) \ 89 94 (name), (type), (bits_offset) 90 95 #define BTF_ENUM_ENC(name, val) (name), (val) ··· 296 291 .value_type_id = 3, 297 292 .max_entries = 4, 298 293 }, 299 - 300 294 { 301 295 .descr = "struct test #3 Invalid member offset", 302 296 .raw_types = { ··· 323 319 .btf_load_err = true, 324 320 .err_str = "Invalid member bits_offset", 325 321 }, 326 - 322 + /* 323 + * struct A { 324 + * unsigned long long m; 325 + * int n; 326 + * char o; 327 + * [3 bytes hole] 328 + * int p[8]; 329 + * }; 330 + */ 331 + { 332 + .descr = "global data test #1", 333 + .raw_types = { 334 + /* int */ 335 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */ 336 + /* unsigned long long */ 337 + BTF_TYPE_INT_ENC(0, 0, 0, 64, 8), /* [2] */ 338 + /* char */ 339 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 8, 1), /* [3] */ 340 + /* int[8] */ 341 + BTF_TYPE_ARRAY_ENC(1, 1, 8), /* [4] */ 342 + /* struct A { */ /* [5] */ 343 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 4), 48), 344 + BTF_MEMBER_ENC(NAME_TBD, 2, 0), /* unsigned long long m;*/ 345 + BTF_MEMBER_ENC(NAME_TBD, 1, 64),/* int n; */ 346 + BTF_MEMBER_ENC(NAME_TBD, 3, 96),/* char o; */ 347 + BTF_MEMBER_ENC(NAME_TBD, 4, 128),/* int p[8] */ 348 + /* } */ 349 + BTF_END_RAW, 350 + }, 351 + .str_sec = "\0A\0m\0n\0o\0p", 352 + .str_sec_size = sizeof("\0A\0m\0n\0o\0p"), 353 + .map_type = BPF_MAP_TYPE_ARRAY, 354 + .map_name = "struct_test1_map", 355 + .key_size = sizeof(int), 356 + .value_size = 48, 357 + .key_type_id = 1, 358 + .value_type_id = 5, 359 + .max_entries = 4, 360 + }, 361 + /* 362 + * struct A { 363 + * unsigned long long m; 364 + * int n; 365 + * char o; 366 + * [3 bytes hole] 367 + * int p[8]; 368 + * }; 369 + * static struct A t; <- in .bss 370 + */ 371 + { 372 + .descr = "global data test #2", 373 + .raw_types = { 374 + /* int */ 375 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */ 376 + /* unsigned long long */ 377 + BTF_TYPE_INT_ENC(0, 0, 0, 64, 8), /* [2] */ 378 + /* char */ 379 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 8, 1), /* [3] */ 380 + /* int[8] */ 381 + BTF_TYPE_ARRAY_ENC(1, 1, 8), /* [4] */ 382 + /* struct A { */ /* [5] */ 383 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 4), 48), 384 + BTF_MEMBER_ENC(NAME_TBD, 2, 0), /* unsigned long long m;*/ 385 + BTF_MEMBER_ENC(NAME_TBD, 1, 64),/* int n; */ 386 + BTF_MEMBER_ENC(NAME_TBD, 3, 96),/* char o; */ 387 + BTF_MEMBER_ENC(NAME_TBD, 4, 128),/* int p[8] */ 388 + /* } */ 389 + /* static struct A t */ 390 + BTF_VAR_ENC(NAME_TBD, 5, 0), /* [6] */ 391 + /* .bss section */ /* [7] */ 392 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_DATASEC, 0, 1), 48), 393 + BTF_VAR_SECINFO_ENC(6, 0, 48), 394 + BTF_END_RAW, 395 + }, 396 + .str_sec = "\0A\0m\0n\0o\0p\0t\0.bss", 397 + .str_sec_size = sizeof("\0A\0m\0n\0o\0p\0t\0.bss"), 398 + .map_type = BPF_MAP_TYPE_ARRAY, 399 + .map_name = ".bss", 400 + .key_size = sizeof(int), 401 + .value_size = 48, 402 + .key_type_id = 0, 403 + .value_type_id = 7, 404 + .max_entries = 1, 405 + }, 406 + { 407 + .descr = "global data test #3", 408 + .raw_types = { 409 + /* int */ 410 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */ 411 + /* static int t */ 412 + BTF_VAR_ENC(NAME_TBD, 1, 0), /* [2] */ 413 + /* .bss section */ /* [3] */ 414 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_DATASEC, 0, 1), 4), 415 + BTF_VAR_SECINFO_ENC(2, 0, 4), 416 + BTF_END_RAW, 417 + }, 418 + .str_sec = "\0t\0.bss", 419 + .str_sec_size = sizeof("\0t\0.bss"), 420 + .map_type = BPF_MAP_TYPE_ARRAY, 421 + .map_name = ".bss", 422 + .key_size = sizeof(int), 423 + .value_size = 4, 424 + .key_type_id = 0, 425 + .value_type_id = 3, 426 + .max_entries = 1, 427 + }, 428 + { 429 + .descr = "global data test #4, unsupported linkage", 430 + .raw_types = { 431 + /* int */ 432 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */ 433 + /* static int t */ 434 + BTF_VAR_ENC(NAME_TBD, 1, 2), /* [2] */ 435 + /* .bss section */ /* [3] */ 436 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_DATASEC, 0, 1), 4), 437 + BTF_VAR_SECINFO_ENC(2, 0, 4), 438 + BTF_END_RAW, 439 + }, 440 + .str_sec = "\0t\0.bss", 441 + .str_sec_size = sizeof("\0t\0.bss"), 442 + .map_type = BPF_MAP_TYPE_ARRAY, 443 + .map_name = ".bss", 444 + .key_size = sizeof(int), 445 + .value_size = 4, 446 + .key_type_id = 0, 447 + .value_type_id = 3, 448 + .max_entries = 1, 449 + .btf_load_err = true, 450 + .err_str = "Linkage not supported", 451 + }, 452 + { 453 + .descr = "global data test #5, invalid var type", 454 + .raw_types = { 455 + /* static void t */ 456 + BTF_VAR_ENC(NAME_TBD, 0, 0), /* [1] */ 457 + /* .bss section */ /* [2] */ 458 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_DATASEC, 0, 1), 4), 459 + BTF_VAR_SECINFO_ENC(1, 0, 4), 460 + BTF_END_RAW, 461 + }, 462 + .str_sec = "\0t\0.bss", 463 + .str_sec_size = sizeof("\0t\0.bss"), 464 + .map_type = BPF_MAP_TYPE_ARRAY, 465 + .map_name = ".bss", 466 + .key_size = sizeof(int), 467 + .value_size = 4, 468 + .key_type_id = 0, 469 + .value_type_id = 2, 470 + .max_entries = 1, 471 + .btf_load_err = true, 472 + .err_str = "Invalid type_id", 473 + }, 474 + { 475 + .descr = "global data test #6, invalid var type (fwd type)", 476 + .raw_types = { 477 + /* union A */ 478 + BTF_TYPE_ENC(NAME_TBD, 479 + BTF_INFO_ENC(BTF_KIND_FWD, 1, 0), 0), /* [1] */ 480 + /* static union A t */ 481 + BTF_VAR_ENC(NAME_TBD, 1, 0), /* [2] */ 482 + /* .bss section */ /* [3] */ 483 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_DATASEC, 0, 1), 4), 484 + BTF_VAR_SECINFO_ENC(2, 0, 4), 485 + BTF_END_RAW, 486 + }, 487 + .str_sec = "\0A\0t\0.bss", 488 + .str_sec_size = sizeof("\0A\0t\0.bss"), 489 + .map_type = BPF_MAP_TYPE_ARRAY, 490 + .map_name = ".bss", 491 + .key_size = sizeof(int), 492 + .value_size = 4, 493 + .key_type_id = 0, 494 + .value_type_id = 2, 495 + .max_entries = 1, 496 + .btf_load_err = true, 497 + .err_str = "Invalid type", 498 + }, 499 + { 500 + .descr = "global data test #7, invalid var type (fwd type)", 501 + .raw_types = { 502 + /* union A */ 503 + BTF_TYPE_ENC(NAME_TBD, 504 + BTF_INFO_ENC(BTF_KIND_FWD, 1, 0), 0), /* [1] */ 505 + /* static union A t */ 506 + BTF_VAR_ENC(NAME_TBD, 1, 0), /* [2] */ 507 + /* .bss section */ /* [3] */ 508 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_DATASEC, 0, 1), 4), 509 + BTF_VAR_SECINFO_ENC(1, 0, 4), 510 + BTF_END_RAW, 511 + }, 512 + .str_sec = "\0A\0t\0.bss", 513 + .str_sec_size = sizeof("\0A\0t\0.bss"), 514 + .map_type = BPF_MAP_TYPE_ARRAY, 515 + .map_name = ".bss", 516 + .key_size = sizeof(int), 517 + .value_size = 4, 518 + .key_type_id = 0, 519 + .value_type_id = 2, 520 + .max_entries = 1, 521 + .btf_load_err = true, 522 + .err_str = "Invalid type", 523 + }, 524 + { 525 + .descr = "global data test #8, invalid var size", 526 + .raw_types = { 527 + /* int */ 528 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */ 529 + /* unsigned long long */ 530 + BTF_TYPE_INT_ENC(0, 0, 0, 64, 8), /* [2] */ 531 + /* char */ 532 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 8, 1), /* [3] */ 533 + /* int[8] */ 534 + BTF_TYPE_ARRAY_ENC(1, 1, 8), /* [4] */ 535 + /* struct A { */ /* [5] */ 536 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 4), 48), 537 + BTF_MEMBER_ENC(NAME_TBD, 2, 0), /* unsigned long long m;*/ 538 + BTF_MEMBER_ENC(NAME_TBD, 1, 64),/* int n; */ 539 + BTF_MEMBER_ENC(NAME_TBD, 3, 96),/* char o; */ 540 + BTF_MEMBER_ENC(NAME_TBD, 4, 128),/* int p[8] */ 541 + /* } */ 542 + /* static struct A t */ 543 + BTF_VAR_ENC(NAME_TBD, 5, 0), /* [6] */ 544 + /* .bss section */ /* [7] */ 545 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_DATASEC, 0, 1), 48), 546 + BTF_VAR_SECINFO_ENC(6, 0, 47), 547 + BTF_END_RAW, 548 + }, 549 + .str_sec = "\0A\0m\0n\0o\0p\0t\0.bss", 550 + .str_sec_size = sizeof("\0A\0m\0n\0o\0p\0t\0.bss"), 551 + .map_type = BPF_MAP_TYPE_ARRAY, 552 + .map_name = ".bss", 553 + .key_size = sizeof(int), 554 + .value_size = 48, 555 + .key_type_id = 0, 556 + .value_type_id = 7, 557 + .max_entries = 1, 558 + .btf_load_err = true, 559 + .err_str = "Invalid size", 560 + }, 561 + { 562 + .descr = "global data test #9, invalid var size", 563 + .raw_types = { 564 + /* int */ 565 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */ 566 + /* unsigned long long */ 567 + BTF_TYPE_INT_ENC(0, 0, 0, 64, 8), /* [2] */ 568 + /* char */ 569 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 8, 1), /* [3] */ 570 + /* int[8] */ 571 + BTF_TYPE_ARRAY_ENC(1, 1, 8), /* [4] */ 572 + /* struct A { */ /* [5] */ 573 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 4), 48), 574 + BTF_MEMBER_ENC(NAME_TBD, 2, 0), /* unsigned long long m;*/ 575 + BTF_MEMBER_ENC(NAME_TBD, 1, 64),/* int n; */ 576 + BTF_MEMBER_ENC(NAME_TBD, 3, 96),/* char o; */ 577 + BTF_MEMBER_ENC(NAME_TBD, 4, 128),/* int p[8] */ 578 + /* } */ 579 + /* static struct A t */ 580 + BTF_VAR_ENC(NAME_TBD, 5, 0), /* [6] */ 581 + /* .bss section */ /* [7] */ 582 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_DATASEC, 0, 1), 46), 583 + BTF_VAR_SECINFO_ENC(6, 0, 48), 584 + BTF_END_RAW, 585 + }, 586 + .str_sec = "\0A\0m\0n\0o\0p\0t\0.bss", 587 + .str_sec_size = sizeof("\0A\0m\0n\0o\0p\0t\0.bss"), 588 + .map_type = BPF_MAP_TYPE_ARRAY, 589 + .map_name = ".bss", 590 + .key_size = sizeof(int), 591 + .value_size = 48, 592 + .key_type_id = 0, 593 + .value_type_id = 7, 594 + .max_entries = 1, 595 + .btf_load_err = true, 596 + .err_str = "Invalid size", 597 + }, 598 + { 599 + .descr = "global data test #10, invalid var size", 600 + .raw_types = { 601 + /* int */ 602 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */ 603 + /* unsigned long long */ 604 + BTF_TYPE_INT_ENC(0, 0, 0, 64, 8), /* [2] */ 605 + /* char */ 606 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 8, 1), /* [3] */ 607 + /* int[8] */ 608 + BTF_TYPE_ARRAY_ENC(1, 1, 8), /* [4] */ 609 + /* struct A { */ /* [5] */ 610 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 4), 48), 611 + BTF_MEMBER_ENC(NAME_TBD, 2, 0), /* unsigned long long m;*/ 612 + BTF_MEMBER_ENC(NAME_TBD, 1, 64),/* int n; */ 613 + BTF_MEMBER_ENC(NAME_TBD, 3, 96),/* char o; */ 614 + BTF_MEMBER_ENC(NAME_TBD, 4, 128),/* int p[8] */ 615 + /* } */ 616 + /* static struct A t */ 617 + BTF_VAR_ENC(NAME_TBD, 5, 0), /* [6] */ 618 + /* .bss section */ /* [7] */ 619 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_DATASEC, 0, 1), 46), 620 + BTF_VAR_SECINFO_ENC(6, 0, 46), 621 + BTF_END_RAW, 622 + }, 623 + .str_sec = "\0A\0m\0n\0o\0p\0t\0.bss", 624 + .str_sec_size = sizeof("\0A\0m\0n\0o\0p\0t\0.bss"), 625 + .map_type = BPF_MAP_TYPE_ARRAY, 626 + .map_name = ".bss", 627 + .key_size = sizeof(int), 628 + .value_size = 48, 629 + .key_type_id = 0, 630 + .value_type_id = 7, 631 + .max_entries = 1, 632 + .btf_load_err = true, 633 + .err_str = "Invalid size", 634 + }, 635 + { 636 + .descr = "global data test #11, multiple section members", 637 + .raw_types = { 638 + /* int */ 639 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */ 640 + /* unsigned long long */ 641 + BTF_TYPE_INT_ENC(0, 0, 0, 64, 8), /* [2] */ 642 + /* char */ 643 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 8, 1), /* [3] */ 644 + /* int[8] */ 645 + BTF_TYPE_ARRAY_ENC(1, 1, 8), /* [4] */ 646 + /* struct A { */ /* [5] */ 647 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 4), 48), 648 + BTF_MEMBER_ENC(NAME_TBD, 2, 0), /* unsigned long long m;*/ 649 + BTF_MEMBER_ENC(NAME_TBD, 1, 64),/* int n; */ 650 + BTF_MEMBER_ENC(NAME_TBD, 3, 96),/* char o; */ 651 + BTF_MEMBER_ENC(NAME_TBD, 4, 128),/* int p[8] */ 652 + /* } */ 653 + /* static struct A t */ 654 + BTF_VAR_ENC(NAME_TBD, 5, 0), /* [6] */ 655 + /* static int u */ 656 + BTF_VAR_ENC(NAME_TBD, 1, 0), /* [7] */ 657 + /* .bss section */ /* [8] */ 658 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_DATASEC, 0, 2), 62), 659 + BTF_VAR_SECINFO_ENC(6, 10, 48), 660 + BTF_VAR_SECINFO_ENC(7, 58, 4), 661 + BTF_END_RAW, 662 + }, 663 + .str_sec = "\0A\0m\0n\0o\0p\0t\0u\0.bss", 664 + .str_sec_size = sizeof("\0A\0m\0n\0o\0p\0t\0u\0.bss"), 665 + .map_type = BPF_MAP_TYPE_ARRAY, 666 + .map_name = ".bss", 667 + .key_size = sizeof(int), 668 + .value_size = 62, 669 + .key_type_id = 0, 670 + .value_type_id = 8, 671 + .max_entries = 1, 672 + }, 673 + { 674 + .descr = "global data test #12, invalid offset", 675 + .raw_types = { 676 + /* int */ 677 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */ 678 + /* unsigned long long */ 679 + BTF_TYPE_INT_ENC(0, 0, 0, 64, 8), /* [2] */ 680 + /* char */ 681 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 8, 1), /* [3] */ 682 + /* int[8] */ 683 + BTF_TYPE_ARRAY_ENC(1, 1, 8), /* [4] */ 684 + /* struct A { */ /* [5] */ 685 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 4), 48), 686 + BTF_MEMBER_ENC(NAME_TBD, 2, 0), /* unsigned long long m;*/ 687 + BTF_MEMBER_ENC(NAME_TBD, 1, 64),/* int n; */ 688 + BTF_MEMBER_ENC(NAME_TBD, 3, 96),/* char o; */ 689 + BTF_MEMBER_ENC(NAME_TBD, 4, 128),/* int p[8] */ 690 + /* } */ 691 + /* static struct A t */ 692 + BTF_VAR_ENC(NAME_TBD, 5, 0), /* [6] */ 693 + /* static int u */ 694 + BTF_VAR_ENC(NAME_TBD, 1, 0), /* [7] */ 695 + /* .bss section */ /* [8] */ 696 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_DATASEC, 0, 2), 62), 697 + BTF_VAR_SECINFO_ENC(6, 10, 48), 698 + BTF_VAR_SECINFO_ENC(7, 60, 4), 699 + BTF_END_RAW, 700 + }, 701 + .str_sec = "\0A\0m\0n\0o\0p\0t\0u\0.bss", 702 + .str_sec_size = sizeof("\0A\0m\0n\0o\0p\0t\0u\0.bss"), 703 + .map_type = BPF_MAP_TYPE_ARRAY, 704 + .map_name = ".bss", 705 + .key_size = sizeof(int), 706 + .value_size = 62, 707 + .key_type_id = 0, 708 + .value_type_id = 8, 709 + .max_entries = 1, 710 + .btf_load_err = true, 711 + .err_str = "Invalid offset+size", 712 + }, 713 + { 714 + .descr = "global data test #13, invalid offset", 715 + .raw_types = { 716 + /* int */ 717 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */ 718 + /* unsigned long long */ 719 + BTF_TYPE_INT_ENC(0, 0, 0, 64, 8), /* [2] */ 720 + /* char */ 721 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 8, 1), /* [3] */ 722 + /* int[8] */ 723 + BTF_TYPE_ARRAY_ENC(1, 1, 8), /* [4] */ 724 + /* struct A { */ /* [5] */ 725 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 4), 48), 726 + BTF_MEMBER_ENC(NAME_TBD, 2, 0), /* unsigned long long m;*/ 727 + BTF_MEMBER_ENC(NAME_TBD, 1, 64),/* int n; */ 728 + BTF_MEMBER_ENC(NAME_TBD, 3, 96),/* char o; */ 729 + BTF_MEMBER_ENC(NAME_TBD, 4, 128),/* int p[8] */ 730 + /* } */ 731 + /* static struct A t */ 732 + BTF_VAR_ENC(NAME_TBD, 5, 0), /* [6] */ 733 + /* static int u */ 734 + BTF_VAR_ENC(NAME_TBD, 1, 0), /* [7] */ 735 + /* .bss section */ /* [8] */ 736 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_DATASEC, 0, 2), 62), 737 + BTF_VAR_SECINFO_ENC(6, 10, 48), 738 + BTF_VAR_SECINFO_ENC(7, 12, 4), 739 + BTF_END_RAW, 740 + }, 741 + .str_sec = "\0A\0m\0n\0o\0p\0t\0u\0.bss", 742 + .str_sec_size = sizeof("\0A\0m\0n\0o\0p\0t\0u\0.bss"), 743 + .map_type = BPF_MAP_TYPE_ARRAY, 744 + .map_name = ".bss", 745 + .key_size = sizeof(int), 746 + .value_size = 62, 747 + .key_type_id = 0, 748 + .value_type_id = 8, 749 + .max_entries = 1, 750 + .btf_load_err = true, 751 + .err_str = "Invalid offset", 752 + }, 753 + { 754 + .descr = "global data test #14, invalid offset", 755 + .raw_types = { 756 + /* int */ 757 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */ 758 + /* unsigned long long */ 759 + BTF_TYPE_INT_ENC(0, 0, 0, 64, 8), /* [2] */ 760 + /* char */ 761 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 8, 1), /* [3] */ 762 + /* int[8] */ 763 + BTF_TYPE_ARRAY_ENC(1, 1, 8), /* [4] */ 764 + /* struct A { */ /* [5] */ 765 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 4), 48), 766 + BTF_MEMBER_ENC(NAME_TBD, 2, 0), /* unsigned long long m;*/ 767 + BTF_MEMBER_ENC(NAME_TBD, 1, 64),/* int n; */ 768 + BTF_MEMBER_ENC(NAME_TBD, 3, 96),/* char o; */ 769 + BTF_MEMBER_ENC(NAME_TBD, 4, 128),/* int p[8] */ 770 + /* } */ 771 + /* static struct A t */ 772 + BTF_VAR_ENC(NAME_TBD, 5, 0), /* [6] */ 773 + /* static int u */ 774 + BTF_VAR_ENC(NAME_TBD, 1, 0), /* [7] */ 775 + /* .bss section */ /* [8] */ 776 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_DATASEC, 0, 2), 62), 777 + BTF_VAR_SECINFO_ENC(7, 58, 4), 778 + BTF_VAR_SECINFO_ENC(6, 10, 48), 779 + BTF_END_RAW, 780 + }, 781 + .str_sec = "\0A\0m\0n\0o\0p\0t\0u\0.bss", 782 + .str_sec_size = sizeof("\0A\0m\0n\0o\0p\0t\0u\0.bss"), 783 + .map_type = BPF_MAP_TYPE_ARRAY, 784 + .map_name = ".bss", 785 + .key_size = sizeof(int), 786 + .value_size = 62, 787 + .key_type_id = 0, 788 + .value_type_id = 8, 789 + .max_entries = 1, 790 + .btf_load_err = true, 791 + .err_str = "Invalid offset", 792 + }, 793 + { 794 + .descr = "global data test #15, not var kind", 795 + .raw_types = { 796 + /* int */ 797 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */ 798 + BTF_VAR_ENC(NAME_TBD, 1, 0), /* [2] */ 799 + /* .bss section */ /* [3] */ 800 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_DATASEC, 0, 1), 4), 801 + BTF_VAR_SECINFO_ENC(1, 0, 4), 802 + BTF_END_RAW, 803 + }, 804 + .str_sec = "\0A\0t\0.bss", 805 + .str_sec_size = sizeof("\0A\0t\0.bss"), 806 + .map_type = BPF_MAP_TYPE_ARRAY, 807 + .map_name = ".bss", 808 + .key_size = sizeof(int), 809 + .value_size = 4, 810 + .key_type_id = 0, 811 + .value_type_id = 3, 812 + .max_entries = 1, 813 + .btf_load_err = true, 814 + .err_str = "Not a VAR kind member", 815 + }, 816 + { 817 + .descr = "global data test #16, invalid var referencing sec", 818 + .raw_types = { 819 + /* int */ 820 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */ 821 + BTF_VAR_ENC(NAME_TBD, 5, 0), /* [2] */ 822 + BTF_VAR_ENC(NAME_TBD, 2, 0), /* [3] */ 823 + /* a section */ /* [4] */ 824 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_DATASEC, 0, 1), 4), 825 + BTF_VAR_SECINFO_ENC(3, 0, 4), 826 + /* a section */ /* [5] */ 827 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_DATASEC, 0, 1), 4), 828 + BTF_VAR_SECINFO_ENC(6, 0, 4), 829 + BTF_VAR_ENC(NAME_TBD, 1, 0), /* [6] */ 830 + BTF_END_RAW, 831 + }, 832 + .str_sec = "\0A\0t\0s\0a\0a", 833 + .str_sec_size = sizeof("\0A\0t\0s\0a\0a"), 834 + .map_type = BPF_MAP_TYPE_ARRAY, 835 + .map_name = ".bss", 836 + .key_size = sizeof(int), 837 + .value_size = 4, 838 + .key_type_id = 0, 839 + .value_type_id = 4, 840 + .max_entries = 1, 841 + .btf_load_err = true, 842 + .err_str = "Invalid type_id", 843 + }, 844 + { 845 + .descr = "global data test #17, invalid var referencing var", 846 + .raw_types = { 847 + /* int */ 848 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */ 849 + BTF_VAR_ENC(NAME_TBD, 1, 0), /* [2] */ 850 + BTF_VAR_ENC(NAME_TBD, 2, 0), /* [3] */ 851 + /* a section */ /* [4] */ 852 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_DATASEC, 0, 1), 4), 853 + BTF_VAR_SECINFO_ENC(3, 0, 4), 854 + BTF_END_RAW, 855 + }, 856 + .str_sec = "\0A\0t\0s\0a\0a", 857 + .str_sec_size = sizeof("\0A\0t\0s\0a\0a"), 858 + .map_type = BPF_MAP_TYPE_ARRAY, 859 + .map_name = ".bss", 860 + .key_size = sizeof(int), 861 + .value_size = 4, 862 + .key_type_id = 0, 863 + .value_type_id = 4, 864 + .max_entries = 1, 865 + .btf_load_err = true, 866 + .err_str = "Invalid type_id", 867 + }, 868 + { 869 + .descr = "global data test #18, invalid var loop", 870 + .raw_types = { 871 + /* int */ 872 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */ 873 + BTF_VAR_ENC(NAME_TBD, 2, 0), /* [2] */ 874 + /* .bss section */ /* [3] */ 875 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_DATASEC, 0, 1), 4), 876 + BTF_VAR_SECINFO_ENC(2, 0, 4), 877 + BTF_END_RAW, 878 + }, 879 + .str_sec = "\0A\0t\0aaa", 880 + .str_sec_size = sizeof("\0A\0t\0aaa"), 881 + .map_type = BPF_MAP_TYPE_ARRAY, 882 + .map_name = ".bss", 883 + .key_size = sizeof(int), 884 + .value_size = 4, 885 + .key_type_id = 0, 886 + .value_type_id = 4, 887 + .max_entries = 1, 888 + .btf_load_err = true, 889 + .err_str = "Invalid type_id", 890 + }, 891 + { 892 + .descr = "global data test #19, invalid var referencing var", 893 + .raw_types = { 894 + /* int */ 895 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */ 896 + BTF_VAR_ENC(NAME_TBD, 3, 0), /* [2] */ 897 + BTF_VAR_ENC(NAME_TBD, 1, 0), /* [3] */ 898 + BTF_END_RAW, 899 + }, 900 + .str_sec = "\0A\0t\0s\0a\0a", 901 + .str_sec_size = sizeof("\0A\0t\0s\0a\0a"), 902 + .map_type = BPF_MAP_TYPE_ARRAY, 903 + .map_name = ".bss", 904 + .key_size = sizeof(int), 905 + .value_size = 4, 906 + .key_type_id = 0, 907 + .value_type_id = 4, 908 + .max_entries = 1, 909 + .btf_load_err = true, 910 + .err_str = "Invalid type_id", 911 + }, 912 + { 913 + .descr = "global data test #20, invalid ptr referencing var", 914 + .raw_types = { 915 + /* int */ 916 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */ 917 + /* PTR type_id=3 */ /* [2] */ 918 + BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 3), 919 + BTF_VAR_ENC(NAME_TBD, 1, 0), /* [3] */ 920 + BTF_END_RAW, 921 + }, 922 + .str_sec = "\0A\0t\0s\0a\0a", 923 + .str_sec_size = sizeof("\0A\0t\0s\0a\0a"), 924 + .map_type = BPF_MAP_TYPE_ARRAY, 925 + .map_name = ".bss", 926 + .key_size = sizeof(int), 927 + .value_size = 4, 928 + .key_type_id = 0, 929 + .value_type_id = 4, 930 + .max_entries = 1, 931 + .btf_load_err = true, 932 + .err_str = "Invalid type_id", 933 + }, 934 + { 935 + .descr = "global data test #21, var included in struct", 936 + .raw_types = { 937 + /* int */ 938 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */ 939 + /* struct A { */ /* [2] */ 940 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 2), sizeof(int) * 2), 941 + BTF_MEMBER_ENC(NAME_TBD, 1, 0), /* int m; */ 942 + BTF_MEMBER_ENC(NAME_TBD, 3, 32),/* VAR type_id=3; */ 943 + /* } */ 944 + BTF_VAR_ENC(NAME_TBD, 1, 0), /* [3] */ 945 + BTF_END_RAW, 946 + }, 947 + .str_sec = "\0A\0t\0s\0a\0a", 948 + .str_sec_size = sizeof("\0A\0t\0s\0a\0a"), 949 + .map_type = BPF_MAP_TYPE_ARRAY, 950 + .map_name = ".bss", 951 + .key_size = sizeof(int), 952 + .value_size = 4, 953 + .key_type_id = 0, 954 + .value_type_id = 4, 955 + .max_entries = 1, 956 + .btf_load_err = true, 957 + .err_str = "Invalid member", 958 + }, 959 + { 960 + .descr = "global data test #22, array of var", 961 + .raw_types = { 962 + /* int */ 963 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */ 964 + BTF_TYPE_ARRAY_ENC(3, 1, 4), /* [2] */ 965 + BTF_VAR_ENC(NAME_TBD, 1, 0), /* [3] */ 966 + BTF_END_RAW, 967 + }, 968 + .str_sec = "\0A\0t\0s\0a\0a", 969 + .str_sec_size = sizeof("\0A\0t\0s\0a\0a"), 970 + .map_type = BPF_MAP_TYPE_ARRAY, 971 + .map_name = ".bss", 972 + .key_size = sizeof(int), 973 + .value_size = 4, 974 + .key_type_id = 0, 975 + .value_type_id = 4, 976 + .max_entries = 1, 977 + .btf_load_err = true, 978 + .err_str = "Invalid elem", 979 + }, 327 980 /* Test member exceeds the size of struct. 328 981 * 329 982 * struct A { ··· 4338 3677 } aenum; 4339 3678 uint32_t ui32b; 4340 3679 uint32_t bits2c:2; 3680 + uint8_t si8_4[2][2]; 4341 3681 }; 4342 3682 4343 3683 #ifdef __SIZEOF_INT128__ ··· 4391 3729 BTF_ENUM_ENC(NAME_TBD, 2), 4392 3730 BTF_ENUM_ENC(NAME_TBD, 3), 4393 3731 /* struct pprint_mapv */ /* [16] */ 4394 - BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 10), 40), 3732 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 11), 40), 4395 3733 BTF_MEMBER_ENC(NAME_TBD, 11, 0), /* uint32_t ui32 */ 4396 3734 BTF_MEMBER_ENC(NAME_TBD, 10, 32), /* uint16_t ui16 */ 4397 3735 BTF_MEMBER_ENC(NAME_TBD, 12, 64), /* int32_t si32 */ ··· 4402 3740 BTF_MEMBER_ENC(NAME_TBD, 15, 192), /* aenum */ 4403 3741 BTF_MEMBER_ENC(NAME_TBD, 11, 224), /* uint32_t ui32b */ 4404 3742 BTF_MEMBER_ENC(NAME_TBD, 6, 256), /* bits2c */ 3743 + BTF_MEMBER_ENC(NAME_TBD, 17, 264), /* si8_4 */ 3744 + BTF_TYPE_ARRAY_ENC(18, 1, 2), /* [17] */ 3745 + BTF_TYPE_ARRAY_ENC(1, 1, 2), /* [18] */ 4405 3746 BTF_END_RAW, 4406 3747 }, 4407 - BTF_STR_SEC("\0unsigned char\0unsigned short\0unsigned int\0int\0unsigned long long\0uint8_t\0uint16_t\0uint32_t\0int32_t\0uint64_t\0ui64\0ui8a\0ENUM_ZERO\0ENUM_ONE\0ENUM_TWO\0ENUM_THREE\0pprint_mapv\0ui32\0ui16\0si32\0unused_bits2a\0bits28\0unused_bits2b\0aenum\0ui32b\0bits2c"), 3748 + BTF_STR_SEC("\0unsigned char\0unsigned short\0unsigned int\0int\0unsigned long long\0uint8_t\0uint16_t\0uint32_t\0int32_t\0uint64_t\0ui64\0ui8a\0ENUM_ZERO\0ENUM_ONE\0ENUM_TWO\0ENUM_THREE\0pprint_mapv\0ui32\0ui16\0si32\0unused_bits2a\0bits28\0unused_bits2b\0aenum\0ui32b\0bits2c\0si8_4"), 4408 3749 .key_size = sizeof(unsigned int), 4409 3750 .value_size = sizeof(struct pprint_mapv), 4410 3751 .key_type_id = 3, /* unsigned int */ ··· 4456 3791 BTF_ENUM_ENC(NAME_TBD, 2), 4457 3792 BTF_ENUM_ENC(NAME_TBD, 3), 4458 3793 /* struct pprint_mapv */ /* [16] */ 4459 - BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 1, 10), 40), 3794 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 1, 11), 40), 4460 3795 BTF_MEMBER_ENC(NAME_TBD, 11, BTF_MEMBER_OFFSET(0, 0)), /* uint32_t ui32 */ 4461 3796 BTF_MEMBER_ENC(NAME_TBD, 10, BTF_MEMBER_OFFSET(0, 32)), /* uint16_t ui16 */ 4462 3797 BTF_MEMBER_ENC(NAME_TBD, 12, BTF_MEMBER_OFFSET(0, 64)), /* int32_t si32 */ ··· 4467 3802 BTF_MEMBER_ENC(NAME_TBD, 15, BTF_MEMBER_OFFSET(0, 192)), /* aenum */ 4468 3803 BTF_MEMBER_ENC(NAME_TBD, 11, BTF_MEMBER_OFFSET(0, 224)), /* uint32_t ui32b */ 4469 3804 BTF_MEMBER_ENC(NAME_TBD, 6, BTF_MEMBER_OFFSET(2, 256)), /* bits2c */ 3805 + BTF_MEMBER_ENC(NAME_TBD, 17, 264), /* si8_4 */ 3806 + BTF_TYPE_ARRAY_ENC(18, 1, 2), /* [17] */ 3807 + BTF_TYPE_ARRAY_ENC(1, 1, 2), /* [18] */ 4470 3808 BTF_END_RAW, 4471 3809 }, 4472 - BTF_STR_SEC("\0unsigned char\0unsigned short\0unsigned int\0int\0unsigned long long\0uint8_t\0uint16_t\0uint32_t\0int32_t\0uint64_t\0ui64\0ui8a\0ENUM_ZERO\0ENUM_ONE\0ENUM_TWO\0ENUM_THREE\0pprint_mapv\0ui32\0ui16\0si32\0unused_bits2a\0bits28\0unused_bits2b\0aenum\0ui32b\0bits2c"), 3810 + BTF_STR_SEC("\0unsigned char\0unsigned short\0unsigned int\0int\0unsigned long long\0uint8_t\0uint16_t\0uint32_t\0int32_t\0uint64_t\0ui64\0ui8a\0ENUM_ZERO\0ENUM_ONE\0ENUM_TWO\0ENUM_THREE\0pprint_mapv\0ui32\0ui16\0si32\0unused_bits2a\0bits28\0unused_bits2b\0aenum\0ui32b\0bits2c\0si8_4"), 4473 3811 .key_size = sizeof(unsigned int), 4474 3812 .value_size = sizeof(struct pprint_mapv), 4475 3813 .key_type_id = 3, /* unsigned int */ ··· 4523 3855 BTF_ENUM_ENC(NAME_TBD, 2), 4524 3856 BTF_ENUM_ENC(NAME_TBD, 3), 4525 3857 /* struct pprint_mapv */ /* [16] */ 4526 - BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 1, 10), 40), 3858 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 1, 11), 40), 4527 3859 BTF_MEMBER_ENC(NAME_TBD, 11, BTF_MEMBER_OFFSET(0, 0)), /* uint32_t ui32 */ 4528 3860 BTF_MEMBER_ENC(NAME_TBD, 10, BTF_MEMBER_OFFSET(0, 32)), /* uint16_t ui16 */ 4529 3861 BTF_MEMBER_ENC(NAME_TBD, 12, BTF_MEMBER_OFFSET(0, 64)), /* int32_t si32 */ ··· 4534 3866 BTF_MEMBER_ENC(NAME_TBD, 15, BTF_MEMBER_OFFSET(0, 192)), /* aenum */ 4535 3867 BTF_MEMBER_ENC(NAME_TBD, 11, BTF_MEMBER_OFFSET(0, 224)), /* uint32_t ui32b */ 4536 3868 BTF_MEMBER_ENC(NAME_TBD, 17, BTF_MEMBER_OFFSET(2, 256)), /* bits2c */ 3869 + BTF_MEMBER_ENC(NAME_TBD, 20, BTF_MEMBER_OFFSET(0, 264)), /* si8_4 */ 4537 3870 /* typedef unsigned int ___int */ /* [17] */ 4538 3871 BTF_TYPEDEF_ENC(NAME_TBD, 18), 4539 3872 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_VOLATILE, 0, 0), 6), /* [18] */ 4540 3873 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 15), /* [19] */ 3874 + BTF_TYPE_ARRAY_ENC(21, 1, 2), /* [20] */ 3875 + BTF_TYPE_ARRAY_ENC(1, 1, 2), /* [21] */ 4541 3876 BTF_END_RAW, 4542 3877 }, 4543 - BTF_STR_SEC("\0unsigned char\0unsigned short\0unsigned int\0int\0unsigned long long\0uint8_t\0uint16_t\0uint32_t\0int32_t\0uint64_t\0ui64\0ui8a\0ENUM_ZERO\0ENUM_ONE\0ENUM_TWO\0ENUM_THREE\0pprint_mapv\0ui32\0ui16\0si32\0unused_bits2a\0bits28\0unused_bits2b\0aenum\0ui32b\0bits2c\0___int"), 3878 + BTF_STR_SEC("\0unsigned char\0unsigned short\0unsigned int\0int\0unsigned long long\0uint8_t\0uint16_t\0uint32_t\0int32_t\0uint64_t\0ui64\0ui8a\0ENUM_ZERO\0ENUM_ONE\0ENUM_TWO\0ENUM_THREE\0pprint_mapv\0ui32\0ui16\0si32\0unused_bits2a\0bits28\0unused_bits2b\0aenum\0ui32b\0bits2c\0___int\0si8_4"), 4544 3879 .key_size = sizeof(unsigned int), 4545 3880 .value_size = sizeof(struct pprint_mapv), 4546 3881 .key_type_id = 3, /* unsigned int */ ··· 4678 4007 v->aenum = i & 0x03; 4679 4008 v->ui32b = 4; 4680 4009 v->bits2c = 1; 4010 + v->si8_4[0][0] = (cpu + i) & 0xff; 4011 + v->si8_4[0][1] = (cpu + i + 1) & 0xff; 4012 + v->si8_4[1][0] = (cpu + i + 2) & 0xff; 4013 + v->si8_4[1][1] = (cpu + i + 3) & 0xff; 4681 4014 v = (void *)v + rounded_value_size; 4682 4015 } 4683 4016 } ··· 4715 4040 nexpected_line = snprintf(expected_line, line_size, 4716 4041 "%s%u: {%u,0,%d,0x%x,0x%x,0x%x," 4717 4042 "{%lu|[%u,%u,%u,%u,%u,%u,%u,%u]},%s," 4718 - "%u,0x%x}\n", 4043 + "%u,0x%x,[[%d,%d],[%d,%d]]}\n", 4719 4044 percpu_map ? "\tcpu" : "", 4720 4045 percpu_map ? cpu : next_key, 4721 4046 v->ui32, v->si32, ··· 4729 4054 v->ui8a[6], v->ui8a[7], 4730 4055 pprint_enum_str[v->aenum], 4731 4056 v->ui32b, 4732 - v->bits2c); 4057 + v->bits2c, 4058 + v->si8_4[0][0], v->si8_4[0][1], 4059 + v->si8_4[1][0], v->si8_4[1][1]); 4733 4060 } 4734 4061 4735 4062 #ifdef __SIZEOF_INT128__
+5 -1
tools/testing/selftests/bpf/test_progs.c
··· 9 9 10 10 int error_cnt, pass_cnt; 11 11 bool jit_enabled; 12 + bool verifier_stats = false; 12 13 13 14 struct ipv4_packet pkt_v4 = { 14 15 .eth.h_proto = __bpf_constant_htons(ETH_P_IP), ··· 163 162 #include <prog_tests/tests.h> 164 163 #undef DECLARE 165 164 166 - int main(void) 165 + int main(int ac, char **av) 167 166 { 168 167 srand(time(NULL)); 169 168 170 169 jit_enabled = is_jit_enabled(); 170 + 171 + if (ac == 2 && strcmp(av[1], "-s") == 0) 172 + verifier_stats = true; 171 173 172 174 #define CALL 173 175 #include <prog_tests/tests.h>
+1
tools/testing/selftests/bpf/test_progs.h
··· 40 40 41 41 extern int error_cnt, pass_cnt; 42 42 extern bool jit_enabled; 43 + extern bool verifier_stats; 43 44 44 45 #define MAGIC_BYTES 123 45 46
+111 -25
tools/testing/selftests/bpf/test_tc_tunnel.sh
··· 15 15 readonly ns1_v6=fd::1 16 16 readonly ns2_v6=fd::2 17 17 18 + # Must match port used by bpf program 19 + readonly udpport=5555 20 + # MPLSoverUDP 21 + readonly mplsudpport=6635 22 + readonly mplsproto=137 23 + 18 24 readonly infile="$(mktemp)" 19 25 readonly outfile="$(mktemp)" 20 26 ··· 44 38 # clamp route to reserve room for tunnel headers 45 39 ip -netns "${ns1}" -4 route flush table main 46 40 ip -netns "${ns1}" -6 route flush table main 47 - ip -netns "${ns1}" -4 route add "${ns2_v4}" mtu 1476 dev veth1 48 - ip -netns "${ns1}" -6 route add "${ns2_v6}" mtu 1456 dev veth1 41 + ip -netns "${ns1}" -4 route add "${ns2_v4}" mtu 1458 dev veth1 42 + ip -netns "${ns1}" -6 route add "${ns2_v6}" mtu 1438 dev veth1 49 43 50 44 sleep 1 51 45 ··· 92 86 # no arguments: automated test, run all 93 87 if [[ "$#" -eq "0" ]]; then 94 88 echo "ipip" 95 - $0 ipv4 ipip 100 89 + $0 ipv4 ipip none 100 96 90 97 91 echo "ip6ip6" 98 - $0 ipv6 ip6tnl 100 92 + $0 ipv6 ip6tnl none 100 99 93 100 - echo "ip gre" 101 - $0 ipv4 gre 100 94 + for mac in none mpls eth ; do 95 + echo "ip gre $mac" 96 + $0 ipv4 gre $mac 100 102 97 103 - echo "ip6 gre" 104 - $0 ipv6 ip6gre 100 98 + echo "ip6 gre $mac" 99 + $0 ipv6 ip6gre $mac 100 105 100 106 - echo "ip gre gso" 107 - $0 ipv4 gre 2000 101 + echo "ip gre $mac gso" 102 + $0 ipv4 gre $mac 2000 108 103 109 - echo "ip6 gre gso" 110 - $0 ipv6 ip6gre 2000 104 + echo "ip6 gre $mac gso" 105 + $0 ipv6 ip6gre $mac 2000 106 + 107 + echo "ip udp $mac" 108 + $0 ipv4 udp $mac 100 109 + 110 + echo "ip6 udp $mac" 111 + $0 ipv6 ip6udp $mac 100 112 + 113 + echo "ip udp $mac gso" 114 + $0 ipv4 udp $mac 2000 115 + 116 + echo "ip6 udp $mac gso" 117 + $0 ipv6 ip6udp $mac 2000 118 + done 111 119 112 120 echo "OK. All tests passed" 113 121 exit 0 114 122 fi 115 123 116 - if [[ "$#" -ne "3" ]]; then 124 + if [[ "$#" -ne "4" ]]; then 117 125 echo "Usage: $0" 118 - echo " or: $0 <ipv4|ipv6> <tuntype> <data_len>" 126 + echo " or: $0 <ipv4|ipv6> <tuntype> <none|mpls|eth> <data_len>" 119 127 exit 1 120 128 fi 121 129 ··· 137 117 "ipv4") 138 118 readonly addr1="${ns1_v4}" 139 119 readonly addr2="${ns2_v4}" 140 - readonly netcat_opt=-4 120 + readonly ipproto=4 121 + readonly netcat_opt=-${ipproto} 122 + readonly foumod=fou 123 + readonly foutype=ipip 124 + readonly fouproto=4 125 + readonly fouproto_mpls=${mplsproto} 126 + readonly gretaptype=gretap 141 127 ;; 142 128 "ipv6") 143 129 readonly addr1="${ns1_v6}" 144 130 readonly addr2="${ns2_v6}" 145 - readonly netcat_opt=-6 131 + readonly ipproto=6 132 + readonly netcat_opt=-${ipproto} 133 + readonly foumod=fou6 134 + readonly foutype=ip6tnl 135 + readonly fouproto="41 -6" 136 + readonly fouproto_mpls="${mplsproto} -6" 137 + readonly gretaptype=ip6gretap 146 138 ;; 147 139 *) 148 140 echo "unknown arg: $1" ··· 163 131 esac 164 132 165 133 readonly tuntype=$2 166 - readonly datalen=$3 134 + readonly mac=$3 135 + readonly datalen=$4 167 136 168 - echo "encap ${addr1} to ${addr2}, type ${tuntype}, len ${datalen}" 137 + echo "encap ${addr1} to ${addr2}, type ${tuntype}, mac ${mac} len ${datalen}" 169 138 170 139 trap cleanup EXIT 171 140 ··· 183 150 ip netns exec "${ns1}" tc qdisc add dev veth1 clsact 184 151 ip netns exec "${ns1}" tc filter add dev veth1 egress \ 185 152 bpf direct-action object-file ./test_tc_tunnel.o \ 186 - section "encap_${tuntype}" 153 + section "encap_${tuntype}_${mac}" 187 154 echo "test bpf encap without decap (expect failure)" 188 155 server_listen 189 156 ! client_connect 190 157 158 + if [[ "$tuntype" =~ "udp" ]]; then 159 + # Set up fou tunnel. 160 + ttype="${foutype}" 161 + targs="encap fou encap-sport auto encap-dport $udpport" 162 + # fou may be a module; allow this to fail. 163 + modprobe "${foumod}" ||true 164 + if [[ "$mac" == "mpls" ]]; then 165 + dport=${mplsudpport} 166 + dproto=${fouproto_mpls} 167 + tmode="mode any ttl 255" 168 + else 169 + dport=${udpport} 170 + dproto=${fouproto} 171 + fi 172 + ip netns exec "${ns2}" ip fou add port $dport ipproto ${dproto} 173 + targs="encap fou encap-sport auto encap-dport $dport" 174 + elif [[ "$tuntype" =~ "gre" && "$mac" == "eth" ]]; then 175 + ttype=$gretaptype 176 + else 177 + ttype=$tuntype 178 + targs="" 179 + fi 180 + 191 181 # serverside, insert decap module 192 182 # server is still running 193 183 # client can connect again 194 - ip netns exec "${ns2}" ip link add dev testtun0 type "${tuntype}" \ 195 - remote "${addr1}" local "${addr2}" 184 + ip netns exec "${ns2}" ip link add name testtun0 type "${ttype}" \ 185 + ${tmode} remote "${addr1}" local "${addr2}" $targs 186 + 187 + expect_tun_fail=0 188 + 189 + if [[ "$tuntype" == "ip6udp" && "$mac" == "mpls" ]]; then 190 + # No support for MPLS IPv6 fou tunnel; expect failure. 191 + expect_tun_fail=1 192 + elif [[ "$tuntype" =~ "udp" && "$mac" == "eth" ]]; then 193 + # No support for TEB fou tunnel; expect failure. 194 + expect_tun_fail=1 195 + elif [[ "$tuntype" =~ "gre" && "$mac" == "eth" ]]; then 196 + # Share ethernet address between tunnel/veth2 so L2 decap works. 197 + ethaddr=$(ip netns exec "${ns2}" ip link show veth2 | \ 198 + awk '/ether/ { print $2 }') 199 + ip netns exec "${ns2}" ip link set testtun0 address $ethaddr 200 + elif [[ "$mac" == "mpls" ]]; then 201 + modprobe mpls_iptunnel ||true 202 + modprobe mpls_gso ||true 203 + ip netns exec "${ns2}" sysctl -qw net.mpls.platform_labels=65536 204 + ip netns exec "${ns2}" ip -f mpls route add 1000 dev lo 205 + ip netns exec "${ns2}" ip link set lo up 206 + ip netns exec "${ns2}" sysctl -qw net.mpls.conf.testtun0.input=1 207 + ip netns exec "${ns2}" sysctl -qw net.ipv4.conf.lo.rp_filter=0 208 + fi 209 + 196 210 # Because packets are decapped by the tunnel they arrive on testtun0 from 197 211 # the IP stack perspective. Ensure reverse path filtering is disabled 198 212 # otherwise we drop the TCP SYN as arriving on testtun0 instead of the ··· 249 169 # selected as the max of the "all" and device-specific values. 250 170 ip netns exec "${ns2}" sysctl -qw net.ipv4.conf.testtun0.rp_filter=0 251 171 ip netns exec "${ns2}" ip link set dev testtun0 up 252 - echo "test bpf encap with tunnel device decap" 253 - client_connect 254 - verify_data 172 + if [[ "$expect_tun_fail" == 1 ]]; then 173 + # This tunnel mode is not supported, so we expect failure. 174 + echo "test bpf encap with tunnel device decap (expect failure)" 175 + ! client_connect 176 + else 177 + echo "test bpf encap with tunnel device decap" 178 + client_connect 179 + verify_data 180 + server_listen 181 + fi 255 182 256 183 # serverside, use BPF for decap 257 184 ip netns exec "${ns2}" ip link del dev testtun0 258 185 ip netns exec "${ns2}" tc qdisc add dev veth2 clsact 259 186 ip netns exec "${ns2}" tc filter add dev veth2 ingress \ 260 187 bpf direct-action object-file ./test_tc_tunnel.o section decap 261 - server_listen 262 188 echo "test bpf encap with bpf decap" 263 189 client_connect 264 190 verify_data
+73 -13
tools/testing/selftests/bpf/test_verifier.c
··· 50 50 #include "../../../include/linux/filter.h" 51 51 52 52 #define MAX_INSNS BPF_MAXINSNS 53 + #define MAX_TEST_INSNS 1000000 53 54 #define MAX_FIXUPS 8 54 - #define MAX_NR_MAPS 14 55 + #define MAX_NR_MAPS 16 55 56 #define MAX_TEST_RUNS 8 56 57 #define POINTER_VALUE 0xcafe4all 57 58 #define TEST_DATA_LEN 64 ··· 67 66 struct bpf_test { 68 67 const char *descr; 69 68 struct bpf_insn insns[MAX_INSNS]; 69 + struct bpf_insn *fill_insns; 70 70 int fixup_map_hash_8b[MAX_FIXUPS]; 71 71 int fixup_map_hash_48b[MAX_FIXUPS]; 72 72 int fixup_map_hash_16b[MAX_FIXUPS]; ··· 82 80 int fixup_cgroup_storage[MAX_FIXUPS]; 83 81 int fixup_percpu_cgroup_storage[MAX_FIXUPS]; 84 82 int fixup_map_spin_lock[MAX_FIXUPS]; 83 + int fixup_map_array_ro[MAX_FIXUPS]; 84 + int fixup_map_array_wo[MAX_FIXUPS]; 85 + int fixup_map_array_small[MAX_FIXUPS]; 85 86 const char *errstr; 86 87 const char *errstr_unpriv; 87 88 uint32_t retval, retval_unpriv, insn_processed; 89 + int prog_len; 88 90 enum { 89 91 UNDEF, 90 92 ACCEPT, ··· 125 119 126 120 static void bpf_fill_ld_abs_vlan_push_pop(struct bpf_test *self) 127 121 { 128 - /* test: {skb->data[0], vlan_push} x 68 + {skb->data[0], vlan_pop} x 68 */ 122 + /* test: {skb->data[0], vlan_push} x 51 + {skb->data[0], vlan_pop} x 51 */ 129 123 #define PUSH_CNT 51 130 - unsigned int len = BPF_MAXINSNS; 131 - struct bpf_insn *insn = self->insns; 124 + /* jump range is limited to 16 bit. PUSH_CNT of ld_abs needs room */ 125 + unsigned int len = (1 << 15) - PUSH_CNT * 2 * 5 * 6; 126 + struct bpf_insn *insn = self->fill_insns; 132 127 int i = 0, j, k = 0; 133 128 134 129 insn[i++] = BPF_MOV64_REG(BPF_REG_6, BPF_REG_1); ··· 163 156 for (; i < len - 1; i++) 164 157 insn[i] = BPF_ALU32_IMM(BPF_MOV, BPF_REG_0, 0xbef); 165 158 insn[len - 1] = BPF_EXIT_INSN(); 159 + self->prog_len = len; 166 160 } 167 161 168 162 static void bpf_fill_jump_around_ld_abs(struct bpf_test *self) 169 163 { 170 - struct bpf_insn *insn = self->insns; 171 - unsigned int len = BPF_MAXINSNS; 164 + struct bpf_insn *insn = self->fill_insns; 165 + /* jump range is limited to 16 bit. every ld_abs is replaced by 6 insns */ 166 + unsigned int len = (1 << 15) / 6; 172 167 int i = 0; 173 168 174 169 insn[i++] = BPF_MOV64_REG(BPF_REG_6, BPF_REG_1); ··· 180 171 while (i < len - 1) 181 172 insn[i++] = BPF_LD_ABS(BPF_B, 1); 182 173 insn[i] = BPF_EXIT_INSN(); 174 + self->prog_len = i + 1; 183 175 } 184 176 185 177 static void bpf_fill_rand_ld_dw(struct bpf_test *self) 186 178 { 187 - struct bpf_insn *insn = self->insns; 179 + struct bpf_insn *insn = self->fill_insns; 188 180 uint64_t res = 0; 189 181 int i = 0; 190 182 ··· 203 193 insn[i++] = BPF_ALU64_IMM(BPF_RSH, BPF_REG_1, 32); 204 194 insn[i++] = BPF_ALU64_REG(BPF_XOR, BPF_REG_0, BPF_REG_1); 205 195 insn[i] = BPF_EXIT_INSN(); 196 + self->prog_len = i + 1; 206 197 res ^= (res >> 32); 207 198 self->retval = (uint32_t)res; 208 199 } ··· 288 277 return false; 289 278 } 290 279 291 - static int create_map(uint32_t type, uint32_t size_key, 292 - uint32_t size_value, uint32_t max_elem) 280 + static int __create_map(uint32_t type, uint32_t size_key, 281 + uint32_t size_value, uint32_t max_elem, 282 + uint32_t extra_flags) 293 283 { 294 284 int fd; 295 285 296 286 fd = bpf_create_map(type, size_key, size_value, max_elem, 297 - type == BPF_MAP_TYPE_HASH ? BPF_F_NO_PREALLOC : 0); 287 + (type == BPF_MAP_TYPE_HASH ? 288 + BPF_F_NO_PREALLOC : 0) | extra_flags); 298 289 if (fd < 0) { 299 290 if (skip_unsupported_map(type)) 300 291 return -1; ··· 304 291 } 305 292 306 293 return fd; 294 + } 295 + 296 + static int create_map(uint32_t type, uint32_t size_key, 297 + uint32_t size_value, uint32_t max_elem) 298 + { 299 + return __create_map(type, size_key, size_value, max_elem, 0); 307 300 } 308 301 309 302 static void update_map(int fd, int index) ··· 538 519 int *fixup_cgroup_storage = test->fixup_cgroup_storage; 539 520 int *fixup_percpu_cgroup_storage = test->fixup_percpu_cgroup_storage; 540 521 int *fixup_map_spin_lock = test->fixup_map_spin_lock; 522 + int *fixup_map_array_ro = test->fixup_map_array_ro; 523 + int *fixup_map_array_wo = test->fixup_map_array_wo; 524 + int *fixup_map_array_small = test->fixup_map_array_small; 541 525 542 - if (test->fill_helper) 526 + if (test->fill_helper) { 527 + test->fill_insns = calloc(MAX_TEST_INSNS, sizeof(struct bpf_insn)); 543 528 test->fill_helper(test); 529 + } 544 530 545 531 /* Allocating HTs with 1 elem is fine here, since we only test 546 532 * for verifier and not do a runtime lookup, so the only thing ··· 666 642 fixup_map_spin_lock++; 667 643 } while (*fixup_map_spin_lock); 668 644 } 645 + if (*fixup_map_array_ro) { 646 + map_fds[14] = __create_map(BPF_MAP_TYPE_ARRAY, sizeof(int), 647 + sizeof(struct test_val), 1, 648 + BPF_F_RDONLY_PROG); 649 + update_map(map_fds[14], 0); 650 + do { 651 + prog[*fixup_map_array_ro].imm = map_fds[14]; 652 + fixup_map_array_ro++; 653 + } while (*fixup_map_array_ro); 654 + } 655 + if (*fixup_map_array_wo) { 656 + map_fds[15] = __create_map(BPF_MAP_TYPE_ARRAY, sizeof(int), 657 + sizeof(struct test_val), 1, 658 + BPF_F_WRONLY_PROG); 659 + update_map(map_fds[15], 0); 660 + do { 661 + prog[*fixup_map_array_wo].imm = map_fds[15]; 662 + fixup_map_array_wo++; 663 + } while (*fixup_map_array_wo); 664 + } 665 + if (*fixup_map_array_small) { 666 + map_fds[16] = __create_map(BPF_MAP_TYPE_ARRAY, sizeof(int), 667 + 1, 1, 0); 668 + update_map(map_fds[16], 0); 669 + do { 670 + prog[*fixup_map_array_small].imm = map_fds[16]; 671 + fixup_map_array_small++; 672 + } while (*fixup_map_array_small); 673 + } 669 674 } 670 675 671 676 static int set_admin(bool admin) ··· 771 718 prog_type = BPF_PROG_TYPE_SOCKET_FILTER; 772 719 fixup_skips = skips; 773 720 do_test_fixup(test, prog_type, prog, map_fds); 721 + if (test->fill_insns) { 722 + prog = test->fill_insns; 723 + prog_len = test->prog_len; 724 + } else { 725 + prog_len = probe_filter_length(prog); 726 + } 774 727 /* If there were some map skips during fixup due to missing bpf 775 728 * features, skip this test. 776 729 */ 777 730 if (fixup_skips != skips) 778 731 return; 779 - prog_len = probe_filter_length(prog); 780 732 781 733 pflags = 0; 782 734 if (test->flags & F_LOAD_WITH_STRICT_ALIGNMENT) ··· 789 731 if (test->flags & F_NEEDS_EFFICIENT_UNALIGNED_ACCESS) 790 732 pflags |= BPF_F_ANY_ALIGNMENT; 791 733 fd_prog = bpf_verify_program(prog_type, prog, prog_len, pflags, 792 - "GPL", 0, bpf_vlog, sizeof(bpf_vlog), 1); 734 + "GPL", 0, bpf_vlog, sizeof(bpf_vlog), 4); 793 735 if (fd_prog < 0 && !bpf_probe_prog_type(prog_type, 0)) { 794 736 printf("SKIP (unsupported program type %d)\n", prog_type); 795 737 skips++; ··· 888 830 goto fail_log; 889 831 } 890 832 close_fds: 833 + if (test->fill_insns) 834 + free(test->fill_insns); 891 835 close(fd_prog); 892 836 for (i = 0; i < MAX_NR_MAPS; i++) 893 837 close(map_fds[i]);
+4
tools/testing/selftests/bpf/trace_helpers.c
··· 52 52 int start = 0, end = sym_cnt; 53 53 int result; 54 54 55 + /* kallsyms not loaded. return NULL */ 56 + if (sym_cnt <= 0) 57 + return NULL; 58 + 55 59 while (start < end) { 56 60 size_t mid = start + (end - start) / 2; 57 61
+159
tools/testing/selftests/bpf/verifier/array_access.c
··· 217 217 .result = REJECT, 218 218 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 219 219 }, 220 + { 221 + "valid read map access into a read-only array 1", 222 + .insns = { 223 + BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 224 + BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 225 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 226 + BPF_LD_MAP_FD(BPF_REG_1, 0), 227 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), 228 + BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1), 229 + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0), 230 + BPF_EXIT_INSN(), 231 + }, 232 + .fixup_map_array_ro = { 3 }, 233 + .result = ACCEPT, 234 + .retval = 28, 235 + }, 236 + { 237 + "valid read map access into a read-only array 2", 238 + .insns = { 239 + BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 240 + BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 241 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 242 + BPF_LD_MAP_FD(BPF_REG_1, 0), 243 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), 244 + BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6), 245 + 246 + BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 247 + BPF_MOV64_IMM(BPF_REG_2, 4), 248 + BPF_MOV64_IMM(BPF_REG_3, 0), 249 + BPF_MOV64_IMM(BPF_REG_4, 0), 250 + BPF_MOV64_IMM(BPF_REG_5, 0), 251 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 252 + BPF_FUNC_csum_diff), 253 + BPF_EXIT_INSN(), 254 + }, 255 + .prog_type = BPF_PROG_TYPE_SCHED_CLS, 256 + .fixup_map_array_ro = { 3 }, 257 + .result = ACCEPT, 258 + .retval = -29, 259 + }, 260 + { 261 + "invalid write map access into a read-only array 1", 262 + .insns = { 263 + BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 264 + BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 265 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 266 + BPF_LD_MAP_FD(BPF_REG_1, 0), 267 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), 268 + BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1), 269 + BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 42), 270 + BPF_EXIT_INSN(), 271 + }, 272 + .fixup_map_array_ro = { 3 }, 273 + .result = REJECT, 274 + .errstr = "write into map forbidden", 275 + }, 276 + { 277 + "invalid write map access into a read-only array 2", 278 + .insns = { 279 + BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), 280 + BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 281 + BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 282 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 283 + BPF_LD_MAP_FD(BPF_REG_1, 0), 284 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), 285 + BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 5), 286 + BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), 287 + BPF_MOV64_IMM(BPF_REG_2, 0), 288 + BPF_MOV64_REG(BPF_REG_3, BPF_REG_0), 289 + BPF_MOV64_IMM(BPF_REG_4, 8), 290 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 291 + BPF_FUNC_skb_load_bytes), 292 + BPF_EXIT_INSN(), 293 + }, 294 + .prog_type = BPF_PROG_TYPE_SCHED_CLS, 295 + .fixup_map_array_ro = { 4 }, 296 + .result = REJECT, 297 + .errstr = "write into map forbidden", 298 + }, 299 + { 300 + "valid write map access into a write-only array 1", 301 + .insns = { 302 + BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 303 + BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 304 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 305 + BPF_LD_MAP_FD(BPF_REG_1, 0), 306 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), 307 + BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1), 308 + BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 42), 309 + BPF_MOV64_IMM(BPF_REG_0, 1), 310 + BPF_EXIT_INSN(), 311 + }, 312 + .fixup_map_array_wo = { 3 }, 313 + .result = ACCEPT, 314 + .retval = 1, 315 + }, 316 + { 317 + "valid write map access into a write-only array 2", 318 + .insns = { 319 + BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), 320 + BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 321 + BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 322 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 323 + BPF_LD_MAP_FD(BPF_REG_1, 0), 324 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), 325 + BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 5), 326 + BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), 327 + BPF_MOV64_IMM(BPF_REG_2, 0), 328 + BPF_MOV64_REG(BPF_REG_3, BPF_REG_0), 329 + BPF_MOV64_IMM(BPF_REG_4, 8), 330 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 331 + BPF_FUNC_skb_load_bytes), 332 + BPF_EXIT_INSN(), 333 + }, 334 + .prog_type = BPF_PROG_TYPE_SCHED_CLS, 335 + .fixup_map_array_wo = { 4 }, 336 + .result = ACCEPT, 337 + .retval = 0, 338 + }, 339 + { 340 + "invalid read map access into a write-only array 1", 341 + .insns = { 342 + BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 343 + BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 344 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 345 + BPF_LD_MAP_FD(BPF_REG_1, 0), 346 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), 347 + BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1), 348 + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0), 349 + BPF_EXIT_INSN(), 350 + }, 351 + .fixup_map_array_wo = { 3 }, 352 + .result = REJECT, 353 + .errstr = "read from map forbidden", 354 + }, 355 + { 356 + "invalid read map access into a write-only array 2", 357 + .insns = { 358 + BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 359 + BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 360 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 361 + BPF_LD_MAP_FD(BPF_REG_1, 0), 362 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), 363 + BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6), 364 + 365 + BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 366 + BPF_MOV64_IMM(BPF_REG_2, 4), 367 + BPF_MOV64_IMM(BPF_REG_3, 0), 368 + BPF_MOV64_IMM(BPF_REG_4, 0), 369 + BPF_MOV64_IMM(BPF_REG_5, 0), 370 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 371 + BPF_FUNC_csum_diff), 372 + BPF_EXIT_INSN(), 373 + }, 374 + .prog_type = BPF_PROG_TYPE_SCHED_CLS, 375 + .fixup_map_array_wo = { 3 }, 376 + .result = REJECT, 377 + .errstr = "read from map forbidden", 378 + },
-1
tools/testing/selftests/bpf/verifier/ctx_skb.c
··· 705 705 .errstr = "invalid bpf_context access", 706 706 .result = REJECT, 707 707 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 708 - .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 709 708 }, 710 709 { 711 710 "check cb access: half, wrong type",
+347
tools/testing/selftests/bpf/verifier/direct_value_access.c
··· 1 + { 2 + "direct map access, write test 1", 3 + .insns = { 4 + BPF_MOV64_IMM(BPF_REG_0, 1), 5 + BPF_LD_MAP_VALUE(BPF_REG_1, 0, 0), 6 + BPF_ST_MEM(BPF_DW, BPF_REG_1, 0, 4242), 7 + BPF_EXIT_INSN(), 8 + }, 9 + .fixup_map_array_48b = { 1 }, 10 + .result = ACCEPT, 11 + .retval = 1, 12 + }, 13 + { 14 + "direct map access, write test 2", 15 + .insns = { 16 + BPF_MOV64_IMM(BPF_REG_0, 1), 17 + BPF_LD_MAP_VALUE(BPF_REG_1, 0, 8), 18 + BPF_ST_MEM(BPF_DW, BPF_REG_1, 0, 4242), 19 + BPF_EXIT_INSN(), 20 + }, 21 + .fixup_map_array_48b = { 1 }, 22 + .result = ACCEPT, 23 + .retval = 1, 24 + }, 25 + { 26 + "direct map access, write test 3", 27 + .insns = { 28 + BPF_MOV64_IMM(BPF_REG_0, 1), 29 + BPF_LD_MAP_VALUE(BPF_REG_1, 0, 8), 30 + BPF_ST_MEM(BPF_DW, BPF_REG_1, 8, 4242), 31 + BPF_EXIT_INSN(), 32 + }, 33 + .fixup_map_array_48b = { 1 }, 34 + .result = ACCEPT, 35 + .retval = 1, 36 + }, 37 + { 38 + "direct map access, write test 4", 39 + .insns = { 40 + BPF_MOV64_IMM(BPF_REG_0, 1), 41 + BPF_LD_MAP_VALUE(BPF_REG_1, 0, 40), 42 + BPF_ST_MEM(BPF_DW, BPF_REG_1, 0, 4242), 43 + BPF_EXIT_INSN(), 44 + }, 45 + .fixup_map_array_48b = { 1 }, 46 + .result = ACCEPT, 47 + .retval = 1, 48 + }, 49 + { 50 + "direct map access, write test 5", 51 + .insns = { 52 + BPF_MOV64_IMM(BPF_REG_0, 1), 53 + BPF_LD_MAP_VALUE(BPF_REG_1, 0, 32), 54 + BPF_ST_MEM(BPF_DW, BPF_REG_1, 8, 4242), 55 + BPF_EXIT_INSN(), 56 + }, 57 + .fixup_map_array_48b = { 1 }, 58 + .result = ACCEPT, 59 + .retval = 1, 60 + }, 61 + { 62 + "direct map access, write test 6", 63 + .insns = { 64 + BPF_MOV64_IMM(BPF_REG_0, 1), 65 + BPF_LD_MAP_VALUE(BPF_REG_1, 0, 40), 66 + BPF_ST_MEM(BPF_DW, BPF_REG_1, 4, 4242), 67 + BPF_EXIT_INSN(), 68 + }, 69 + .fixup_map_array_48b = { 1 }, 70 + .result = REJECT, 71 + .errstr = "R1 min value is outside of the array range", 72 + }, 73 + { 74 + "direct map access, write test 7", 75 + .insns = { 76 + BPF_MOV64_IMM(BPF_REG_0, 1), 77 + BPF_LD_MAP_VALUE(BPF_REG_1, 0, -1), 78 + BPF_ST_MEM(BPF_DW, BPF_REG_1, 4, 4242), 79 + BPF_EXIT_INSN(), 80 + }, 81 + .fixup_map_array_48b = { 1 }, 82 + .result = REJECT, 83 + .errstr = "direct value offset of 4294967295 is not allowed", 84 + }, 85 + { 86 + "direct map access, write test 8", 87 + .insns = { 88 + BPF_MOV64_IMM(BPF_REG_0, 1), 89 + BPF_LD_MAP_VALUE(BPF_REG_1, 0, 1), 90 + BPF_ST_MEM(BPF_DW, BPF_REG_1, -1, 4242), 91 + BPF_EXIT_INSN(), 92 + }, 93 + .fixup_map_array_48b = { 1 }, 94 + .result = ACCEPT, 95 + .retval = 1, 96 + }, 97 + { 98 + "direct map access, write test 9", 99 + .insns = { 100 + BPF_MOV64_IMM(BPF_REG_0, 1), 101 + BPF_LD_MAP_VALUE(BPF_REG_1, 0, 48), 102 + BPF_ST_MEM(BPF_DW, BPF_REG_1, 0, 4242), 103 + BPF_EXIT_INSN(), 104 + }, 105 + .fixup_map_array_48b = { 1 }, 106 + .result = REJECT, 107 + .errstr = "invalid access to map value pointer", 108 + }, 109 + { 110 + "direct map access, write test 10", 111 + .insns = { 112 + BPF_MOV64_IMM(BPF_REG_0, 1), 113 + BPF_LD_MAP_VALUE(BPF_REG_1, 0, 47), 114 + BPF_ST_MEM(BPF_B, BPF_REG_1, 0, 4), 115 + BPF_EXIT_INSN(), 116 + }, 117 + .fixup_map_array_48b = { 1 }, 118 + .result = ACCEPT, 119 + .retval = 1, 120 + }, 121 + { 122 + "direct map access, write test 11", 123 + .insns = { 124 + BPF_MOV64_IMM(BPF_REG_0, 1), 125 + BPF_LD_MAP_VALUE(BPF_REG_1, 0, 48), 126 + BPF_ST_MEM(BPF_B, BPF_REG_1, 0, 4), 127 + BPF_EXIT_INSN(), 128 + }, 129 + .fixup_map_array_48b = { 1 }, 130 + .result = REJECT, 131 + .errstr = "invalid access to map value pointer", 132 + }, 133 + { 134 + "direct map access, write test 12", 135 + .insns = { 136 + BPF_MOV64_IMM(BPF_REG_0, 1), 137 + BPF_LD_MAP_VALUE(BPF_REG_1, 0, (1<<29)), 138 + BPF_ST_MEM(BPF_B, BPF_REG_1, 0, 4), 139 + BPF_EXIT_INSN(), 140 + }, 141 + .fixup_map_array_48b = { 1 }, 142 + .result = REJECT, 143 + .errstr = "direct value offset of 536870912 is not allowed", 144 + }, 145 + { 146 + "direct map access, write test 13", 147 + .insns = { 148 + BPF_MOV64_IMM(BPF_REG_0, 1), 149 + BPF_LD_MAP_VALUE(BPF_REG_1, 0, (1<<29)-1), 150 + BPF_ST_MEM(BPF_B, BPF_REG_1, 0, 4), 151 + BPF_EXIT_INSN(), 152 + }, 153 + .fixup_map_array_48b = { 1 }, 154 + .result = REJECT, 155 + .errstr = "invalid access to map value pointer, value_size=48 off=536870911", 156 + }, 157 + { 158 + "direct map access, write test 14", 159 + .insns = { 160 + BPF_MOV64_IMM(BPF_REG_0, 1), 161 + BPF_LD_MAP_VALUE(BPF_REG_1, 0, 47), 162 + BPF_LD_MAP_VALUE(BPF_REG_2, 0, 46), 163 + BPF_ST_MEM(BPF_H, BPF_REG_2, 0, 0xffff), 164 + BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1, 0), 165 + BPF_EXIT_INSN(), 166 + }, 167 + .fixup_map_array_48b = { 1, 3 }, 168 + .result = ACCEPT, 169 + .retval = 0xff, 170 + }, 171 + { 172 + "direct map access, write test 15", 173 + .insns = { 174 + BPF_MOV64_IMM(BPF_REG_0, 1), 175 + BPF_LD_MAP_VALUE(BPF_REG_1, 0, 46), 176 + BPF_LD_MAP_VALUE(BPF_REG_2, 0, 46), 177 + BPF_ST_MEM(BPF_H, BPF_REG_2, 0, 0xffff), 178 + BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1, 0), 179 + BPF_EXIT_INSN(), 180 + }, 181 + .fixup_map_array_48b = { 1, 3 }, 182 + .result = ACCEPT, 183 + .retval = 0xffff, 184 + }, 185 + { 186 + "direct map access, write test 16", 187 + .insns = { 188 + BPF_MOV64_IMM(BPF_REG_0, 1), 189 + BPF_LD_MAP_VALUE(BPF_REG_1, 0, 46), 190 + BPF_LD_MAP_VALUE(BPF_REG_2, 0, 47), 191 + BPF_ST_MEM(BPF_H, BPF_REG_2, 0, 0xffff), 192 + BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1, 0), 193 + BPF_EXIT_INSN(), 194 + }, 195 + .fixup_map_array_48b = { 1, 3 }, 196 + .result = REJECT, 197 + .errstr = "invalid access to map value, value_size=48 off=47 size=2", 198 + }, 199 + { 200 + "direct map access, write test 17", 201 + .insns = { 202 + BPF_MOV64_IMM(BPF_REG_0, 1), 203 + BPF_LD_MAP_VALUE(BPF_REG_1, 0, 46), 204 + BPF_LD_MAP_VALUE(BPF_REG_2, 0, 46), 205 + BPF_ST_MEM(BPF_H, BPF_REG_2, 1, 0xffff), 206 + BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1, 0), 207 + BPF_EXIT_INSN(), 208 + }, 209 + .fixup_map_array_48b = { 1, 3 }, 210 + .result = REJECT, 211 + .errstr = "invalid access to map value, value_size=48 off=47 size=2", 212 + }, 213 + { 214 + "direct map access, write test 18", 215 + .insns = { 216 + BPF_MOV64_IMM(BPF_REG_0, 1), 217 + BPF_LD_MAP_VALUE(BPF_REG_1, 0, 0), 218 + BPF_ST_MEM(BPF_H, BPF_REG_1, 0, 42), 219 + BPF_EXIT_INSN(), 220 + }, 221 + .fixup_map_array_small = { 1 }, 222 + .result = REJECT, 223 + .errstr = "R1 min value is outside of the array range", 224 + }, 225 + { 226 + "direct map access, write test 19", 227 + .insns = { 228 + BPF_MOV64_IMM(BPF_REG_0, 1), 229 + BPF_LD_MAP_VALUE(BPF_REG_1, 0, 0), 230 + BPF_ST_MEM(BPF_B, BPF_REG_1, 0, 42), 231 + BPF_EXIT_INSN(), 232 + }, 233 + .fixup_map_array_small = { 1 }, 234 + .result = ACCEPT, 235 + .retval = 1, 236 + }, 237 + { 238 + "direct map access, write test 20", 239 + .insns = { 240 + BPF_MOV64_IMM(BPF_REG_0, 1), 241 + BPF_LD_MAP_VALUE(BPF_REG_1, 0, 1), 242 + BPF_ST_MEM(BPF_B, BPF_REG_1, 0, 42), 243 + BPF_EXIT_INSN(), 244 + }, 245 + .fixup_map_array_small = { 1 }, 246 + .result = REJECT, 247 + .errstr = "invalid access to map value pointer", 248 + }, 249 + { 250 + "direct map access, invalid insn test 1", 251 + .insns = { 252 + BPF_MOV64_IMM(BPF_REG_0, 1), 253 + BPF_LD_IMM64_RAW_FULL(BPF_REG_1, BPF_PSEUDO_MAP_VALUE, 0, 1, 0, 47), 254 + BPF_EXIT_INSN(), 255 + }, 256 + .fixup_map_array_48b = { 1 }, 257 + .result = REJECT, 258 + .errstr = "invalid bpf_ld_imm64 insn", 259 + }, 260 + { 261 + "direct map access, invalid insn test 2", 262 + .insns = { 263 + BPF_MOV64_IMM(BPF_REG_0, 1), 264 + BPF_LD_IMM64_RAW_FULL(BPF_REG_1, BPF_PSEUDO_MAP_VALUE, 1, 0, 0, 47), 265 + BPF_EXIT_INSN(), 266 + }, 267 + .fixup_map_array_48b = { 1 }, 268 + .result = REJECT, 269 + .errstr = "BPF_LD_IMM64 uses reserved fields", 270 + }, 271 + { 272 + "direct map access, invalid insn test 3", 273 + .insns = { 274 + BPF_MOV64_IMM(BPF_REG_0, 1), 275 + BPF_LD_IMM64_RAW_FULL(BPF_REG_1, BPF_PSEUDO_MAP_VALUE, ~0, 0, 0, 47), 276 + BPF_EXIT_INSN(), 277 + }, 278 + .fixup_map_array_48b = { 1 }, 279 + .result = REJECT, 280 + .errstr = "BPF_LD_IMM64 uses reserved fields", 281 + }, 282 + { 283 + "direct map access, invalid insn test 4", 284 + .insns = { 285 + BPF_MOV64_IMM(BPF_REG_0, 1), 286 + BPF_LD_IMM64_RAW_FULL(BPF_REG_1, BPF_PSEUDO_MAP_VALUE, 0, ~0, 0, 47), 287 + BPF_EXIT_INSN(), 288 + }, 289 + .fixup_map_array_48b = { 1 }, 290 + .result = REJECT, 291 + .errstr = "invalid bpf_ld_imm64 insn", 292 + }, 293 + { 294 + "direct map access, invalid insn test 5", 295 + .insns = { 296 + BPF_MOV64_IMM(BPF_REG_0, 1), 297 + BPF_LD_IMM64_RAW_FULL(BPF_REG_1, BPF_PSEUDO_MAP_VALUE, ~0, ~0, 0, 47), 298 + BPF_EXIT_INSN(), 299 + }, 300 + .fixup_map_array_48b = { 1 }, 301 + .result = REJECT, 302 + .errstr = "invalid bpf_ld_imm64 insn", 303 + }, 304 + { 305 + "direct map access, invalid insn test 6", 306 + .insns = { 307 + BPF_MOV64_IMM(BPF_REG_0, 1), 308 + BPF_LD_IMM64_RAW_FULL(BPF_REG_1, BPF_PSEUDO_MAP_FD, ~0, 0, 0, 0), 309 + BPF_EXIT_INSN(), 310 + }, 311 + .fixup_map_array_48b = { 1 }, 312 + .result = REJECT, 313 + .errstr = "BPF_LD_IMM64 uses reserved fields", 314 + }, 315 + { 316 + "direct map access, invalid insn test 7", 317 + .insns = { 318 + BPF_MOV64_IMM(BPF_REG_0, 1), 319 + BPF_LD_IMM64_RAW_FULL(BPF_REG_1, BPF_PSEUDO_MAP_FD, 0, ~0, 0, 0), 320 + BPF_EXIT_INSN(), 321 + }, 322 + .fixup_map_array_48b = { 1 }, 323 + .result = REJECT, 324 + .errstr = "invalid bpf_ld_imm64 insn", 325 + }, 326 + { 327 + "direct map access, invalid insn test 8", 328 + .insns = { 329 + BPF_MOV64_IMM(BPF_REG_0, 1), 330 + BPF_LD_IMM64_RAW_FULL(BPF_REG_1, BPF_PSEUDO_MAP_FD, ~0, ~0, 0, 0), 331 + BPF_EXIT_INSN(), 332 + }, 333 + .fixup_map_array_48b = { 1 }, 334 + .result = REJECT, 335 + .errstr = "invalid bpf_ld_imm64 insn", 336 + }, 337 + { 338 + "direct map access, invalid insn test 9", 339 + .insns = { 340 + BPF_MOV64_IMM(BPF_REG_0, 1), 341 + BPF_LD_IMM64_RAW_FULL(BPF_REG_1, BPF_PSEUDO_MAP_FD, 0, 0, 0, 47), 342 + BPF_EXIT_INSN(), 343 + }, 344 + .fixup_map_array_48b = { 1 }, 345 + .result = REJECT, 346 + .errstr = "unrecognized bpf_ld_imm64 insn", 347 + },
+9
tools/testing/selftests/bpf/verifier/ld_dw.c
··· 34 34 .result = ACCEPT, 35 35 .retval = 5, 36 36 }, 37 + { 38 + "ld_dw: xor semi-random 64 bit imms, test 5", 39 + .insns = { }, 40 + .data = { }, 41 + .fill_helper = bpf_fill_rand_ld_dw, 42 + .prog_type = BPF_PROG_TYPE_SCHED_CLS, 43 + .result = ACCEPT, 44 + .retval = 1000000 - 6, 45 + },
+184 -2
tools/testing/selftests/bpf/verifier/var_off.c
··· 40 40 .prog_type = BPF_PROG_TYPE_LWT_IN, 41 41 }, 42 42 { 43 - "indirect variable-offset stack access", 43 + "indirect variable-offset stack access, unbounded", 44 + .insns = { 45 + BPF_MOV64_IMM(BPF_REG_2, 6), 46 + BPF_MOV64_IMM(BPF_REG_3, 28), 47 + /* Fill the top 16 bytes of the stack. */ 48 + BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, 0), 49 + BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 50 + /* Get an unknown value. */ 51 + BPF_LDX_MEM(BPF_DW, BPF_REG_4, BPF_REG_1, offsetof(struct bpf_sock_ops, 52 + bytes_received)), 53 + /* Check the lower bound but don't check the upper one. */ 54 + BPF_JMP_IMM(BPF_JSLT, BPF_REG_4, 0, 4), 55 + /* Point the lower bound to initialized stack. Offset is now in range 56 + * from fp-16 to fp+0x7fffffffffffffef, i.e. max value is unbounded. 57 + */ 58 + BPF_ALU64_IMM(BPF_SUB, BPF_REG_4, 16), 59 + BPF_ALU64_REG(BPF_ADD, BPF_REG_4, BPF_REG_10), 60 + BPF_MOV64_IMM(BPF_REG_5, 8), 61 + /* Dereference it indirectly. */ 62 + BPF_EMIT_CALL(BPF_FUNC_getsockopt), 63 + BPF_MOV64_IMM(BPF_REG_0, 0), 64 + BPF_EXIT_INSN(), 65 + }, 66 + .errstr = "R4 unbounded indirect variable offset stack access", 67 + .result = REJECT, 68 + .prog_type = BPF_PROG_TYPE_SOCK_OPS, 69 + }, 70 + { 71 + "indirect variable-offset stack access, max out of bound", 44 72 .insns = { 45 73 /* Fill the top 8 bytes of the stack */ 46 74 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), ··· 88 60 BPF_EXIT_INSN(), 89 61 }, 90 62 .fixup_map_hash_8b = { 5 }, 91 - .errstr = "variable stack read R2", 63 + .errstr = "R2 max value is outside of stack bound", 92 64 .result = REJECT, 65 + .prog_type = BPF_PROG_TYPE_LWT_IN, 66 + }, 67 + { 68 + "indirect variable-offset stack access, min out of bound", 69 + .insns = { 70 + /* Fill the top 8 bytes of the stack */ 71 + BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 72 + /* Get an unknown value */ 73 + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0), 74 + /* Make it small and 4-byte aligned */ 75 + BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 4), 76 + BPF_ALU64_IMM(BPF_SUB, BPF_REG_2, 516), 77 + /* add it to fp. We now have either fp-516 or fp-512, but 78 + * we don't know which 79 + */ 80 + BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_10), 81 + /* dereference it indirectly */ 82 + BPF_LD_MAP_FD(BPF_REG_1, 0), 83 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), 84 + BPF_MOV64_IMM(BPF_REG_0, 0), 85 + BPF_EXIT_INSN(), 86 + }, 87 + .fixup_map_hash_8b = { 5 }, 88 + .errstr = "R2 min value is outside of stack bound", 89 + .result = REJECT, 90 + .prog_type = BPF_PROG_TYPE_LWT_IN, 91 + }, 92 + { 93 + "indirect variable-offset stack access, max_off+size > max_initialized", 94 + .insns = { 95 + /* Fill only the second from top 8 bytes of the stack. */ 96 + BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, 0), 97 + /* Get an unknown value. */ 98 + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0), 99 + /* Make it small and 4-byte aligned. */ 100 + BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 4), 101 + BPF_ALU64_IMM(BPF_SUB, BPF_REG_2, 16), 102 + /* Add it to fp. We now have either fp-12 or fp-16, but we don't know 103 + * which. fp-12 size 8 is partially uninitialized stack. 104 + */ 105 + BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_10), 106 + /* Dereference it indirectly. */ 107 + BPF_LD_MAP_FD(BPF_REG_1, 0), 108 + BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem), 109 + BPF_MOV64_IMM(BPF_REG_0, 0), 110 + BPF_EXIT_INSN(), 111 + }, 112 + .fixup_map_hash_8b = { 5 }, 113 + .errstr = "invalid indirect read from stack var_off", 114 + .result = REJECT, 115 + .prog_type = BPF_PROG_TYPE_LWT_IN, 116 + }, 117 + { 118 + "indirect variable-offset stack access, min_off < min_initialized", 119 + .insns = { 120 + /* Fill only the top 8 bytes of the stack. */ 121 + BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 122 + /* Get an unknown value */ 123 + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0), 124 + /* Make it small and 4-byte aligned. */ 125 + BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 4), 126 + BPF_ALU64_IMM(BPF_SUB, BPF_REG_2, 16), 127 + /* Add it to fp. We now have either fp-12 or fp-16, but we don't know 128 + * which. fp-16 size 8 is partially uninitialized stack. 129 + */ 130 + BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_10), 131 + /* Dereference it indirectly. */ 132 + BPF_LD_MAP_FD(BPF_REG_1, 0), 133 + BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem), 134 + BPF_MOV64_IMM(BPF_REG_0, 0), 135 + BPF_EXIT_INSN(), 136 + }, 137 + .fixup_map_hash_8b = { 5 }, 138 + .errstr = "invalid indirect read from stack var_off", 139 + .result = REJECT, 140 + .prog_type = BPF_PROG_TYPE_LWT_IN, 141 + }, 142 + { 143 + "indirect variable-offset stack access, priv vs unpriv", 144 + .insns = { 145 + /* Fill the top 16 bytes of the stack. */ 146 + BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, 0), 147 + BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 148 + /* Get an unknown value. */ 149 + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0), 150 + /* Make it small and 4-byte aligned. */ 151 + BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 4), 152 + BPF_ALU64_IMM(BPF_SUB, BPF_REG_2, 16), 153 + /* Add it to fp. We now have either fp-12 or fp-16, we don't know 154 + * which, but either way it points to initialized stack. 155 + */ 156 + BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_10), 157 + /* Dereference it indirectly. */ 158 + BPF_LD_MAP_FD(BPF_REG_1, 0), 159 + BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem), 160 + BPF_MOV64_IMM(BPF_REG_0, 0), 161 + BPF_EXIT_INSN(), 162 + }, 163 + .fixup_map_hash_8b = { 6 }, 164 + .errstr_unpriv = "R2 stack pointer arithmetic goes out of range, prohibited for !root", 165 + .result_unpriv = REJECT, 166 + .result = ACCEPT, 167 + .prog_type = BPF_PROG_TYPE_CGROUP_SKB, 168 + }, 169 + { 170 + "indirect variable-offset stack access, uninitialized", 171 + .insns = { 172 + BPF_MOV64_IMM(BPF_REG_2, 6), 173 + BPF_MOV64_IMM(BPF_REG_3, 28), 174 + /* Fill the top 16 bytes of the stack. */ 175 + BPF_ST_MEM(BPF_W, BPF_REG_10, -16, 0), 176 + BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 177 + /* Get an unknown value. */ 178 + BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_1, 0), 179 + /* Make it small and 4-byte aligned. */ 180 + BPF_ALU64_IMM(BPF_AND, BPF_REG_4, 4), 181 + BPF_ALU64_IMM(BPF_SUB, BPF_REG_4, 16), 182 + /* Add it to fp. We now have either fp-12 or fp-16, we don't know 183 + * which, but either way it points to initialized stack. 184 + */ 185 + BPF_ALU64_REG(BPF_ADD, BPF_REG_4, BPF_REG_10), 186 + BPF_MOV64_IMM(BPF_REG_5, 8), 187 + /* Dereference it indirectly. */ 188 + BPF_EMIT_CALL(BPF_FUNC_getsockopt), 189 + BPF_MOV64_IMM(BPF_REG_0, 0), 190 + BPF_EXIT_INSN(), 191 + }, 192 + .errstr = "invalid indirect read from stack var_off", 193 + .result = REJECT, 194 + .prog_type = BPF_PROG_TYPE_SOCK_OPS, 195 + }, 196 + { 197 + "indirect variable-offset stack access, ok", 198 + .insns = { 199 + /* Fill the top 16 bytes of the stack. */ 200 + BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, 0), 201 + BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 202 + /* Get an unknown value. */ 203 + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0), 204 + /* Make it small and 4-byte aligned. */ 205 + BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 4), 206 + BPF_ALU64_IMM(BPF_SUB, BPF_REG_2, 16), 207 + /* Add it to fp. We now have either fp-12 or fp-16, we don't know 208 + * which, but either way it points to initialized stack. 209 + */ 210 + BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_10), 211 + /* Dereference it indirectly. */ 212 + BPF_LD_MAP_FD(BPF_REG_1, 0), 213 + BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem), 214 + BPF_MOV64_IMM(BPF_REG_0, 0), 215 + BPF_EXIT_INSN(), 216 + }, 217 + .fixup_map_hash_8b = { 6 }, 218 + .result = ACCEPT, 93 219 .prog_type = BPF_PROG_TYPE_LWT_IN, 94 220 },