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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'for-netdev' of https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next

Daniel Borkmann says:

====================
pull-request: bpf-next 2024-07-12

We've added 23 non-merge commits during the last 3 day(s) which contain
a total of 18 files changed, 234 insertions(+), 243 deletions(-).

The main changes are:

1) Improve BPF verifier by utilizing overflow.h helpers to check
for overflows, from Shung-Hsi Yu.

2) Fix NULL pointer dereference in resolve_prog_type() for BPF_PROG_TYPE_EXT
when attr->attach_prog_fd was not specified, from Tengda Wu.

3) Fix arm64 BPF JIT when generating code for BPF trampolines with
BPF_TRAMP_F_CALL_ORIG which corrupted upper address bits,
from Puranjay Mohan.

4) Remove test_run callback from lwt_seg6local_prog_ops which never worked
in the first place and caused syzbot reports,
from Sebastian Andrzej Siewior.

5) Relax BPF verifier to accept non-zero offset on KF_TRUSTED_ARGS/
/KF_RCU-typed BPF kfuncs, from Matt Bobrowski.

6) Fix a long standing bug in libbpf with regards to handling of BPF
skeleton's forward and backward compatibility, from Andrii Nakryiko.

7) Annotate btf_{seq,snprintf}_show functions with __printf,
from Alan Maguire.

8) BPF selftest improvements to reuse common network helpers in sk_lookup
test and dropping the open-coded inetaddr_len() and make_socket() ones,
from Geliang Tang.

* tag 'for-netdev' of https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next: (23 commits)
selftests/bpf: Test for null-pointer-deref bugfix in resolve_prog_type()
bpf: Fix null pointer dereference in resolve_prog_type() for BPF_PROG_TYPE_EXT
selftests/bpf: DENYLIST.aarch64: Skip fexit_sleep again
bpf: use check_sub_overflow() to check for subtraction overflows
bpf: use check_add_overflow() to check for addition overflows
bpf: fix overflow check in adjust_jmp_off()
bpf: Eliminate remaining "make W=1" warnings in kernel/bpf/btf.o
bpf: annotate BTF show functions with __printf
bpf, arm64: Fix trampoline for BPF_TRAMP_F_CALL_ORIG
selftests/bpf: Close obj in error path in xdp_adjust_tail
selftests/bpf: Null checks for links in bpf_tcp_ca
selftests/bpf: Use connect_fd_to_fd in sk_lookup
selftests/bpf: Use start_server_addr in sk_lookup
selftests/bpf: Use start_server_str in sk_lookup
selftests/bpf: Close fd in error path in drop_on_reuseport
selftests/bpf: Add ASSERT_OK_FD macro
selftests/bpf: Add backlog for network_helper_opts
selftests/bpf: fix compilation failure when CONFIG_NF_FLOW_TABLE=m
bpf: Remove tst_run from lwt_seg6local_prog_ops.
bpf: relax zero fixed offset constraint on KF_TRUSTED_ARGS/KF_RCU
...
====================

Link: https://patch.msgid.link/20240712212448.5378-1-daniel@iogearbox.net
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+234 -243
+2 -2
arch/arm64/net/bpf_jit_comp.c
··· 2147 2147 emit(A64_STR64I(A64_R(20), A64_SP, regs_off + 8), ctx); 2148 2148 2149 2149 if (flags & BPF_TRAMP_F_CALL_ORIG) { 2150 - emit_addr_mov_i64(A64_R(0), (const u64)im, ctx); 2150 + emit_a64_mov_i64(A64_R(0), (const u64)im, ctx); 2151 2151 emit_call((const u64)__bpf_tramp_enter, ctx); 2152 2152 } 2153 2153 ··· 2191 2191 2192 2192 if (flags & BPF_TRAMP_F_CALL_ORIG) { 2193 2193 im->ip_epilogue = ctx->ro_image + ctx->idx; 2194 - emit_addr_mov_i64(A64_R(0), (const u64)im, ctx); 2194 + emit_a64_mov_i64(A64_R(0), (const u64)im, ctx); 2195 2195 emit_call((const u64)__bpf_tramp_exit, ctx); 2196 2196 } 2197 2197
+1 -1
include/linux/bpf_verifier.h
··· 856 856 /* only use after check_attach_btf_id() */ 857 857 static inline enum bpf_prog_type resolve_prog_type(const struct bpf_prog *prog) 858 858 { 859 - return prog->type == BPF_PROG_TYPE_EXT ? 859 + return (prog->type == BPF_PROG_TYPE_EXT && prog->aux->dst_prog) ? 860 860 prog->aux->dst_prog->type : prog->type; 861 861 } 862 862
+5 -5
kernel/bpf/btf.c
··· 415 415 struct btf_show { 416 416 u64 flags; 417 417 void *target; /* target of show operation (seq file, buffer) */ 418 - void (*showfn)(struct btf_show *show, const char *fmt, va_list args); 418 + __printf(2, 0) void (*showfn)(struct btf_show *show, const char *fmt, va_list args); 419 419 const struct btf *btf; 420 420 /* below are used during iteration */ 421 421 struct { ··· 7538 7538 btf_type_ops(t)->show(btf, t, type_id, obj, 0, show); 7539 7539 } 7540 7540 7541 - static void btf_seq_show(struct btf_show *show, const char *fmt, 7542 - va_list args) 7541 + __printf(2, 0) static void btf_seq_show(struct btf_show *show, const char *fmt, 7542 + va_list args) 7543 7543 { 7544 7544 seq_vprintf((struct seq_file *)show->target, fmt, args); 7545 7545 } ··· 7572 7572 int len; /* length we would have written */ 7573 7573 }; 7574 7574 7575 - static void btf_snprintf_show(struct btf_show *show, const char *fmt, 7576 - va_list args) 7575 + __printf(2, 0) static void btf_snprintf_show(struct btf_show *show, const char *fmt, 7576 + va_list args) 7577 7577 { 7578 7578 struct btf_show_snprintf *ssnprintf = (struct btf_show_snprintf *)show; 7579 7579 int len;
+51 -129
kernel/bpf/verifier.c
··· 11335 11335 btf_type_ids_nocast_alias(&env->log, reg_btf, reg_ref_id, meta->btf, ref_id)) 11336 11336 strict_type_match = true; 11337 11337 11338 - WARN_ON_ONCE(is_kfunc_trusted_args(meta) && reg->off); 11338 + WARN_ON_ONCE(is_kfunc_release(meta) && 11339 + (reg->off || !tnum_is_const(reg->var_off) || 11340 + reg->var_off.value)); 11339 11341 11340 11342 reg_ref_t = btf_type_skip_modifiers(reg_btf, reg_ref_id, &reg_ref_id); 11341 11343 reg_ref_tname = btf_name_by_offset(reg_btf, reg_ref_t->name_off); ··· 11919 11917 return -EINVAL; 11920 11918 } 11921 11919 } 11922 - 11923 11920 fallthrough; 11924 11921 case KF_ARG_PTR_TO_CTX: 11925 - /* Trusted arguments have the same offset checks as release arguments */ 11926 - arg_type |= OBJ_RELEASE; 11927 - break; 11928 11922 case KF_ARG_PTR_TO_DYNPTR: 11929 11923 case KF_ARG_PTR_TO_ITER: 11930 11924 case KF_ARG_PTR_TO_LIST_HEAD: ··· 11933 11935 case KF_ARG_PTR_TO_REFCOUNTED_KPTR: 11934 11936 case KF_ARG_PTR_TO_CONST_STR: 11935 11937 case KF_ARG_PTR_TO_WORKQUEUE: 11936 - /* Trusted by default */ 11937 11938 break; 11938 11939 default: 11939 11940 WARN_ON_ONCE(1); ··· 12726 12729 return 0; 12727 12730 } 12728 12731 12729 - static bool signed_add_overflows(s64 a, s64 b) 12730 - { 12731 - /* Do the add in u64, where overflow is well-defined */ 12732 - s64 res = (s64)((u64)a + (u64)b); 12733 - 12734 - if (b < 0) 12735 - return res > a; 12736 - return res < a; 12737 - } 12738 - 12739 - static bool signed_add32_overflows(s32 a, s32 b) 12740 - { 12741 - /* Do the add in u32, where overflow is well-defined */ 12742 - s32 res = (s32)((u32)a + (u32)b); 12743 - 12744 - if (b < 0) 12745 - return res > a; 12746 - return res < a; 12747 - } 12748 - 12749 - static bool signed_add16_overflows(s16 a, s16 b) 12750 - { 12751 - /* Do the add in u16, where overflow is well-defined */ 12752 - s16 res = (s16)((u16)a + (u16)b); 12753 - 12754 - if (b < 0) 12755 - return res > a; 12756 - return res < a; 12757 - } 12758 - 12759 - static bool signed_sub_overflows(s64 a, s64 b) 12760 - { 12761 - /* Do the sub in u64, where overflow is well-defined */ 12762 - s64 res = (s64)((u64)a - (u64)b); 12763 - 12764 - if (b < 0) 12765 - return res < a; 12766 - return res > a; 12767 - } 12768 - 12769 - static bool signed_sub32_overflows(s32 a, s32 b) 12770 - { 12771 - /* Do the sub in u32, where overflow is well-defined */ 12772 - s32 res = (s32)((u32)a - (u32)b); 12773 - 12774 - if (b < 0) 12775 - return res < a; 12776 - return res > a; 12777 - } 12778 - 12779 12732 static bool check_reg_sane_offset(struct bpf_verifier_env *env, 12780 12733 const struct bpf_reg_state *reg, 12781 12734 enum bpf_reg_type type) ··· 13207 13260 * added into the variable offset, and we copy the fixed offset 13208 13261 * from ptr_reg. 13209 13262 */ 13210 - if (signed_add_overflows(smin_ptr, smin_val) || 13211 - signed_add_overflows(smax_ptr, smax_val)) { 13263 + if (check_add_overflow(smin_ptr, smin_val, &dst_reg->smin_value) || 13264 + check_add_overflow(smax_ptr, smax_val, &dst_reg->smax_value)) { 13212 13265 dst_reg->smin_value = S64_MIN; 13213 13266 dst_reg->smax_value = S64_MAX; 13214 - } else { 13215 - dst_reg->smin_value = smin_ptr + smin_val; 13216 - dst_reg->smax_value = smax_ptr + smax_val; 13217 13267 } 13218 - if (umin_ptr + umin_val < umin_ptr || 13219 - umax_ptr + umax_val < umax_ptr) { 13268 + if (check_add_overflow(umin_ptr, umin_val, &dst_reg->umin_value) || 13269 + check_add_overflow(umax_ptr, umax_val, &dst_reg->umax_value)) { 13220 13270 dst_reg->umin_value = 0; 13221 13271 dst_reg->umax_value = U64_MAX; 13222 - } else { 13223 - dst_reg->umin_value = umin_ptr + umin_val; 13224 - dst_reg->umax_value = umax_ptr + umax_val; 13225 13272 } 13226 13273 dst_reg->var_off = tnum_add(ptr_reg->var_off, off_reg->var_off); 13227 13274 dst_reg->off = ptr_reg->off; ··· 13258 13317 /* A new variable offset is created. If the subtrahend is known 13259 13318 * nonnegative, then any reg->range we had before is still good. 13260 13319 */ 13261 - if (signed_sub_overflows(smin_ptr, smax_val) || 13262 - signed_sub_overflows(smax_ptr, smin_val)) { 13320 + if (check_sub_overflow(smin_ptr, smax_val, &dst_reg->smin_value) || 13321 + check_sub_overflow(smax_ptr, smin_val, &dst_reg->smax_value)) { 13263 13322 /* Overflow possible, we know nothing */ 13264 13323 dst_reg->smin_value = S64_MIN; 13265 13324 dst_reg->smax_value = S64_MAX; 13266 - } else { 13267 - dst_reg->smin_value = smin_ptr - smax_val; 13268 - dst_reg->smax_value = smax_ptr - smin_val; 13269 13325 } 13270 13326 if (umin_ptr < umax_val) { 13271 13327 /* Overflow possible, we know nothing */ ··· 13315 13377 static void scalar32_min_max_add(struct bpf_reg_state *dst_reg, 13316 13378 struct bpf_reg_state *src_reg) 13317 13379 { 13318 - s32 smin_val = src_reg->s32_min_value; 13319 - s32 smax_val = src_reg->s32_max_value; 13320 - u32 umin_val = src_reg->u32_min_value; 13321 - u32 umax_val = src_reg->u32_max_value; 13380 + s32 *dst_smin = &dst_reg->s32_min_value; 13381 + s32 *dst_smax = &dst_reg->s32_max_value; 13382 + u32 *dst_umin = &dst_reg->u32_min_value; 13383 + u32 *dst_umax = &dst_reg->u32_max_value; 13322 13384 13323 - if (signed_add32_overflows(dst_reg->s32_min_value, smin_val) || 13324 - signed_add32_overflows(dst_reg->s32_max_value, smax_val)) { 13325 - dst_reg->s32_min_value = S32_MIN; 13326 - dst_reg->s32_max_value = S32_MAX; 13327 - } else { 13328 - dst_reg->s32_min_value += smin_val; 13329 - dst_reg->s32_max_value += smax_val; 13385 + if (check_add_overflow(*dst_smin, src_reg->s32_min_value, dst_smin) || 13386 + check_add_overflow(*dst_smax, src_reg->s32_max_value, dst_smax)) { 13387 + *dst_smin = S32_MIN; 13388 + *dst_smax = S32_MAX; 13330 13389 } 13331 - if (dst_reg->u32_min_value + umin_val < umin_val || 13332 - dst_reg->u32_max_value + umax_val < umax_val) { 13333 - dst_reg->u32_min_value = 0; 13334 - dst_reg->u32_max_value = U32_MAX; 13335 - } else { 13336 - dst_reg->u32_min_value += umin_val; 13337 - dst_reg->u32_max_value += umax_val; 13390 + if (check_add_overflow(*dst_umin, src_reg->u32_min_value, dst_umin) || 13391 + check_add_overflow(*dst_umax, src_reg->u32_max_value, dst_umax)) { 13392 + *dst_umin = 0; 13393 + *dst_umax = U32_MAX; 13338 13394 } 13339 13395 } 13340 13396 13341 13397 static void scalar_min_max_add(struct bpf_reg_state *dst_reg, 13342 13398 struct bpf_reg_state *src_reg) 13343 13399 { 13344 - s64 smin_val = src_reg->smin_value; 13345 - s64 smax_val = src_reg->smax_value; 13346 - u64 umin_val = src_reg->umin_value; 13347 - u64 umax_val = src_reg->umax_value; 13400 + s64 *dst_smin = &dst_reg->smin_value; 13401 + s64 *dst_smax = &dst_reg->smax_value; 13402 + u64 *dst_umin = &dst_reg->umin_value; 13403 + u64 *dst_umax = &dst_reg->umax_value; 13348 13404 13349 - if (signed_add_overflows(dst_reg->smin_value, smin_val) || 13350 - signed_add_overflows(dst_reg->smax_value, smax_val)) { 13351 - dst_reg->smin_value = S64_MIN; 13352 - dst_reg->smax_value = S64_MAX; 13353 - } else { 13354 - dst_reg->smin_value += smin_val; 13355 - dst_reg->smax_value += smax_val; 13405 + if (check_add_overflow(*dst_smin, src_reg->smin_value, dst_smin) || 13406 + check_add_overflow(*dst_smax, src_reg->smax_value, dst_smax)) { 13407 + *dst_smin = S64_MIN; 13408 + *dst_smax = S64_MAX; 13356 13409 } 13357 - if (dst_reg->umin_value + umin_val < umin_val || 13358 - dst_reg->umax_value + umax_val < umax_val) { 13359 - dst_reg->umin_value = 0; 13360 - dst_reg->umax_value = U64_MAX; 13361 - } else { 13362 - dst_reg->umin_value += umin_val; 13363 - dst_reg->umax_value += umax_val; 13410 + if (check_add_overflow(*dst_umin, src_reg->umin_value, dst_umin) || 13411 + check_add_overflow(*dst_umax, src_reg->umax_value, dst_umax)) { 13412 + *dst_umin = 0; 13413 + *dst_umax = U64_MAX; 13364 13414 } 13365 13415 } 13366 13416 13367 13417 static void scalar32_min_max_sub(struct bpf_reg_state *dst_reg, 13368 13418 struct bpf_reg_state *src_reg) 13369 13419 { 13370 - s32 smin_val = src_reg->s32_min_value; 13371 - s32 smax_val = src_reg->s32_max_value; 13420 + s32 *dst_smin = &dst_reg->s32_min_value; 13421 + s32 *dst_smax = &dst_reg->s32_max_value; 13372 13422 u32 umin_val = src_reg->u32_min_value; 13373 13423 u32 umax_val = src_reg->u32_max_value; 13374 13424 13375 - if (signed_sub32_overflows(dst_reg->s32_min_value, smax_val) || 13376 - signed_sub32_overflows(dst_reg->s32_max_value, smin_val)) { 13425 + if (check_sub_overflow(*dst_smin, src_reg->s32_max_value, dst_smin) || 13426 + check_sub_overflow(*dst_smax, src_reg->s32_min_value, dst_smax)) { 13377 13427 /* Overflow possible, we know nothing */ 13378 - dst_reg->s32_min_value = S32_MIN; 13379 - dst_reg->s32_max_value = S32_MAX; 13380 - } else { 13381 - dst_reg->s32_min_value -= smax_val; 13382 - dst_reg->s32_max_value -= smin_val; 13428 + *dst_smin = S32_MIN; 13429 + *dst_smax = S32_MAX; 13383 13430 } 13384 13431 if (dst_reg->u32_min_value < umax_val) { 13385 13432 /* Overflow possible, we know nothing */ ··· 13380 13457 static void scalar_min_max_sub(struct bpf_reg_state *dst_reg, 13381 13458 struct bpf_reg_state *src_reg) 13382 13459 { 13383 - s64 smin_val = src_reg->smin_value; 13384 - s64 smax_val = src_reg->smax_value; 13460 + s64 *dst_smin = &dst_reg->smin_value; 13461 + s64 *dst_smax = &dst_reg->smax_value; 13385 13462 u64 umin_val = src_reg->umin_value; 13386 13463 u64 umax_val = src_reg->umax_value; 13387 13464 13388 - if (signed_sub_overflows(dst_reg->smin_value, smax_val) || 13389 - signed_sub_overflows(dst_reg->smax_value, smin_val)) { 13465 + if (check_sub_overflow(*dst_smin, src_reg->smax_value, dst_smin) || 13466 + check_sub_overflow(*dst_smax, src_reg->smin_value, dst_smax)) { 13390 13467 /* Overflow possible, we know nothing */ 13391 - dst_reg->smin_value = S64_MIN; 13392 - dst_reg->smax_value = S64_MAX; 13393 - } else { 13394 - dst_reg->smin_value -= smax_val; 13395 - dst_reg->smax_value -= smin_val; 13468 + *dst_smin = S64_MIN; 13469 + *dst_smax = S64_MAX; 13396 13470 } 13397 13471 if (dst_reg->umin_value < umax_val) { 13398 13472 /* Overflow possible, we know nothing */ ··· 18758 18838 { 18759 18839 struct bpf_insn *insn = prog->insnsi; 18760 18840 u32 insn_cnt = prog->len, i; 18841 + s32 imm; 18842 + s16 off; 18761 18843 18762 18844 for (i = 0; i < insn_cnt; i++, insn++) { 18763 18845 u8 code = insn->code; ··· 18771 18849 if (insn->code == (BPF_JMP32 | BPF_JA)) { 18772 18850 if (i + 1 + insn->imm != tgt_idx) 18773 18851 continue; 18774 - if (signed_add32_overflows(insn->imm, delta)) 18852 + if (check_add_overflow(insn->imm, delta, &imm)) 18775 18853 return -ERANGE; 18776 - insn->imm += delta; 18854 + insn->imm = imm; 18777 18855 } else { 18778 18856 if (i + 1 + insn->off != tgt_idx) 18779 18857 continue; 18780 - if (signed_add16_overflows(insn->imm, delta)) 18858 + if (check_add_overflow(insn->off, delta, &off)) 18781 18859 return -ERANGE; 18782 - insn->off += delta; 18860 + insn->off = off; 18783 18861 } 18784 18862 } 18785 18863 return 0;
-1
net/core/filter.c
··· 11053 11053 }; 11054 11054 11055 11055 const struct bpf_prog_ops lwt_seg6local_prog_ops = { 11056 - .test_run = bpf_prog_test_run_skb, 11057 11056 }; 11058 11057 11059 11058 const struct bpf_verifier_ops cg_sock_verifier_ops = {
+32 -14
tools/bpf/bpftool/gen.c
··· 852 852 { 853 853 struct bpf_map *map; 854 854 char ident[256]; 855 - size_t i; 855 + size_t i, map_sz; 856 856 857 857 if (!map_cnt) 858 858 return; 859 859 860 + /* for backward compatibility with old libbpf versions that don't 861 + * handle new BPF skeleton with new struct bpf_map_skeleton definition 862 + * that includes link field, avoid specifying new increased size, 863 + * unless we absolutely have to (i.e., if there are struct_ops maps 864 + * present) 865 + */ 866 + map_sz = offsetof(struct bpf_map_skeleton, link); 867 + if (populate_links) { 868 + bpf_object__for_each_map(map, obj) { 869 + if (bpf_map__type(map) == BPF_MAP_TYPE_STRUCT_OPS) { 870 + map_sz = sizeof(struct bpf_map_skeleton); 871 + break; 872 + } 873 + } 874 + } 875 + 860 876 codegen("\ 861 877 \n\ 862 - \n\ 878 + \n\ 863 879 /* maps */ \n\ 864 880 s->map_cnt = %zu; \n\ 865 - s->map_skel_sz = sizeof(*s->maps); \n\ 866 - s->maps = (struct bpf_map_skeleton *)calloc(s->map_cnt, s->map_skel_sz);\n\ 881 + s->map_skel_sz = %zu; \n\ 882 + s->maps = (struct bpf_map_skeleton *)calloc(s->map_cnt,\n\ 883 + sizeof(*s->maps) > %zu ? sizeof(*s->maps) : %zu);\n\ 867 884 if (!s->maps) { \n\ 868 885 err = -ENOMEM; \n\ 869 886 goto err; \n\ 870 887 } \n\ 871 888 ", 872 - map_cnt 889 + map_cnt, map_sz, map_sz, map_sz 873 890 ); 874 891 i = 0; 875 892 bpf_object__for_each_map(map, obj) { ··· 895 878 896 879 codegen("\ 897 880 \n\ 898 - \n\ 899 - s->maps[%zu].name = \"%s\"; \n\ 900 - s->maps[%zu].map = &obj->maps.%s; \n\ 881 + \n\ 882 + map = (struct bpf_map_skeleton *)((char *)s->maps + %zu * s->map_skel_sz);\n\ 883 + map->name = \"%s\"; \n\ 884 + map->map = &obj->maps.%s; \n\ 901 885 ", 902 - i, bpf_map__name(map), i, ident); 886 + i, bpf_map__name(map), ident); 903 887 /* memory-mapped internal maps */ 904 888 if (mmaped && is_mmapable_map(map, ident, sizeof(ident))) { 905 - printf("\ts->maps[%zu].mmaped = (void **)&obj->%s;\n", 906 - i, ident); 889 + printf("\tmap->mmaped = (void **)&obj->%s;\n", ident); 907 890 } 908 891 909 892 if (populate_links && bpf_map__type(map) == BPF_MAP_TYPE_STRUCT_OPS) { 910 893 codegen("\ 911 894 \n\ 912 - s->maps[%zu].link = &obj->links.%s;\n\ 913 - ", 914 - i, ident); 895 + map->link = &obj->links.%s; \n\ 896 + ", ident); 915 897 } 916 898 i++; 917 899 } ··· 1479 1463 %1$s__create_skeleton(struct %1$s *obj) \n\ 1480 1464 { \n\ 1481 1465 struct bpf_object_skeleton *s; \n\ 1466 + struct bpf_map_skeleton *map __attribute__((unused));\n\ 1482 1467 int err; \n\ 1483 1468 \n\ 1484 1469 s = (struct bpf_object_skeleton *)calloc(1, sizeof(*s));\n\ ··· 1770 1753 { \n\ 1771 1754 struct %1$s *obj; \n\ 1772 1755 struct bpf_object_subskeleton *s; \n\ 1756 + struct bpf_map_skeleton *map __attribute__((unused));\n\ 1773 1757 int err; \n\ 1774 1758 \n\ 1775 1759 obj = (struct %1$s *)calloc(1, sizeof(*obj)); \n\
+40 -31
tools/lib/bpf/libbpf.c
··· 13712 13712 13713 13713 static int populate_skeleton_maps(const struct bpf_object *obj, 13714 13714 struct bpf_map_skeleton *maps, 13715 - size_t map_cnt) 13715 + size_t map_cnt, size_t map_skel_sz) 13716 13716 { 13717 13717 int i; 13718 13718 13719 13719 for (i = 0; i < map_cnt; i++) { 13720 - struct bpf_map **map = maps[i].map; 13721 - const char *name = maps[i].name; 13722 - void **mmaped = maps[i].mmaped; 13720 + struct bpf_map_skeleton *map_skel = (void *)maps + i * map_skel_sz; 13721 + struct bpf_map **map = map_skel->map; 13722 + const char *name = map_skel->name; 13723 + void **mmaped = map_skel->mmaped; 13723 13724 13724 13725 *map = bpf_object__find_map_by_name(obj, name); 13725 13726 if (!*map) { ··· 13737 13736 13738 13737 static int populate_skeleton_progs(const struct bpf_object *obj, 13739 13738 struct bpf_prog_skeleton *progs, 13740 - size_t prog_cnt) 13739 + size_t prog_cnt, size_t prog_skel_sz) 13741 13740 { 13742 13741 int i; 13743 13742 13744 13743 for (i = 0; i < prog_cnt; i++) { 13745 - struct bpf_program **prog = progs[i].prog; 13746 - const char *name = progs[i].name; 13744 + struct bpf_prog_skeleton *prog_skel = (void *)progs + i * prog_skel_sz; 13745 + struct bpf_program **prog = prog_skel->prog; 13746 + const char *name = prog_skel->name; 13747 13747 13748 13748 *prog = bpf_object__find_program_by_name(obj, name); 13749 13749 if (!*prog) { ··· 13785 13783 } 13786 13784 13787 13785 *s->obj = obj; 13788 - err = populate_skeleton_maps(obj, s->maps, s->map_cnt); 13786 + err = populate_skeleton_maps(obj, s->maps, s->map_cnt, s->map_skel_sz); 13789 13787 if (err) { 13790 13788 pr_warn("failed to populate skeleton maps for '%s': %d\n", s->name, err); 13791 13789 return libbpf_err(err); 13792 13790 } 13793 13791 13794 - err = populate_skeleton_progs(obj, s->progs, s->prog_cnt); 13792 + err = populate_skeleton_progs(obj, s->progs, s->prog_cnt, s->prog_skel_sz); 13795 13793 if (err) { 13796 13794 pr_warn("failed to populate skeleton progs for '%s': %d\n", s->name, err); 13797 13795 return libbpf_err(err); ··· 13821 13819 return libbpf_err(-errno); 13822 13820 } 13823 13821 13824 - err = populate_skeleton_maps(s->obj, s->maps, s->map_cnt); 13822 + err = populate_skeleton_maps(s->obj, s->maps, s->map_cnt, s->map_skel_sz); 13825 13823 if (err) { 13826 13824 pr_warn("failed to populate subskeleton maps: %d\n", err); 13827 13825 return libbpf_err(err); 13828 13826 } 13829 13827 13830 - err = populate_skeleton_progs(s->obj, s->progs, s->prog_cnt); 13828 + err = populate_skeleton_progs(s->obj, s->progs, s->prog_cnt, s->prog_skel_sz); 13831 13829 if (err) { 13832 13830 pr_warn("failed to populate subskeleton maps: %d\n", err); 13833 13831 return libbpf_err(err); 13834 13832 } 13835 13833 13836 13834 for (var_idx = 0; var_idx < s->var_cnt; var_idx++) { 13837 - var_skel = &s->vars[var_idx]; 13835 + var_skel = (void *)s->vars + var_idx * s->var_skel_sz; 13838 13836 map = *var_skel->map; 13839 13837 map_type_id = bpf_map__btf_value_type_id(map); 13840 13838 map_type = btf__type_by_id(btf, map_type_id); ··· 13881 13879 } 13882 13880 13883 13881 for (i = 0; i < s->map_cnt; i++) { 13884 - struct bpf_map *map = *s->maps[i].map; 13882 + struct bpf_map_skeleton *map_skel = (void *)s->maps + i * s->map_skel_sz; 13883 + struct bpf_map *map = *map_skel->map; 13885 13884 size_t mmap_sz = bpf_map_mmap_sz(map); 13886 13885 int prot, map_fd = map->fd; 13887 - void **mmaped = s->maps[i].mmaped; 13886 + void **mmaped = map_skel->mmaped; 13888 13887 13889 13888 if (!mmaped) 13890 13889 continue; ··· 13933 13930 int i, err; 13934 13931 13935 13932 for (i = 0; i < s->prog_cnt; i++) { 13936 - struct bpf_program *prog = *s->progs[i].prog; 13937 - struct bpf_link **link = s->progs[i].link; 13933 + struct bpf_prog_skeleton *prog_skel = (void *)s->progs + i * s->prog_skel_sz; 13934 + struct bpf_program *prog = *prog_skel->prog; 13935 + struct bpf_link **link = prog_skel->link; 13938 13936 13939 13937 if (!prog->autoload || !prog->autoattach) 13940 13938 continue; ··· 13967 13963 */ 13968 13964 } 13969 13965 13970 - /* Skeleton is created with earlier version of bpftool 13971 - * which does not support auto-attachment 13972 - */ 13973 - if (s->map_skel_sz < sizeof(struct bpf_map_skeleton)) 13974 - return 0; 13975 13966 13976 13967 for (i = 0; i < s->map_cnt; i++) { 13977 - struct bpf_map *map = *s->maps[i].map; 13978 - struct bpf_link **link = s->maps[i].link; 13968 + struct bpf_map_skeleton *map_skel = (void *)s->maps + i * s->map_skel_sz; 13969 + struct bpf_map *map = *map_skel->map; 13970 + struct bpf_link **link; 13979 13971 13980 13972 if (!map->autocreate || !map->autoattach) 13981 - continue; 13982 - 13983 - if (*link) 13984 13973 continue; 13985 13974 13986 13975 /* only struct_ops maps can be attached */ 13987 13976 if (!bpf_map__is_struct_ops(map)) 13988 13977 continue; 13989 - *link = bpf_map__attach_struct_ops(map); 13990 13978 13979 + /* skeleton is created with earlier version of bpftool, notify user */ 13980 + if (s->map_skel_sz < offsetofend(struct bpf_map_skeleton, link)) { 13981 + pr_warn("map '%s': BPF skeleton version is old, skipping map auto-attachment...\n", 13982 + bpf_map__name(map)); 13983 + continue; 13984 + } 13985 + 13986 + link = map_skel->link; 13987 + if (*link) 13988 + continue; 13989 + 13990 + *link = bpf_map__attach_struct_ops(map); 13991 13991 if (!*link) { 13992 13992 err = -errno; 13993 - pr_warn("map '%s': failed to auto-attach: %d\n", 13994 - bpf_map__name(map), err); 13993 + pr_warn("map '%s': failed to auto-attach: %d\n", bpf_map__name(map), err); 13995 13994 return libbpf_err(err); 13996 13995 } 13997 13996 } ··· 14007 14000 int i; 14008 14001 14009 14002 for (i = 0; i < s->prog_cnt; i++) { 14010 - struct bpf_link **link = s->progs[i].link; 14003 + struct bpf_prog_skeleton *prog_skel = (void *)s->progs + i * s->prog_skel_sz; 14004 + struct bpf_link **link = prog_skel->link; 14011 14005 14012 14006 bpf_link__destroy(*link); 14013 14007 *link = NULL; ··· 14018 14010 return; 14019 14011 14020 14012 for (i = 0; i < s->map_cnt; i++) { 14021 - struct bpf_link **link = s->maps[i].link; 14013 + struct bpf_map_skeleton *map_skel = (void *)s->maps + i * s->map_skel_sz; 14014 + struct bpf_link **link = map_skel->link; 14022 14015 14023 14016 if (link) { 14024 14017 bpf_link__destroy(*link);
+1
tools/testing/selftests/bpf/DENYLIST.aarch64
··· 1 1 bpf_cookie/multi_kprobe_attach_api # kprobe_multi_link_api_subtest:FAIL:fentry_raw_skel_load unexpected error: -3 2 2 bpf_cookie/multi_kprobe_link_api # kprobe_multi_link_api_subtest:FAIL:fentry_raw_skel_load unexpected error: -3 3 + fexit_sleep # The test never returns. The remaining tests cannot start. 3 4 kprobe_multi_bench_attach # needs CONFIG_FPROBE 4 5 kprobe_multi_test # needs CONFIG_FPROBE 5 6 module_attach # prog 'kprobe_multi': failed to auto-attach: -95
+1 -1
tools/testing/selftests/bpf/network_helpers.c
··· 106 106 } 107 107 108 108 if (type == SOCK_STREAM) { 109 - if (listen(fd, 1) < 0) { 109 + if (listen(fd, opts->backlog ? MAX(opts->backlog, 0) : 1) < 0) { 110 110 log_err("Failed to listed on socket"); 111 111 goto error_close; 112 112 }
+10
tools/testing/selftests/bpf/network_helpers.h
··· 25 25 int timeout_ms; 26 26 bool must_fail; 27 27 int proto; 28 + /* +ve: Passed to listen() as-is. 29 + * 0: Default when the test does not set 30 + * a particular value during the struct init. 31 + * It is changed to 1 before passing to listen(). 32 + * Most tests only have one on-going connection. 33 + * -ve: It is changed to 0 before passing to listen(). 34 + * It is useful to force syncookie without 35 + * changing the "tcp_syncookies" sysctl from 1 to 2. 36 + */ 37 + int backlog; 28 38 int (*post_socket_cb)(int fd, void *opts); 29 39 void *cb_opts; 30 40 };
+12 -4
tools/testing/selftests/bpf/prog_tests/bpf_tcp_ca.c
··· 411 411 return; 412 412 413 413 link = bpf_map__attach_struct_ops(skel->maps.ca_update_1); 414 - ASSERT_OK_PTR(link, "attach_struct_ops"); 414 + if (!ASSERT_OK_PTR(link, "attach_struct_ops")) 415 + goto out; 415 416 416 417 do_test(&opts); 417 418 saved_ca1_cnt = skel->bss->ca1_cnt; ··· 426 425 ASSERT_GT(skel->bss->ca2_cnt, 0, "ca2_ca2_cnt"); 427 426 428 427 bpf_link__destroy(link); 428 + out: 429 429 tcp_ca_update__destroy(skel); 430 430 } 431 431 ··· 449 447 return; 450 448 451 449 link = bpf_map__attach_struct_ops(skel->maps.ca_update_1); 452 - ASSERT_OK_PTR(link, "attach_struct_ops"); 450 + if (!ASSERT_OK_PTR(link, "attach_struct_ops")) 451 + goto out; 453 452 454 453 do_test(&opts); 455 454 saved_ca1_cnt = skel->bss->ca1_cnt; ··· 463 460 ASSERT_GT(skel->bss->ca1_cnt, saved_ca1_cnt, "ca2_ca1_cnt"); 464 461 465 462 bpf_link__destroy(link); 463 + out: 466 464 tcp_ca_update__destroy(skel); 467 465 } 468 466 ··· 485 481 return; 486 482 487 483 link_nl = bpf_map__attach_struct_ops(skel->maps.ca_no_link); 488 - ASSERT_OK_PTR(link_nl, "attach_struct_ops_nl"); 484 + if (!ASSERT_OK_PTR(link_nl, "attach_struct_ops_nl")) 485 + goto out; 489 486 490 487 link = bpf_map__attach_struct_ops(skel->maps.ca_update_1); 491 488 ASSERT_OK_PTR(link, "attach_struct_ops"); ··· 499 494 500 495 bpf_link__destroy(link); 501 496 bpf_link__destroy(link_nl); 497 + out: 502 498 tcp_ca_update__destroy(skel); 503 499 } 504 500 ··· 542 536 bpf_link__destroy(link); 543 537 544 538 link = bpf_map__attach_struct_ops(skel->maps.ca_update_2); 545 - ASSERT_OK_PTR(link, "attach_struct_ops_2nd"); 539 + if (!ASSERT_OK_PTR(link, "attach_struct_ops_2nd")) 540 + goto out; 546 541 547 542 /* BPF_F_REPLACE with a wrong old map Fd. It should fail! 548 543 * ··· 566 559 567 560 bpf_link__destroy(link); 568 561 562 + out: 569 563 tcp_ca_update__destroy(skel); 570 564 } 571 565
+40 -42
tools/testing/selftests/bpf/prog_tests/sk_lookup.c
··· 77 77 bool reuseport_has_conns; /* Add a connected socket to reuseport group */ 78 78 }; 79 79 80 + struct cb_opts { 81 + int family; 82 + int sotype; 83 + bool reuseport; 84 + }; 85 + 80 86 static __u32 duration; /* for CHECK macro */ 81 87 82 88 static bool is_ipv6(const char *ip) ··· 148 142 return fd; 149 143 } 150 144 151 - static int make_server(int sotype, const char *ip, int port, 152 - struct bpf_program *reuseport_prog) 145 + static int setsockopts(int fd, void *opts) 153 146 { 154 - struct sockaddr_storage addr = {0}; 147 + struct cb_opts *co = (struct cb_opts *)opts; 155 148 const int one = 1; 156 - int err, fd = -1; 157 - 158 - fd = make_socket(sotype, ip, port, &addr); 159 - if (fd < 0) 160 - return -1; 149 + int err = 0; 161 150 162 151 /* Enabled for UDPv6 sockets for IPv4-mapped IPv6 to work. */ 163 - if (sotype == SOCK_DGRAM) { 152 + if (co->sotype == SOCK_DGRAM) { 164 153 err = setsockopt(fd, SOL_IP, IP_RECVORIGDSTADDR, &one, 165 154 sizeof(one)); 166 155 if (CHECK(err, "setsockopt(IP_RECVORIGDSTADDR)", "failed\n")) { ··· 164 163 } 165 164 } 166 165 167 - if (sotype == SOCK_DGRAM && addr.ss_family == AF_INET6) { 166 + if (co->sotype == SOCK_DGRAM && co->family == AF_INET6) { 168 167 err = setsockopt(fd, SOL_IPV6, IPV6_RECVORIGDSTADDR, &one, 169 168 sizeof(one)); 170 169 if (CHECK(err, "setsockopt(IPV6_RECVORIGDSTADDR)", "failed\n")) { ··· 173 172 } 174 173 } 175 174 176 - if (sotype == SOCK_STREAM) { 175 + if (co->sotype == SOCK_STREAM) { 177 176 err = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, 178 177 sizeof(one)); 179 178 if (CHECK(err, "setsockopt(SO_REUSEADDR)", "failed\n")) { ··· 182 181 } 183 182 } 184 183 185 - if (reuseport_prog) { 184 + if (co->reuseport) { 186 185 err = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &one, 187 186 sizeof(one)); 188 187 if (CHECK(err, "setsockopt(SO_REUSEPORT)", "failed\n")) { ··· 191 190 } 192 191 } 193 192 194 - err = bind(fd, (void *)&addr, inetaddr_len(&addr)); 195 - if (CHECK(err, "bind", "failed\n")) { 196 - log_err("failed to bind listen socket"); 197 - goto fail; 198 - } 193 + fail: 194 + return err; 195 + } 199 196 200 - if (sotype == SOCK_STREAM) { 201 - err = listen(fd, SOMAXCONN); 202 - if (CHECK(err, "make_server", "listen")) { 203 - log_err("failed to listen on port %d", port); 204 - goto fail; 205 - } 206 - } 197 + static int make_server(int sotype, const char *ip, int port, 198 + struct bpf_program *reuseport_prog) 199 + { 200 + struct cb_opts cb_opts = { 201 + .family = is_ipv6(ip) ? AF_INET6 : AF_INET, 202 + .sotype = sotype, 203 + .reuseport = reuseport_prog, 204 + }; 205 + struct network_helper_opts opts = { 206 + .backlog = SOMAXCONN, 207 + .post_socket_cb = setsockopts, 208 + .cb_opts = &cb_opts, 209 + }; 210 + int err, fd; 211 + 212 + fd = start_server_str(cb_opts.family, sotype, ip, port, &opts); 213 + if (!ASSERT_OK_FD(fd, "start_server_str")) 214 + return -1; 207 215 208 216 /* Late attach reuseport prog so we can have one init path */ 209 217 if (reuseport_prog) { ··· 416 406 } 417 407 418 408 /* Reply from original destination address. */ 419 - fd = socket(dst_addr->ss_family, SOCK_DGRAM, 0); 420 - if (CHECK(fd < 0, "socket", "failed\n")) { 409 + fd = start_server_addr(SOCK_DGRAM, dst_addr, sizeof(*dst_addr), NULL); 410 + if (!ASSERT_OK_FD(fd, "start_server_addr")) { 421 411 log_err("failed to create tx socket"); 422 412 return -1; 423 - } 424 - 425 - ret = bind(fd, (struct sockaddr *)dst_addr, sizeof(*dst_addr)); 426 - if (CHECK(ret, "bind", "failed\n")) { 427 - log_err("failed to bind tx socket"); 428 - goto out; 429 413 } 430 414 431 415 msg.msg_control = NULL; ··· 633 629 * BPF socket lookup. 634 630 */ 635 631 if (t->reuseport_has_conns) { 636 - struct sockaddr_storage addr = {}; 637 - socklen_t len = sizeof(addr); 638 - 639 632 /* Add an extra socket to reuseport group */ 640 633 reuse_conn_fd = make_server(t->sotype, t->listen_at.ip, 641 634 t->listen_at.port, ··· 640 639 if (reuse_conn_fd < 0) 641 640 goto close; 642 641 643 - /* Connect the extra socket to itself */ 644 - err = getsockname(reuse_conn_fd, (void *)&addr, &len); 645 - if (CHECK(err, "getsockname", "errno %d\n", errno)) 646 - goto close; 647 - err = connect(reuse_conn_fd, (void *)&addr, len); 648 - if (CHECK(err, "connect", "errno %d\n", errno)) 642 + /* Connect the extra socket to itself */ 643 + err = connect_fd_to_fd(reuse_conn_fd, reuse_conn_fd, 0); 644 + if (!ASSERT_OK(err, "connect_fd_to_fd")) 649 645 goto close; 650 646 } 651 647 ··· 992 994 993 995 err = update_lookup_map(t->sock_map, SERVER_A, server1); 994 996 if (err) 995 - goto detach; 997 + goto close_srv1; 996 998 997 999 /* second server on destination address we should never reach */ 998 1000 server2 = make_server(t->sotype, t->connect_to.ip, t->connect_to.port,
+1 -1
tools/testing/selftests/bpf/prog_tests/xdp_adjust_tail.c
··· 222 222 223 223 prog = bpf_object__next_program(obj, NULL); 224 224 if (bpf_object__load(obj)) 225 - return; 225 + goto out; 226 226 227 227 prog_fd = bpf_program__fd(prog); 228 228
-8
tools/testing/selftests/bpf/progs/nested_trust_failure.c
··· 31 31 return 0; 32 32 } 33 33 34 - SEC("tp_btf/task_newtask") 35 - __failure __msg("R1 must have zero offset when passed to release func or trusted arg to kfunc") 36 - int BPF_PROG(test_invalid_nested_offset, struct task_struct *task, u64 clone_flags) 37 - { 38 - bpf_cpumask_first_zero(&task->cpus_mask); 39 - return 0; 40 - } 41 - 42 34 /* Although R2 is of type sk_buff but sock_common is expected, we will hit untrusted ptr first. */ 43 35 SEC("tp_btf/tcp_probe") 44 36 __failure __msg("R2 type=untrusted_ptr_ expected=ptr_, trusted_ptr_, rcu_ptr_")
+8
tools/testing/selftests/bpf/progs/nested_trust_success.c
··· 32 32 bpf_sk_storage_get(&sk_storage_map, skb->sk, 0, 0); 33 33 return 0; 34 34 } 35 + 36 + SEC("tp_btf/task_newtask") 37 + __success 38 + int BPF_PROG(test_nested_offset, struct task_struct *task, u64 clone_flags) 39 + { 40 + bpf_cpumask_first_zero(&task->cpus_mask); 41 + return 0; 42 + }
+7 -3
tools/testing/selftests/bpf/progs/xdp_flowtable.c
··· 58 58 return true; 59 59 } 60 60 61 + struct flow_ports___local { 62 + __be16 source, dest; 63 + } __attribute__((preserve_access_index)); 64 + 61 65 SEC("xdp.frags") 62 66 int xdp_flowtable_do_lookup(struct xdp_md *ctx) 63 67 { ··· 73 69 }; 74 70 void *data = (void *)(long)ctx->data; 75 71 struct ethhdr *eth = data; 76 - struct flow_ports *ports; 72 + struct flow_ports___local *ports; 77 73 __u32 *val, key = 0; 78 74 79 75 if (eth + 1 > data_end) ··· 83 79 case bpf_htons(ETH_P_IP): { 84 80 struct iphdr *iph = data + sizeof(*eth); 85 81 86 - ports = (struct flow_ports *)(iph + 1); 82 + ports = (struct flow_ports___local *)(iph + 1); 87 83 if (ports + 1 > data_end) 88 84 return XDP_PASS; 89 85 ··· 110 106 struct in6_addr *dst = (struct in6_addr *)tuple.ipv6_dst; 111 107 struct ipv6hdr *ip6h = data + sizeof(*eth); 112 108 113 - ports = (struct flow_ports *)(ip6h + 1); 109 + ports = (struct flow_ports___local *)(ip6h + 1); 114 110 if (ports + 1 > data_end) 115 111 return XDP_PASS; 116 112
+9
tools/testing/selftests/bpf/test_progs.h
··· 377 377 ___ok; \ 378 378 }) 379 379 380 + #define ASSERT_OK_FD(fd, name) ({ \ 381 + static int duration = 0; \ 382 + int ___fd = (fd); \ 383 + bool ___ok = ___fd >= 0; \ 384 + CHECK(!___ok, (name), "unexpected fd: %d (errno %d)\n", \ 385 + ___fd, errno); \ 386 + ___ok; \ 387 + }) 388 + 380 389 #define SYS(goto_label, fmt, ...) \ 381 390 ({ \ 382 391 char cmd[1024]; \
+14 -1
tools/testing/selftests/bpf/verifier/calls.c
··· 76 76 }, 77 77 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 78 78 .result = REJECT, 79 - .errstr = "R1 must have zero offset when passed to release func or trusted arg to kfunc", 79 + .errstr = "arg#0 expected pointer to ctx, but got PTR", 80 80 .fixup_kfunc_btf_id = { 81 81 { "bpf_kfunc_call_test_pass_ctx", 2 }, 82 82 }, ··· 274 274 }, 275 275 .result_unpriv = REJECT, 276 276 .result = ACCEPT, 277 + }, 278 + { 279 + "calls: invalid kfunc call: must provide (attach_prog_fd, btf_id) pair when freplace", 280 + .insns = { 281 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, BPF_PSEUDO_KFUNC_CALL, 0, 0), 282 + BPF_EXIT_INSN(), 283 + }, 284 + .prog_type = BPF_PROG_TYPE_EXT, 285 + .result = REJECT, 286 + .errstr = "Tracing programs must provide btf_id", 287 + .fixup_kfunc_btf_id = { 288 + { "bpf_dynptr_from_skb", 0 }, 289 + }, 277 290 }, 278 291 { 279 292 "calls: basic sanity",