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

Merge tag 'bpf-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf

Pull bpf fixes from Alexei Starovoitov:

- Fix invalid write loop logic in libbpf's bpf_linker__add_buf() (Amery
Hung)

- Fix a potential use-after-free of BTF object (Anton Protopopov)

- Add feature detection to libbpf and avoid moving arena global
variables on older kernels (Emil Tsalapatis)

- Remove extern declaration of bpf_stream_vprintk() from libbpf headers
(Ihor Solodrai)

- Fix truncated netlink dumps in bpftool (Jakub Kicinski)

- Fix map_kptr grace period wait in bpf selftests (Kumar Kartikeya
Dwivedi)

- Remove hexdump dependency while building bpf selftests (Matthieu
Baerts)

- Complete fsession support in BPF trampolines on riscv (Menglong Dong)

* tag 'bpf-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf:
selftests/bpf: Remove hexdump dependency
libbpf: Remove extern declaration of bpf_stream_vprintk()
selftests/bpf: Use vmlinux.h in test_xdp_meta
bpftool: Fix truncated netlink dumps
libbpf: Delay feature gate check until object prepare time
libbpf: Do not use PROG_TYPE_TRACEPOINT program for feature gating
bpf: Add a map/btf from a fd array more consistently
selftests/bpf: Fix map_kptr grace period wait
selftests/bpf: enable fsession_test on riscv64
selftests/bpf: Adjust selftest due to function rename
bpf, riscv: add fsession support for trampolines
bpf: Fix a potential use-after-free of BTF object
bpf, riscv: introduce emit_store_stack_imm64() for trampoline
libbpf: Fix invalid write loop logic in bpf_linker__add_buf()
libbpf: Add gating for arena globals relocation feature

+242 -101
+77 -20
arch/riscv/net/bpf_jit_comp64.c
··· 926 926 } 927 927 } 928 928 929 + static void emit_store_stack_imm64(u8 reg, int stack_off, u64 imm64, 930 + struct rv_jit_context *ctx) 931 + { 932 + /* Load imm64 into reg and store it at [FP + stack_off]. */ 933 + emit_imm(reg, (s64)imm64, ctx); 934 + emit_sd(RV_REG_FP, stack_off, reg, ctx); 935 + } 936 + 929 937 static int invoke_bpf_prog(struct bpf_tramp_link *l, int args_off, int retval_off, 930 938 int run_ctx_off, bool save_ret, struct rv_jit_context *ctx) 931 939 { ··· 941 933 struct bpf_prog *p = l->link.prog; 942 934 int cookie_off = offsetof(struct bpf_tramp_run_ctx, bpf_cookie); 943 935 944 - if (l->cookie) { 945 - emit_imm(RV_REG_T1, l->cookie, ctx); 946 - emit_sd(RV_REG_FP, -run_ctx_off + cookie_off, RV_REG_T1, ctx); 947 - } else { 936 + if (l->cookie) 937 + emit_store_stack_imm64(RV_REG_T1, -run_ctx_off + cookie_off, l->cookie, ctx); 938 + else 948 939 emit_sd(RV_REG_FP, -run_ctx_off + cookie_off, RV_REG_ZERO, ctx); 949 - } 950 940 951 941 /* arg1: prog */ 952 942 emit_imm(RV_REG_A0, (const s64)p, ctx); ··· 996 990 return ret; 997 991 } 998 992 993 + static int invoke_bpf(struct bpf_tramp_links *tl, int args_off, int retval_off, 994 + int run_ctx_off, int func_meta_off, bool save_ret, u64 func_meta, 995 + int cookie_off, struct rv_jit_context *ctx) 996 + { 997 + int i, cur_cookie = (cookie_off - args_off) / 8; 998 + 999 + for (i = 0; i < tl->nr_links; i++) { 1000 + int err; 1001 + 1002 + if (bpf_prog_calls_session_cookie(tl->links[i])) { 1003 + u64 meta = func_meta | ((u64)cur_cookie << BPF_TRAMP_COOKIE_INDEX_SHIFT); 1004 + 1005 + emit_store_stack_imm64(RV_REG_T1, -func_meta_off, meta, ctx); 1006 + cur_cookie--; 1007 + } 1008 + err = invoke_bpf_prog(tl->links[i], args_off, retval_off, run_ctx_off, 1009 + save_ret, ctx); 1010 + if (err) 1011 + return err; 1012 + } 1013 + return 0; 1014 + } 1015 + 999 1016 static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, 1000 1017 const struct btf_func_model *m, 1001 1018 struct bpf_tramp_links *tlinks, ··· 1028 999 int i, ret, offset; 1029 1000 int *branches_off = NULL; 1030 1001 int stack_size = 0, nr_arg_slots = 0; 1031 - int retval_off, args_off, nregs_off, ip_off, run_ctx_off, sreg_off, stk_arg_off; 1002 + int retval_off, args_off, func_meta_off, ip_off, run_ctx_off, sreg_off, stk_arg_off; 1003 + int cookie_off, cookie_cnt; 1032 1004 struct bpf_tramp_links *fentry = &tlinks[BPF_TRAMP_FENTRY]; 1033 1005 struct bpf_tramp_links *fexit = &tlinks[BPF_TRAMP_FEXIT]; 1034 1006 struct bpf_tramp_links *fmod_ret = &tlinks[BPF_TRAMP_MODIFY_RETURN]; 1035 1007 bool is_struct_ops = flags & BPF_TRAMP_F_INDIRECT; 1036 1008 void *orig_call = func_addr; 1037 1009 bool save_ret; 1010 + u64 func_meta; 1038 1011 u32 insn; 1039 1012 1040 1013 /* Two types of generated trampoline stack layout: ··· 1067 1036 * [ ... ] 1068 1037 * FP - args_off [ arg1 ] 1069 1038 * 1070 - * FP - nregs_off [ regs count ] 1039 + * FP - func_meta_off [ regs count, etc ] 1071 1040 * 1072 1041 * FP - ip_off [ traced func ] BPF_TRAMP_F_IP_ARG 1042 + * 1043 + * [ stack cookie N ] 1044 + * [ ... ] 1045 + * FP - cookie_off [ stack cookie 1 ] 1073 1046 * 1074 1047 * FP - run_ctx_off [ bpf_tramp_run_ctx ] 1075 1048 * ··· 1106 1071 stack_size += nr_arg_slots * 8; 1107 1072 args_off = stack_size; 1108 1073 1074 + /* function metadata, such as regs count */ 1109 1075 stack_size += 8; 1110 - nregs_off = stack_size; 1076 + func_meta_off = stack_size; 1111 1077 1112 1078 if (flags & BPF_TRAMP_F_IP_ARG) { 1113 1079 stack_size += 8; 1114 1080 ip_off = stack_size; 1115 1081 } 1082 + 1083 + cookie_cnt = bpf_fsession_cookie_cnt(tlinks); 1084 + /* room for session cookies */ 1085 + stack_size += cookie_cnt * 8; 1086 + cookie_off = stack_size; 1116 1087 1117 1088 stack_size += round_up(sizeof(struct bpf_tramp_run_ctx), 8); 1118 1089 run_ctx_off = stack_size; ··· 1164 1123 emit_sd(RV_REG_FP, -sreg_off, RV_REG_S1, ctx); 1165 1124 1166 1125 /* store ip address of the traced function */ 1167 - if (flags & BPF_TRAMP_F_IP_ARG) { 1168 - emit_imm(RV_REG_T1, (const s64)func_addr, ctx); 1169 - emit_sd(RV_REG_FP, -ip_off, RV_REG_T1, ctx); 1170 - } 1126 + if (flags & BPF_TRAMP_F_IP_ARG) 1127 + emit_store_stack_imm64(RV_REG_T1, -ip_off, (u64)func_addr, ctx); 1171 1128 1172 - emit_li(RV_REG_T1, nr_arg_slots, ctx); 1173 - emit_sd(RV_REG_FP, -nregs_off, RV_REG_T1, ctx); 1129 + func_meta = nr_arg_slots; 1130 + emit_store_stack_imm64(RV_REG_T1, -func_meta_off, func_meta, ctx); 1174 1131 1175 1132 store_args(nr_arg_slots, args_off, ctx); 1133 + 1134 + if (bpf_fsession_cnt(tlinks)) { 1135 + /* clear all session cookies' value */ 1136 + for (i = 0; i < cookie_cnt; i++) 1137 + emit_sd(RV_REG_FP, -cookie_off + 8 * i, RV_REG_ZERO, ctx); 1138 + /* clear return value to make sure fentry always get 0 */ 1139 + emit_sd(RV_REG_FP, -retval_off, RV_REG_ZERO, ctx); 1140 + } 1176 1141 1177 1142 if (flags & BPF_TRAMP_F_CALL_ORIG) { 1178 1143 emit_imm(RV_REG_A0, ctx->insns ? (const s64)im : RV_MAX_COUNT_IMM, ctx); ··· 1187 1140 return ret; 1188 1141 } 1189 1142 1190 - for (i = 0; i < fentry->nr_links; i++) { 1191 - ret = invoke_bpf_prog(fentry->links[i], args_off, retval_off, run_ctx_off, 1192 - flags & BPF_TRAMP_F_RET_FENTRY_RET, ctx); 1143 + if (fentry->nr_links) { 1144 + ret = invoke_bpf(fentry, args_off, retval_off, run_ctx_off, func_meta_off, 1145 + flags & BPF_TRAMP_F_RET_FENTRY_RET, func_meta, cookie_off, ctx); 1193 1146 if (ret) 1194 1147 return ret; 1195 1148 } ··· 1236 1189 *(u32 *)(ctx->insns + branches_off[i]) = insn; 1237 1190 } 1238 1191 1239 - for (i = 0; i < fexit->nr_links; i++) { 1240 - ret = invoke_bpf_prog(fexit->links[i], args_off, retval_off, 1241 - run_ctx_off, false, ctx); 1192 + /* set "is_return" flag for fsession */ 1193 + func_meta |= (1ULL << BPF_TRAMP_IS_RETURN_SHIFT); 1194 + if (bpf_fsession_cnt(tlinks)) 1195 + emit_store_stack_imm64(RV_REG_T1, -func_meta_off, func_meta, ctx); 1196 + 1197 + if (fexit->nr_links) { 1198 + ret = invoke_bpf(fexit, args_off, retval_off, run_ctx_off, func_meta_off, 1199 + false, func_meta, cookie_off, ctx); 1242 1200 if (ret) 1243 1201 goto out; 1244 1202 } ··· 2142 2090 default: 2143 2091 return false; 2144 2092 } 2093 + } 2094 + 2095 + bool bpf_jit_supports_fsession(void) 2096 + { 2097 + return true; 2145 2098 }
+25 -23
kernel/bpf/verifier.c
··· 21333 21333 } 21334 21334 21335 21335 /* 21336 - * Add btf to the used_btfs array and return the index. (If the btf was 21337 - * already added, then just return the index.) Upon successful insertion 21338 - * increase btf refcnt, and, if present, also refcount the corresponding 21339 - * kernel module. 21336 + * Add btf to the env->used_btfs array. If needed, refcount the 21337 + * corresponding kernel module. To simplify caller's logic 21338 + * in case of error or if btf was added before the function 21339 + * decreases the btf refcount. 21340 21340 */ 21341 21341 static int __add_used_btf(struct bpf_verifier_env *env, struct btf *btf) 21342 21342 { 21343 21343 struct btf_mod_pair *btf_mod; 21344 + int ret = 0; 21344 21345 int i; 21345 21346 21346 21347 /* check whether we recorded this BTF (and maybe module) already */ 21347 21348 for (i = 0; i < env->used_btf_cnt; i++) 21348 21349 if (env->used_btfs[i].btf == btf) 21349 - return i; 21350 + goto ret_put; 21350 21351 21351 21352 if (env->used_btf_cnt >= MAX_USED_BTFS) { 21352 21353 verbose(env, "The total number of btfs per program has reached the limit of %u\n", 21353 21354 MAX_USED_BTFS); 21354 - return -E2BIG; 21355 + ret = -E2BIG; 21356 + goto ret_put; 21355 21357 } 21356 - 21357 - btf_get(btf); 21358 21358 21359 21359 btf_mod = &env->used_btfs[env->used_btf_cnt]; 21360 21360 btf_mod->btf = btf; ··· 21364 21364 if (btf_is_module(btf)) { 21365 21365 btf_mod->module = btf_try_get_module(btf); 21366 21366 if (!btf_mod->module) { 21367 - btf_put(btf); 21368 - return -ENXIO; 21367 + ret = -ENXIO; 21368 + goto ret_put; 21369 21369 } 21370 21370 } 21371 21371 21372 - return env->used_btf_cnt++; 21372 + env->used_btf_cnt++; 21373 + return 0; 21374 + 21375 + ret_put: 21376 + /* Either error or this BTF was already added */ 21377 + btf_put(btf); 21378 + return ret; 21373 21379 } 21374 21380 21375 21381 /* replace pseudo btf_id with kernel symbol address */ ··· 21472 21466 21473 21467 btf_fd = insn[1].imm; 21474 21468 if (btf_fd) { 21475 - CLASS(fd, f)(btf_fd); 21476 - 21477 - btf = __btf_get_by_fd(f); 21469 + btf = btf_get_by_fd(btf_fd); 21478 21470 if (IS_ERR(btf)) { 21479 21471 verbose(env, "invalid module BTF object FD specified.\n"); 21480 21472 return -EINVAL; ··· 21482 21478 verbose(env, "kernel is missing BTF, make sure CONFIG_DEBUG_INFO_BTF=y is specified in Kconfig.\n"); 21483 21479 return -EINVAL; 21484 21480 } 21481 + btf_get(btf_vmlinux); 21485 21482 btf = btf_vmlinux; 21486 21483 } 21487 21484 21488 21485 err = __check_pseudo_btf_id(env, insn, aux, btf); 21489 - if (err) 21486 + if (err) { 21487 + btf_put(btf); 21490 21488 return err; 21489 + } 21491 21490 21492 - err = __add_used_btf(env, btf); 21493 - if (err < 0) 21494 - return err; 21495 - return 0; 21491 + return __add_used_btf(env, btf); 21496 21492 } 21497 21493 21498 21494 static bool is_tracing_prog_type(enum bpf_prog_type type) ··· 25374 25370 25375 25371 btf = __btf_get_by_fd(f); 25376 25372 if (!IS_ERR(btf)) { 25377 - err = __add_used_btf(env, btf); 25378 - if (err < 0) 25379 - return err; 25380 - return 0; 25373 + btf_get(btf); 25374 + return __add_used_btf(env, btf); 25381 25375 } 25382 25376 25383 25377 verbose(env, "fd %d is not pointing to valid bpf_map or btf\n", fd);
+4 -1
tools/bpf/bpftool/net.c
··· 156 156 bool multipart = true; 157 157 struct nlmsgerr *err; 158 158 struct nlmsghdr *nh; 159 - char buf[4096]; 159 + char buf[8192]; 160 160 int len, ret; 161 161 162 162 while (multipart) { ··· 201 201 return ret; 202 202 } 203 203 } 204 + 205 + if (len) 206 + p_err("Invalid message or trailing data in Netlink response: %d bytes left", len); 204 207 } 205 208 ret = 0; 206 209 done:
-3
tools/lib/bpf/bpf_helpers.h
··· 315 315 ___param, sizeof(___param)); \ 316 316 }) 317 317 318 - extern int bpf_stream_vprintk(int stream_id, const char *fmt__str, const void *args, 319 - __u32 len__sz) __weak __ksym; 320 - 321 318 #define bpf_stream_printk(stream_id, fmt, args...) \ 322 319 ({ \ 323 320 static const char ___fmt[] = fmt; \
+65
tools/lib/bpf/features.c
··· 506 506 return probe_fd(prog_fd); 507 507 } 508 508 509 + static int probe_ldimm64_full_range_off(int token_fd) 510 + { 511 + char log_buf[1024]; 512 + int prog_fd, map_fd; 513 + int ret; 514 + LIBBPF_OPTS(bpf_map_create_opts, map_opts, 515 + .token_fd = token_fd, 516 + .map_flags = token_fd ? BPF_F_TOKEN_FD : 0, 517 + ); 518 + LIBBPF_OPTS(bpf_prog_load_opts, prog_opts, 519 + .token_fd = token_fd, 520 + .prog_flags = token_fd ? BPF_F_TOKEN_FD : 0, 521 + .log_buf = log_buf, 522 + .log_size = sizeof(log_buf), 523 + ); 524 + struct bpf_insn insns[] = { 525 + BPF_LD_MAP_VALUE(BPF_REG_1, 0, 1UL << 30), 526 + BPF_EXIT_INSN(), 527 + }; 528 + int insn_cnt = ARRAY_SIZE(insns); 529 + 530 + map_fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, "arr", sizeof(int), 1, 1, &map_opts); 531 + if (map_fd < 0) { 532 + ret = -errno; 533 + pr_warn("Error in %s(): %s. Couldn't create simple array map.\n", 534 + __func__, errstr(ret)); 535 + return ret; 536 + } 537 + insns[0].imm = map_fd; 538 + 539 + log_buf[0] = '\0'; 540 + prog_fd = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, "global_reloc", "GPL", insns, insn_cnt, &prog_opts); 541 + ret = -errno; 542 + 543 + close(map_fd); 544 + 545 + if (prog_fd >= 0) { 546 + pr_warn("Error in %s(): Program loading unexpectedly succeeded.\n", __func__); 547 + close(prog_fd); 548 + return -EINVAL; 549 + } 550 + 551 + /* 552 + * Feature is allowed if we're not failing with the error message 553 + * "direct value offset of %u is not allowed" removed in 554 + * 12a1fe6e12db ("bpf/verifier: Do not limit maximum direct offset into arena map"). 555 + * We should instead fail with "invalid access to map value pointer". 556 + * Ensure we match with one of the two and we're not failing with a 557 + * different, unexpected message. 558 + */ 559 + if (strstr(log_buf, "direct value offset of")) 560 + return 0; 561 + 562 + if (!strstr(log_buf, "invalid access to map value pointer")) { 563 + pr_warn("Error in %s(): Program unexpectedly failed with message: %s.\n", 564 + __func__, log_buf); 565 + return ret; 566 + } 567 + 568 + return 1; 569 + } 570 + 509 571 typedef int (*feature_probe_fn)(int /* token_fd */); 510 572 511 573 static struct kern_feature_cache feature_cache; ··· 642 580 }, 643 581 [FEAT_BTF_QMARK_DATASEC] = { 644 582 "BTF DATASEC names starting from '?'", probe_kern_btf_qmark_datasec, 583 + }, 584 + [FEAT_LDIMM64_FULL_RANGE_OFF] = { 585 + "full range LDIMM64 support", probe_ldimm64_full_range_off, 645 586 }, 646 587 }; 647 588
+13 -4
tools/lib/bpf/libbpf.c
··· 3009 3009 memcpy(obj->arena_data, data, data_sz); 3010 3010 obj->arena_data_sz = data_sz; 3011 3011 3012 - /* place globals at the end of the arena */ 3013 - obj->arena_data_off = mmap_sz - data_alloc_sz; 3014 - 3015 3012 /* make bpf_map__init_value() work for ARENA maps */ 3016 3013 map->mmaped = obj->arena_data; 3017 3014 ··· 4666 4669 reloc_desc->type = RELO_DATA; 4667 4670 reloc_desc->insn_idx = insn_idx; 4668 4671 reloc_desc->map_idx = obj->arena_map_idx; 4669 - reloc_desc->sym_off = sym->st_value + obj->arena_data_off; 4672 + reloc_desc->sym_off = sym->st_value; 4670 4673 4671 4674 map = &obj->maps[obj->arena_map_idx]; 4672 4675 pr_debug("prog '%s': found arena map %d (%s, sec %d, off %zu) for insn %u\n", ··· 6380 6383 case RELO_DATA: 6381 6384 map = &obj->maps[relo->map_idx]; 6382 6385 insn[1].imm = insn[0].imm + relo->sym_off; 6386 + 6387 + if (relo->map_idx == obj->arena_map_idx) 6388 + insn[1].imm += obj->arena_data_off; 6389 + 6383 6390 if (obj->gen_loader) { 6384 6391 insn[0].src_reg = BPF_PSEUDO_MAP_IDX_VALUE; 6385 6392 insn[0].imm = relo->map_idx; ··· 7383 7382 return err; 7384 7383 } 7385 7384 bpf_object__sort_relos(obj); 7385 + } 7386 + 7387 + /* place globals at the end of the arena (if supported) */ 7388 + if (obj->arena_map_idx >= 0 && kernel_supports(obj, FEAT_LDIMM64_FULL_RANGE_OFF)) { 7389 + struct bpf_map *arena_map = &obj->maps[obj->arena_map_idx]; 7390 + 7391 + obj->arena_data_off = bpf_map_mmap_sz(arena_map) - 7392 + roundup(obj->arena_data_sz, sysconf(_SC_PAGE_SIZE)); 7386 7393 } 7387 7394 7388 7395 /* Before relocating calls pre-process relocations and mark
+2
tools/lib/bpf/libbpf_internal.h
··· 392 392 FEAT_ARG_CTX_TAG, 393 393 /* Kernel supports '?' at the front of datasec names */ 394 394 FEAT_BTF_QMARK_DATASEC, 395 + /* Kernel supports LDIMM64 imm offsets past 512 MiB. */ 396 + FEAT_LDIMM64_FULL_RANGE_OFF, 395 397 __FEAT_CNT, 396 398 }; 397 399
+1 -1
tools/lib/bpf/linker.c
··· 581 581 582 582 written = 0; 583 583 while (written < buf_sz) { 584 - ret = write(fd, buf, buf_sz); 584 + ret = write(fd, buf + written, buf_sz - written); 585 585 if (ret < 0) { 586 586 ret = -errno; 587 587 pr_warn("failed to write '%s': %s\n", filename, errstr(ret));
+3 -1
tools/lib/bpf/netlink.c
··· 143 143 struct nlmsghdr *nh; 144 144 int len, ret; 145 145 146 - ret = alloc_iov(&iov, 4096); 146 + ret = alloc_iov(&iov, 8192); 147 147 if (ret) 148 148 goto done; 149 149 ··· 212 212 } 213 213 } 214 214 } 215 + if (len) 216 + pr_warn("Invalid message or trailing data in Netlink response: %d bytes left\n", len); 215 217 } 216 218 ret = 0; 217 219 done:
+1 -1
tools/testing/selftests/bpf/Makefile
··· 723 723 # Generates a header with C array declaration, containing test_progs_verification_cert bytes 724 724 $(VERIFY_SIG_HDR): $(VERIFICATION_CERT) 725 725 $(Q)(echo "unsigned char test_progs_verification_cert[] = {"; \ 726 - hexdump -v -e '12/1 " 0x%02x," "\n"' $< | sed 's/0x ,//g; $$s/,$$//'; \ 726 + od -v -t 'xC' -w12 $< | sed 's/ \(\S\+\)/ 0x\1,/g;s/^\S\+/ /;$$d'; \ 727 727 echo "};"; \ 728 728 echo "unsigned int test_progs_verification_cert_len = $$(wc -c < $<);") > $@ 729 729
+6 -9
tools/testing/selftests/bpf/prog_tests/map_kptr.c
··· 118 118 119 119 static int kern_sync_rcu_tasks_trace(struct rcu_tasks_trace_gp *rcu) 120 120 { 121 - long gp_seq = READ_ONCE(rcu->bss->gp_seq); 122 121 LIBBPF_OPTS(bpf_test_run_opts, opts); 122 + int ret; 123 123 124 - if (!ASSERT_OK(bpf_prog_test_run_opts(bpf_program__fd(rcu->progs.do_call_rcu_tasks_trace), 125 - &opts), "do_call_rcu_tasks_trace")) 124 + WRITE_ONCE(rcu->bss->done, 0); 125 + ret = bpf_prog_test_run_opts(bpf_program__fd(rcu->progs.call_rcu_tasks_trace), &opts); 126 + if (!ASSERT_OK(ret, "call_rcu_tasks_trace")) 126 127 return -EFAULT; 127 - if (!ASSERT_OK(opts.retval, "opts.retval == 0")) 128 + if (!ASSERT_OK(opts.retval, "call_rcu_tasks_trace retval")) 128 129 return -EFAULT; 129 - while (gp_seq == READ_ONCE(rcu->bss->gp_seq)) 130 + while (!READ_ONCE(rcu->bss->done)) 130 131 sched_yield(); 131 132 return 0; 132 133 } ··· 160 159 skel = rcu_tasks_trace_gp__open_and_load(); 161 160 if (!ASSERT_OK_PTR(skel, "rcu_tasks_trace_gp__open_and_load")) 162 161 return; 163 - if (!ASSERT_OK(rcu_tasks_trace_gp__attach(skel), "rcu_tasks_trace_gp__attach")) 164 - goto end; 165 162 166 163 if (test__start_subtest("success-map")) { 167 164 test_map_kptr_success(true); ··· 179 180 test_map_kptr_success(true); 180 181 } 181 182 182 - end: 183 183 rcu_tasks_trace_gp__destroy(skel); 184 - return; 185 184 }
+1 -1
tools/testing/selftests/bpf/progs/get_func_args_test.c
··· 167 167 } 168 168 169 169 __u64 test7_result = 0; 170 - #if defined(bpf_target_x86) || defined(bpf_target_arm64) 170 + #if defined(bpf_target_x86) || defined(bpf_target_arm64) || defined(bpf_target_riscv) 171 171 SEC("fsession/bpf_fentry_test1") 172 172 int BPF_PROG(test7) 173 173 {
+1 -1
tools/testing/selftests/bpf/progs/get_func_ip_test.c
··· 106 106 107 107 __u64 test9_entry_result = 0; 108 108 __u64 test9_exit_result = 0; 109 - #if defined(bpf_target_x86) || defined(bpf_target_arm64) 109 + #if defined(bpf_target_x86) || defined(bpf_target_arm64) || defined(bpf_target_riscv) 110 110 SEC("fsession/bpf_fentry_test1") 111 111 int BPF_PROG(test9, int a) 112 112 {
+1 -1
tools/testing/selftests/bpf/progs/profiler.h
··· 169 169 profiler_bpf_sched_process_exec, 170 170 profiler_bpf_sched_process_exit, 171 171 profiler_bpf_sys_enter_kill, 172 - profiler_bpf_do_filp_open_ret, 172 + profiler_bpf_do_file_open_ret, 173 173 profiler_bpf_sched_process_fork, 174 174 profiler_bpf_vfs_link, 175 175 profiler_bpf_vfs_symlink,
+3 -3
tools/testing/selftests/bpf/progs/profiler.inc.h
··· 751 751 return 0; 752 752 } 753 753 754 - SEC("kretprobe/do_filp_open") 755 - int kprobe_ret__do_filp_open(struct pt_regs* ctx) 754 + SEC("kretprobe/do_file_open") 755 + int kprobe_ret__do_file_open(struct pt_regs *ctx) 756 756 { 757 757 struct bpf_func_stats_ctx stats_ctx; 758 - bpf_stats_enter(&stats_ctx, profiler_bpf_do_filp_open_ret); 758 + bpf_stats_enter(&stats_ctx, profiler_bpf_do_file_open_ret); 759 759 760 760 struct file* filp = (struct file*)PT_REGS_RC_CORE(ctx); 761 761
+4 -26
tools/testing/selftests/bpf/progs/rcu_tasks_trace_gp.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 #include <vmlinux.h> 3 - #include <bpf/bpf_tracing.h> 4 3 #include <bpf/bpf_helpers.h> 4 + #include "../test_kmods/bpf_testmod_kfunc.h" 5 5 6 - struct task_ls_map { 7 - __uint(type, BPF_MAP_TYPE_TASK_STORAGE); 8 - __uint(map_flags, BPF_F_NO_PREALLOC); 9 - __type(key, int); 10 - __type(value, int); 11 - } task_ls_map SEC(".maps"); 12 - 13 - long gp_seq; 6 + int done; 14 7 15 8 SEC("syscall") 16 - int do_call_rcu_tasks_trace(void *ctx) 9 + int call_rcu_tasks_trace(void *ctx) 17 10 { 18 - struct task_struct *current; 19 - int *v; 20 - 21 - current = bpf_get_current_task_btf(); 22 - v = bpf_task_storage_get(&task_ls_map, current, NULL, BPF_LOCAL_STORAGE_GET_F_CREATE); 23 - if (!v) 24 - return 1; 25 - /* Invoke call_rcu_tasks_trace */ 26 - return bpf_task_storage_delete(&task_ls_map, current); 27 - } 28 - 29 - SEC("kprobe/rcu_tasks_trace_postgp") 30 - int rcu_tasks_trace_postgp(void *ctx) 31 - { 32 - __sync_add_and_fetch(&gp_seq, 1); 33 - return 0; 11 + return bpf_kfunc_call_test_call_rcu_tasks_trace(&done); 34 12 } 35 13 36 14 char _license[] SEC("license") = "GPL";
+6 -6
tools/testing/selftests/bpf/progs/test_xdp_meta.c
··· 1 - #include <stdbool.h> 2 - #include <linux/bpf.h> 3 - #include <linux/errno.h> 4 - #include <linux/if_ether.h> 5 - #include <linux/pkt_cls.h> 1 + // SPDX-License-Identifier: GPL-2.0 2 + #include <vmlinux.h> 6 3 7 4 #include <bpf/bpf_endian.h> 8 5 #include <bpf/bpf_helpers.h> 6 + #include <errno.h> 7 + 9 8 #include "bpf_kfuncs.h" 9 + #include "bpf_tracing_net.h" 10 10 11 11 #define META_SIZE 32 12 12 ··· 42 42 if (!__builtin_memcmp(meta_have, meta_want, META_SIZE)) 43 43 return true; 44 44 45 - bpf_stream_printk(BPF_STREAM_STDERR, 45 + bpf_stream_printk(BPF_STDERR, 46 46 "FAIL:%s:%d: metadata mismatch\n" 47 47 " have:\n %pI6\n %pI6\n" 48 48 " want:\n %pI6\n %pI6\n",
+28
tools/testing/selftests/bpf/test_kmods/bpf_testmod.c
··· 18 18 #include <linux/in6.h> 19 19 #include <linux/un.h> 20 20 #include <linux/filter.h> 21 + #include <linux/rcupdate_trace.h> 21 22 #include <net/sock.h> 22 23 #include <linux/namei.h> 23 24 #include "bpf_testmod.h" ··· 886 885 { 887 886 } 888 887 888 + struct bpf_kfunc_rcu_tasks_trace_data { 889 + struct rcu_head rcu; 890 + int *done; 891 + }; 892 + 893 + static void bpf_kfunc_rcu_tasks_trace_cb(struct rcu_head *rhp) 894 + { 895 + struct bpf_kfunc_rcu_tasks_trace_data *data; 896 + 897 + data = container_of(rhp, struct bpf_kfunc_rcu_tasks_trace_data, rcu); 898 + WRITE_ONCE(*data->done, 1); 899 + kfree(data); 900 + } 901 + 902 + __bpf_kfunc int bpf_kfunc_call_test_call_rcu_tasks_trace(int *done) 903 + { 904 + struct bpf_kfunc_rcu_tasks_trace_data *data; 905 + 906 + data = kmalloc(sizeof(*data), GFP_ATOMIC); 907 + if (!data) 908 + return -ENOMEM; 909 + data->done = done; 910 + call_rcu_tasks_trace(&data->rcu, bpf_kfunc_rcu_tasks_trace_cb); 911 + return 0; 912 + } 913 + 889 914 __bpf_kfunc int bpf_kfunc_init_sock(struct init_sock_args *args) 890 915 { 891 916 int proto; ··· 1249 1222 BTF_ID_FLAGS(func, bpf_kfunc_call_test_static_unused_arg) 1250 1223 BTF_ID_FLAGS(func, bpf_kfunc_call_test_offset) 1251 1224 BTF_ID_FLAGS(func, bpf_kfunc_call_test_sleepable, KF_SLEEPABLE) 1225 + BTF_ID_FLAGS(func, bpf_kfunc_call_test_call_rcu_tasks_trace) 1252 1226 BTF_ID_FLAGS(func, bpf_kfunc_init_sock, KF_SLEEPABLE) 1253 1227 BTF_ID_FLAGS(func, bpf_kfunc_close_sock, KF_SLEEPABLE) 1254 1228 BTF_ID_FLAGS(func, bpf_kfunc_call_kernel_connect, KF_SLEEPABLE)
+1
tools/testing/selftests/bpf/test_kmods/bpf_testmod_kfunc.h
··· 118 118 119 119 void bpf_kfunc_call_test_destructive(void) __ksym; 120 120 void bpf_kfunc_call_test_sleepable(void) __ksym; 121 + int bpf_kfunc_call_test_call_rcu_tasks_trace(int *done) __ksym; 121 122 122 123 void bpf_kfunc_call_test_offset(struct prog_test_ref_kfunc *p); 123 124 struct prog_test_member *bpf_kfunc_call_memb_acquire(void);