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

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-03-25

We've added 38 non-merge commits during the last 13 day(s) which contain
a total of 50 files changed, 867 insertions(+), 274 deletions(-).

The main changes are:

1) Add the ability to specify and retrieve BPF cookie also for raw
tracepoint programs in order to ease migration from classic to raw
tracepoints, from Andrii Nakryiko.

2) Allow the use of bpf_get_{ns_,}current_pid_tgid() helper for all
program types and add additional BPF selftests, from Yonghong Song.

3) Several improvements to bpftool and its build, for example, enabling
libbpf logs when loading pid_iter in debug mode, from Quentin Monnet.

4) Check the return code of all BPF-related set_memory_*() functions during
load and bail out in case they fail, from Christophe Leroy.

5) Avoid a goto in regs_refine_cond_op() such that the verifier can
be better integrated into Agni tool which doesn't support backedges
yet, from Harishankar Vishwanathan.

6) Add a small BPF trie perf improvement by always inlining
longest_prefix_match, from Jesper Dangaard Brouer.

7) Small BPF selftest refactor in bpf_tcp_ca.c to utilize start_server()
helper instead of open-coding it, from Geliang Tang.

8) Improve test_tc_tunnel.sh BPF selftest to prevent client connect
before the server bind, from Alessandro Carminati.

9) Fix BPF selftest benchmark for older glibc and use syscall(SYS_gettid)
instead of gettid(), from Alan Maguire.

10) Implement a backward-compatible method for struct_ops types with
additional fields which are not present in older kernels,
from Kui-Feng Lee.

11) Add a small helper to check if an instruction is addr_space_cast
from as(0) to as(1) and utilize it in x86-64 JIT, from Puranjay Mohan.

12) Small cleanup to remove unnecessary error check in
bpf_struct_ops_map_update_elem, from Martin KaFai Lau.

13) Improvements to libbpf fd validity checks for BPF map/programs,
from Mykyta Yatsenko.

* tag 'for-netdev' of https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next: (38 commits)
selftests/bpf: Fix flaky test btf_map_in_map/lookup_update
bpf: implement insn_is_cast_user() helper for JITs
bpf: Avoid get_kernel_nofault() to fetch kprobe entry IP
selftests/bpf: Use start_server in bpf_tcp_ca
bpf: Sync uapi bpf.h to tools directory
libbpf: Add new sec_def "sk_skb/verdict"
selftests/bpf: Mark uprobe trigger functions with nocf_check attribute
selftests/bpf: Use syscall(SYS_gettid) instead of gettid() wrapper in bench
bpf-next: Avoid goto in regs_refine_cond_op()
bpftool: Clean up HOST_CFLAGS, HOST_LDFLAGS for bootstrap bpftool
selftests/bpf: scale benchmark counting by using per-CPU counters
bpftool: Remove unnecessary source files from bootstrap version
bpftool: Enable libbpf logs when loading pid_iter in debug mode
selftests/bpf: add raw_tp/tp_btf BPF cookie subtests
libbpf: add support for BPF cookie for raw_tp/tp_btf programs
bpf: support BPF cookie in raw tracepoint (raw_tp, tp_btf) programs
bpf: pass whole link instead of prog when triggering raw tracepoint
bpf: flatten bpf_probe_register call chain
selftests/bpf: Prevent client connect before server bind in test_tc_tunnel.sh
selftests/bpf: Add a sk_msg prog bpf_get_ns_current_pid_tgid() test
...
====================

Link: https://lore.kernel.org/r/20240325233940.7154-1-daniel@iogearbox.net
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+868 -275
+12 -13
arch/arm/net/bpf_jit_32.c
··· 2222 2222 /* If building the body of the JITed code fails somehow, 2223 2223 * we fall back to the interpretation. 2224 2224 */ 2225 - if (build_body(&ctx) < 0) { 2226 - image_ptr = NULL; 2227 - bpf_jit_binary_free(header); 2228 - prog = orig_prog; 2229 - goto out_imms; 2230 - } 2225 + if (build_body(&ctx) < 0) 2226 + goto out_free; 2231 2227 build_epilogue(&ctx); 2232 2228 2233 2229 /* 3.) Extra pass to validate JITed Code */ 2234 - if (validate_code(&ctx)) { 2235 - image_ptr = NULL; 2236 - bpf_jit_binary_free(header); 2237 - prog = orig_prog; 2238 - goto out_imms; 2239 - } 2230 + if (validate_code(&ctx)) 2231 + goto out_free; 2240 2232 flush_icache_range((u32)header, (u32)(ctx.target + ctx.idx)); 2241 2233 2242 2234 if (bpf_jit_enable > 1) 2243 2235 /* there are 2 passes here */ 2244 2236 bpf_jit_dump(prog->len, image_size, 2, ctx.target); 2245 2237 2246 - bpf_jit_binary_lock_ro(header); 2238 + if (bpf_jit_binary_lock_ro(header)) 2239 + goto out_free; 2247 2240 prog->bpf_func = (void *)ctx.target; 2248 2241 prog->jited = 1; 2249 2242 prog->jited_len = image_size; ··· 2253 2260 bpf_jit_prog_release_other(prog, prog == orig_prog ? 2254 2261 tmp : orig_prog); 2255 2262 return prog; 2263 + 2264 + out_free: 2265 + image_ptr = NULL; 2266 + bpf_jit_binary_free(header); 2267 + prog = orig_prog; 2268 + goto out_imms; 2256 2269 } 2257 2270
+2 -5
arch/arm64/net/bpf_jit_comp.c
··· 2176 2176 bpf_prog_pack_free(image, size); 2177 2177 } 2178 2178 2179 - void arch_protect_bpf_trampoline(void *image, unsigned int size) 2179 + int arch_protect_bpf_trampoline(void *image, unsigned int size) 2180 2180 { 2181 - } 2182 - 2183 - void arch_unprotect_bpf_trampoline(void *image, unsigned int size) 2184 - { 2181 + return 0; 2185 2182 } 2186 2183 2187 2184 int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *ro_image,
+16 -6
arch/loongarch/net/bpf_jit.c
··· 1294 1294 flush_icache_range((unsigned long)header, (unsigned long)(ctx.image + ctx.idx)); 1295 1295 1296 1296 if (!prog->is_func || extra_pass) { 1297 + int err; 1298 + 1297 1299 if (extra_pass && ctx.idx != jit_data->ctx.idx) { 1298 1300 pr_err_once("multi-func JIT bug %d != %d\n", 1299 1301 ctx.idx, jit_data->ctx.idx); 1300 - bpf_jit_binary_free(header); 1301 - prog->bpf_func = NULL; 1302 - prog->jited = 0; 1303 - prog->jited_len = 0; 1304 - goto out_offset; 1302 + goto out_free; 1305 1303 } 1306 - bpf_jit_binary_lock_ro(header); 1304 + err = bpf_jit_binary_lock_ro(header); 1305 + if (err) { 1306 + pr_err_once("bpf_jit_binary_lock_ro() returned %d\n", 1307 + err); 1308 + goto out_free; 1309 + } 1307 1310 } else { 1308 1311 jit_data->ctx = ctx; 1309 1312 jit_data->image = image_ptr; ··· 1337 1334 out_offset = -1; 1338 1335 1339 1336 return prog; 1337 + 1338 + out_free: 1339 + bpf_jit_binary_free(header); 1340 + prog->bpf_func = NULL; 1341 + prog->jited = 0; 1342 + prog->jited_len = 0; 1343 + goto out_offset; 1340 1344 } 1341 1345 1342 1346 /* Indicate the JIT backend supports mixing bpf2bpf and tailcalls. */
+2 -1
arch/mips/net/bpf_jit_comp.c
··· 1012 1012 bpf_prog_fill_jited_linfo(prog, &ctx.descriptors[1]); 1013 1013 1014 1014 /* Set as read-only exec and flush instruction cache */ 1015 - bpf_jit_binary_lock_ro(header); 1015 + if (bpf_jit_binary_lock_ro(header)) 1016 + goto out_err; 1016 1017 flush_icache_range((unsigned long)header, 1017 1018 (unsigned long)&ctx.target[ctx.jit_index]); 1018 1019
+7 -1
arch/parisc/net/bpf_jit_core.c
··· 167 167 bpf_flush_icache(jit_data->header, ctx->insns + ctx->ninsns); 168 168 169 169 if (!prog->is_func || extra_pass) { 170 - bpf_jit_binary_lock_ro(jit_data->header); 170 + if (bpf_jit_binary_lock_ro(jit_data->header)) { 171 + bpf_jit_binary_free(jit_data->header); 172 + prog->bpf_func = NULL; 173 + prog->jited = 0; 174 + prog->jited_len = 0; 175 + goto out_offset; 176 + } 171 177 prologue_len = ctx->epilogue_offset - ctx->body_len; 172 178 for (i = 0; i < prog->len; i++) 173 179 ctx->offset[i] += prologue_len;
+5 -1
arch/s390/net/bpf_jit_comp.c
··· 2111 2111 print_fn_code(jit.prg_buf, jit.size_prg); 2112 2112 } 2113 2113 if (!fp->is_func || extra_pass) { 2114 - bpf_jit_binary_lock_ro(header); 2114 + if (bpf_jit_binary_lock_ro(header)) { 2115 + bpf_jit_binary_free(header); 2116 + fp = orig_fp; 2117 + goto free_addrs; 2118 + } 2115 2119 } else { 2116 2120 jit_data->header = header; 2117 2121 jit_data->ctx = jit;
+5 -1
arch/sparc/net/bpf_jit_comp_64.c
··· 1602 1602 bpf_flush_icache(header, (u8 *)header + header->size); 1603 1603 1604 1604 if (!prog->is_func || extra_pass) { 1605 - bpf_jit_binary_lock_ro(header); 1605 + if (bpf_jit_binary_lock_ro(header)) { 1606 + bpf_jit_binary_free(header); 1607 + prog = orig_prog; 1608 + goto out_off; 1609 + } 1606 1610 } else { 1607 1611 jit_data->ctx = ctx; 1608 1612 jit_data->image = image_ptr;
+3 -7
arch/x86/net/bpf_jit_comp.c
··· 1351 1351 break; 1352 1352 1353 1353 case BPF_ALU64 | BPF_MOV | BPF_X: 1354 - if (insn->off == BPF_ADDR_SPACE_CAST && 1355 - insn->imm == 1U << 16) { 1354 + if (insn_is_cast_user(insn)) { 1356 1355 if (dst_reg != src_reg) 1357 1356 /* 32-bit mov */ 1358 1357 emit_mov_reg(&prog, false, dst_reg, src_reg); ··· 3003 3004 bpf_prog_pack_free(image, size); 3004 3005 } 3005 3006 3006 - void arch_protect_bpf_trampoline(void *image, unsigned int size) 3007 + int arch_protect_bpf_trampoline(void *image, unsigned int size) 3007 3008 { 3008 - } 3009 - 3010 - void arch_unprotect_bpf_trampoline(void *image, unsigned int size) 3011 - { 3009 + return 0; 3012 3010 } 3013 3011 3014 3012 int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image, void *image_end,
+1 -2
arch/x86/net/bpf_jit_comp32.c
··· 2600 2600 if (bpf_jit_enable > 1) 2601 2601 bpf_jit_dump(prog->len, proglen, pass + 1, image); 2602 2602 2603 - if (image) { 2604 - bpf_jit_binary_lock_ro(header); 2603 + if (image && !bpf_jit_binary_lock_ro(header)) { 2605 2604 prog->bpf_func = (void *)image; 2606 2605 prog->jited = 1; 2607 2606 prog->jited_len = proglen;
+7 -2
include/linux/bpf.h
··· 1116 1116 void *func_addr); 1117 1117 void *arch_alloc_bpf_trampoline(unsigned int size); 1118 1118 void arch_free_bpf_trampoline(void *image, unsigned int size); 1119 - void arch_protect_bpf_trampoline(void *image, unsigned int size); 1120 - void arch_unprotect_bpf_trampoline(void *image, unsigned int size); 1119 + int __must_check arch_protect_bpf_trampoline(void *image, unsigned int size); 1121 1120 int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags, 1122 1121 struct bpf_tramp_links *tlinks, void *func_addr); 1123 1122 ··· 1605 1606 enum bpf_attach_type attach_type; 1606 1607 struct bpf_trampoline *trampoline; 1607 1608 struct bpf_prog *tgt_prog; 1609 + }; 1610 + 1611 + struct bpf_raw_tp_link { 1612 + struct bpf_link link; 1613 + struct bpf_raw_event_map *btp; 1614 + u64 cookie; 1608 1615 }; 1609 1616 1610 1617 struct bpf_link_primer {
+16 -4
include/linux/filter.h
··· 228 228 return insn->code == (BPF_ALU | BPF_MOV | BPF_X) && insn->imm == 1; 229 229 } 230 230 231 + /* addr_space_cast from as(0) to as(1) is for converting bpf arena pointers 232 + * to pointers in user vma. 233 + */ 234 + static inline bool insn_is_cast_user(const struct bpf_insn *insn) 235 + { 236 + return insn->code == (BPF_ALU64 | BPF_MOV | BPF_X) && 237 + insn->off == BPF_ADDR_SPACE_CAST && 238 + insn->imm == 1U << 16; 239 + } 240 + 231 241 /* BPF_LD_IMM64 macro encodes single 'load 64-bit immediate' insn */ 232 242 #define BPF_LD_IMM64(DST, IMM) \ 233 243 BPF_LD_IMM64_RAW(DST, 0, IMM) ··· 897 887 898 888 #define bpf_classic_proglen(fprog) (fprog->len * sizeof(fprog->filter[0])) 899 889 900 - static inline void bpf_prog_lock_ro(struct bpf_prog *fp) 890 + static inline int __must_check bpf_prog_lock_ro(struct bpf_prog *fp) 901 891 { 902 892 #ifndef CONFIG_BPF_JIT_ALWAYS_ON 903 893 if (!fp->jited) { 904 894 set_vm_flush_reset_perms(fp); 905 - set_memory_ro((unsigned long)fp, fp->pages); 895 + return set_memory_ro((unsigned long)fp, fp->pages); 906 896 } 907 897 #endif 898 + return 0; 908 899 } 909 900 910 - static inline void bpf_jit_binary_lock_ro(struct bpf_binary_header *hdr) 901 + static inline int __must_check 902 + bpf_jit_binary_lock_ro(struct bpf_binary_header *hdr) 911 903 { 912 904 set_vm_flush_reset_perms(hdr); 913 - set_memory_rox((unsigned long)hdr, hdr->size >> PAGE_SHIFT); 905 + return set_memory_rox((unsigned long)hdr, hdr->size >> PAGE_SHIFT); 914 906 } 915 907 916 908 int sk_filter_trim_cap(struct sock *sk, struct sk_buff *skb, unsigned int cap);
+20 -16
include/linux/trace_events.h
··· 765 765 int perf_event_attach_bpf_prog(struct perf_event *event, struct bpf_prog *prog, u64 bpf_cookie); 766 766 void perf_event_detach_bpf_prog(struct perf_event *event); 767 767 int perf_event_query_prog_array(struct perf_event *event, void __user *info); 768 - int bpf_probe_register(struct bpf_raw_event_map *btp, struct bpf_prog *prog); 769 - int bpf_probe_unregister(struct bpf_raw_event_map *btp, struct bpf_prog *prog); 768 + 769 + struct bpf_raw_tp_link; 770 + int bpf_probe_register(struct bpf_raw_event_map *btp, struct bpf_raw_tp_link *link); 771 + int bpf_probe_unregister(struct bpf_raw_event_map *btp, struct bpf_raw_tp_link *link); 772 + 770 773 struct bpf_raw_event_map *bpf_get_raw_tracepoint(const char *name); 771 774 void bpf_put_raw_tracepoint(struct bpf_raw_event_map *btp); 772 775 int bpf_get_perf_event_info(const struct perf_event *event, u32 *prog_id, ··· 797 794 { 798 795 return -EOPNOTSUPP; 799 796 } 800 - static inline int bpf_probe_register(struct bpf_raw_event_map *btp, struct bpf_prog *p) 797 + struct bpf_raw_tp_link; 798 + static inline int bpf_probe_register(struct bpf_raw_event_map *btp, struct bpf_raw_tp_link *link) 801 799 { 802 800 return -EOPNOTSUPP; 803 801 } 804 - static inline int bpf_probe_unregister(struct bpf_raw_event_map *btp, struct bpf_prog *p) 802 + static inline int bpf_probe_unregister(struct bpf_raw_event_map *btp, struct bpf_raw_tp_link *link) 805 803 { 806 804 return -EOPNOTSUPP; 807 805 } ··· 913 909 int perf_event_set_bpf_prog(struct perf_event *event, struct bpf_prog *prog, u64 bpf_cookie); 914 910 void perf_event_free_bpf_prog(struct perf_event *event); 915 911 916 - void bpf_trace_run1(struct bpf_prog *prog, u64 arg1); 917 - void bpf_trace_run2(struct bpf_prog *prog, u64 arg1, u64 arg2); 918 - void bpf_trace_run3(struct bpf_prog *prog, u64 arg1, u64 arg2, 912 + void bpf_trace_run1(struct bpf_raw_tp_link *link, u64 arg1); 913 + void bpf_trace_run2(struct bpf_raw_tp_link *link, u64 arg1, u64 arg2); 914 + void bpf_trace_run3(struct bpf_raw_tp_link *link, u64 arg1, u64 arg2, 919 915 u64 arg3); 920 - void bpf_trace_run4(struct bpf_prog *prog, u64 arg1, u64 arg2, 916 + void bpf_trace_run4(struct bpf_raw_tp_link *link, u64 arg1, u64 arg2, 921 917 u64 arg3, u64 arg4); 922 - void bpf_trace_run5(struct bpf_prog *prog, u64 arg1, u64 arg2, 918 + void bpf_trace_run5(struct bpf_raw_tp_link *link, u64 arg1, u64 arg2, 923 919 u64 arg3, u64 arg4, u64 arg5); 924 - void bpf_trace_run6(struct bpf_prog *prog, u64 arg1, u64 arg2, 920 + void bpf_trace_run6(struct bpf_raw_tp_link *link, u64 arg1, u64 arg2, 925 921 u64 arg3, u64 arg4, u64 arg5, u64 arg6); 926 - void bpf_trace_run7(struct bpf_prog *prog, u64 arg1, u64 arg2, 922 + void bpf_trace_run7(struct bpf_raw_tp_link *link, u64 arg1, u64 arg2, 927 923 u64 arg3, u64 arg4, u64 arg5, u64 arg6, u64 arg7); 928 - void bpf_trace_run8(struct bpf_prog *prog, u64 arg1, u64 arg2, 924 + void bpf_trace_run8(struct bpf_raw_tp_link *link, u64 arg1, u64 arg2, 929 925 u64 arg3, u64 arg4, u64 arg5, u64 arg6, u64 arg7, 930 926 u64 arg8); 931 - void bpf_trace_run9(struct bpf_prog *prog, u64 arg1, u64 arg2, 927 + void bpf_trace_run9(struct bpf_raw_tp_link *link, u64 arg1, u64 arg2, 932 928 u64 arg3, u64 arg4, u64 arg5, u64 arg6, u64 arg7, 933 929 u64 arg8, u64 arg9); 934 - void bpf_trace_run10(struct bpf_prog *prog, u64 arg1, u64 arg2, 930 + void bpf_trace_run10(struct bpf_raw_tp_link *link, u64 arg1, u64 arg2, 935 931 u64 arg3, u64 arg4, u64 arg5, u64 arg6, u64 arg7, 936 932 u64 arg8, u64 arg9, u64 arg10); 937 - void bpf_trace_run11(struct bpf_prog *prog, u64 arg1, u64 arg2, 933 + void bpf_trace_run11(struct bpf_raw_tp_link *link, u64 arg1, u64 arg2, 938 934 u64 arg3, u64 arg4, u64 arg5, u64 arg6, u64 arg7, 939 935 u64 arg8, u64 arg9, u64 arg10, u64 arg11); 940 - void bpf_trace_run12(struct bpf_prog *prog, u64 arg1, u64 arg2, 936 + void bpf_trace_run12(struct bpf_raw_tp_link *link, u64 arg1, u64 arg2, 941 937 u64 arg3, u64 arg4, u64 arg5, u64 arg6, u64 arg7, 942 938 u64 arg8, u64 arg9, u64 arg10, u64 arg11, u64 arg12); 943 939 void perf_trace_run_bpf_submit(void *raw_data, int size, int rctx,
+1 -2
include/trace/bpf_probe.h
··· 46 46 static notrace void \ 47 47 __bpf_trace_##call(void *__data, proto) \ 48 48 { \ 49 - struct bpf_prog *prog = __data; \ 50 - CONCATENATE(bpf_trace_run, COUNT_ARGS(args))(prog, CAST_TO_U64(args)); \ 49 + CONCATENATE(bpf_trace_run, COUNT_ARGS(args))(__data, CAST_TO_U64(args)); \ 51 50 } 52 51 53 52 #undef DECLARE_EVENT_CLASS
+4 -2
include/uapi/linux/bpf.h
··· 1662 1662 } query; 1663 1663 1664 1664 struct { /* anonymous struct used by BPF_RAW_TRACEPOINT_OPEN command */ 1665 - __u64 name; 1666 - __u32 prog_fd; 1665 + __u64 name; 1666 + __u32 prog_fd; 1667 + __u32 :32; 1668 + __aligned_u64 cookie; 1667 1669 } raw_tracepoint; 1668 1670 1669 1671 struct { /* anonymous struct for BPF_BTF_LOAD */
+6 -4
kernel/bpf/bpf_struct_ops.c
··· 728 728 cur_image = image; 729 729 trampoline_start = 0; 730 730 } 731 - if (err < 0) 732 - goto reset_unlock; 733 731 734 732 *(void **)(kdata + moff) = image + trampoline_start + cfi_get_offset(); 735 733 ··· 740 742 if (err) 741 743 goto reset_unlock; 742 744 } 743 - for (i = 0; i < st_map->image_pages_cnt; i++) 744 - arch_protect_bpf_trampoline(st_map->image_pages[i], PAGE_SIZE); 745 + for (i = 0; i < st_map->image_pages_cnt; i++) { 746 + err = arch_protect_bpf_trampoline(st_map->image_pages[i], 747 + PAGE_SIZE); 748 + if (err) 749 + goto reset_unlock; 750 + } 745 751 746 752 if (st_map->map.map_flags & BPF_F_LINK) { 747 753 err = 0;
-2
kernel/bpf/cgroup.c
··· 2575 2575 switch (func_id) { 2576 2576 case BPF_FUNC_get_current_uid_gid: 2577 2577 return &bpf_get_current_uid_gid_proto; 2578 - case BPF_FUNC_get_current_pid_tgid: 2579 - return &bpf_get_current_pid_tgid_proto; 2580 2578 case BPF_FUNC_get_current_comm: 2581 2579 return &bpf_get_current_comm_proto; 2582 2580 #ifdef CONFIG_CGROUP_NET_CLASSID
+24 -8
kernel/bpf/core.c
··· 908 908 static struct bpf_prog_pack *alloc_new_pack(bpf_jit_fill_hole_t bpf_fill_ill_insns) 909 909 { 910 910 struct bpf_prog_pack *pack; 911 + int err; 911 912 912 913 pack = kzalloc(struct_size(pack, bitmap, BITS_TO_LONGS(BPF_PROG_CHUNK_COUNT)), 913 914 GFP_KERNEL); 914 915 if (!pack) 915 916 return NULL; 916 917 pack->ptr = bpf_jit_alloc_exec(BPF_PROG_PACK_SIZE); 917 - if (!pack->ptr) { 918 - kfree(pack); 919 - return NULL; 920 - } 918 + if (!pack->ptr) 919 + goto out; 921 920 bpf_fill_ill_insns(pack->ptr, BPF_PROG_PACK_SIZE); 922 921 bitmap_zero(pack->bitmap, BPF_PROG_PACK_SIZE / BPF_PROG_CHUNK_SIZE); 923 - list_add_tail(&pack->list, &pack_list); 924 922 925 923 set_vm_flush_reset_perms(pack->ptr); 926 - set_memory_rox((unsigned long)pack->ptr, BPF_PROG_PACK_SIZE / PAGE_SIZE); 924 + err = set_memory_rox((unsigned long)pack->ptr, 925 + BPF_PROG_PACK_SIZE / PAGE_SIZE); 926 + if (err) 927 + goto out; 928 + list_add_tail(&pack->list, &pack_list); 927 929 return pack; 930 + 931 + out: 932 + bpf_jit_free_exec(pack->ptr); 933 + kfree(pack); 934 + return NULL; 928 935 } 929 936 930 937 void *bpf_prog_pack_alloc(u32 size, bpf_jit_fill_hole_t bpf_fill_ill_insns) ··· 946 939 size = round_up(size, PAGE_SIZE); 947 940 ptr = bpf_jit_alloc_exec(size); 948 941 if (ptr) { 942 + int err; 943 + 949 944 bpf_fill_ill_insns(ptr, size); 950 945 set_vm_flush_reset_perms(ptr); 951 - set_memory_rox((unsigned long)ptr, size / PAGE_SIZE); 946 + err = set_memory_rox((unsigned long)ptr, 947 + size / PAGE_SIZE); 948 + if (err) { 949 + bpf_jit_free_exec(ptr); 950 + ptr = NULL; 951 + } 952 952 } 953 953 goto out; 954 954 } ··· 2417 2403 } 2418 2404 2419 2405 finalize: 2420 - bpf_prog_lock_ro(fp); 2406 + *err = bpf_prog_lock_ro(fp); 2407 + if (*err) 2408 + return fp; 2421 2409 2422 2410 /* The tail call compatibility check can only be done at 2423 2411 * this late stage as we need to determine, if we deal
+4
kernel/bpf/helpers.c
··· 1730 1730 return &bpf_strtol_proto; 1731 1731 case BPF_FUNC_strtoul: 1732 1732 return &bpf_strtoul_proto; 1733 + case BPF_FUNC_get_current_pid_tgid: 1734 + return &bpf_get_current_pid_tgid_proto; 1735 + case BPF_FUNC_get_ns_current_pid_tgid: 1736 + return &bpf_get_ns_current_pid_tgid_proto; 1733 1737 default: 1734 1738 break; 1735 1739 }
+13 -5
kernel/bpf/lpm_trie.c
··· 155 155 } 156 156 157 157 /** 158 - * longest_prefix_match() - determine the longest prefix 158 + * __longest_prefix_match() - determine the longest prefix 159 159 * @trie: The trie to get internal sizes from 160 160 * @node: The node to operate on 161 161 * @key: The key to compare to @node 162 162 * 163 163 * Determine the longest prefix of @node that matches the bits in @key. 164 164 */ 165 - static size_t longest_prefix_match(const struct lpm_trie *trie, 166 - const struct lpm_trie_node *node, 167 - const struct bpf_lpm_trie_key_u8 *key) 165 + static __always_inline 166 + size_t __longest_prefix_match(const struct lpm_trie *trie, 167 + const struct lpm_trie_node *node, 168 + const struct bpf_lpm_trie_key_u8 *key) 168 169 { 169 170 u32 limit = min(node->prefixlen, key->prefixlen); 170 171 u32 prefixlen = 0, i = 0; ··· 225 224 return prefixlen; 226 225 } 227 226 227 + static size_t longest_prefix_match(const struct lpm_trie *trie, 228 + const struct lpm_trie_node *node, 229 + const struct bpf_lpm_trie_key_u8 *key) 230 + { 231 + return __longest_prefix_match(trie, node, key); 232 + } 233 + 228 234 /* Called from syscall or from eBPF program */ 229 235 static void *trie_lookup_elem(struct bpf_map *map, void *_key) 230 236 { ··· 253 245 * If it's the maximum possible prefix for this trie, we have 254 246 * an exact match and can return it directly. 255 247 */ 256 - matchlen = longest_prefix_match(trie, node, key); 248 + matchlen = __longest_prefix_match(trie, node, key); 257 249 if (matchlen == trie->max_prefixlen) { 258 250 found = node; 259 251 break;
+11 -11
kernel/bpf/syscall.c
··· 3469 3469 return err; 3470 3470 } 3471 3471 3472 - struct bpf_raw_tp_link { 3473 - struct bpf_link link; 3474 - struct bpf_raw_event_map *btp; 3475 - }; 3476 - 3477 3472 static void bpf_raw_tp_link_release(struct bpf_link *link) 3478 3473 { 3479 3474 struct bpf_raw_tp_link *raw_tp = 3480 3475 container_of(link, struct bpf_raw_tp_link, link); 3481 3476 3482 - bpf_probe_unregister(raw_tp->btp, raw_tp->link.prog); 3477 + bpf_probe_unregister(raw_tp->btp, raw_tp); 3483 3478 bpf_put_raw_tracepoint(raw_tp->btp); 3484 3479 } 3485 3480 ··· 3774 3779 #endif /* CONFIG_PERF_EVENTS */ 3775 3780 3776 3781 static int bpf_raw_tp_link_attach(struct bpf_prog *prog, 3777 - const char __user *user_tp_name) 3782 + const char __user *user_tp_name, u64 cookie) 3778 3783 { 3779 3784 struct bpf_link_primer link_primer; 3780 3785 struct bpf_raw_tp_link *link; ··· 3821 3826 bpf_link_init(&link->link, BPF_LINK_TYPE_RAW_TRACEPOINT, 3822 3827 &bpf_raw_tp_link_lops, prog); 3823 3828 link->btp = btp; 3829 + link->cookie = cookie; 3824 3830 3825 3831 err = bpf_link_prime(&link->link, &link_primer); 3826 3832 if (err) { ··· 3829 3833 goto out_put_btp; 3830 3834 } 3831 3835 3832 - err = bpf_probe_register(link->btp, prog); 3836 + err = bpf_probe_register(link->btp, link); 3833 3837 if (err) { 3834 3838 bpf_link_cleanup(&link_primer); 3835 3839 goto out_put_btp; ··· 3842 3846 return err; 3843 3847 } 3844 3848 3845 - #define BPF_RAW_TRACEPOINT_OPEN_LAST_FIELD raw_tracepoint.prog_fd 3849 + #define BPF_RAW_TRACEPOINT_OPEN_LAST_FIELD raw_tracepoint.cookie 3846 3850 3847 3851 static int bpf_raw_tracepoint_open(const union bpf_attr *attr) 3848 3852 { 3849 3853 struct bpf_prog *prog; 3854 + void __user *tp_name; 3855 + __u64 cookie; 3850 3856 int fd; 3851 3857 3852 3858 if (CHECK_ATTR(BPF_RAW_TRACEPOINT_OPEN)) ··· 3858 3860 if (IS_ERR(prog)) 3859 3861 return PTR_ERR(prog); 3860 3862 3861 - fd = bpf_raw_tp_link_attach(prog, u64_to_user_ptr(attr->raw_tracepoint.name)); 3863 + tp_name = u64_to_user_ptr(attr->raw_tracepoint.name); 3864 + cookie = attr->raw_tracepoint.cookie; 3865 + fd = bpf_raw_tp_link_attach(prog, tp_name, cookie); 3862 3866 if (fd < 0) 3863 3867 bpf_prog_put(prog); 3864 3868 return fd; ··· 5198 5198 goto out; 5199 5199 } 5200 5200 if (prog->expected_attach_type == BPF_TRACE_RAW_TP) 5201 - ret = bpf_raw_tp_link_attach(prog, NULL); 5201 + ret = bpf_raw_tp_link_attach(prog, NULL, attr->link_create.tracing.cookie); 5202 5202 else if (prog->expected_attach_type == BPF_TRACE_ITER) 5203 5203 ret = bpf_iter_link_attach(attr, uattr, prog); 5204 5204 else if (prog->expected_attach_type == BPF_LSM_CGROUP)
+5 -10
kernel/bpf/trampoline.c
··· 456 456 if (err < 0) 457 457 goto out_free; 458 458 459 - arch_protect_bpf_trampoline(im->image, im->size); 459 + err = arch_protect_bpf_trampoline(im->image, im->size); 460 + if (err) 461 + goto out_free; 460 462 461 463 WARN_ON(tr->cur_image && total == 0); 462 464 if (tr->cur_image) ··· 1074 1072 bpf_jit_free_exec(image); 1075 1073 } 1076 1074 1077 - void __weak arch_protect_bpf_trampoline(void *image, unsigned int size) 1075 + int __weak arch_protect_bpf_trampoline(void *image, unsigned int size) 1078 1076 { 1079 1077 WARN_ON_ONCE(size > PAGE_SIZE); 1080 - set_memory_rox((long)image, 1); 1081 - } 1082 - 1083 - void __weak arch_unprotect_bpf_trampoline(void *image, unsigned int size) 1084 - { 1085 - WARN_ON_ONCE(size > PAGE_SIZE); 1086 - set_memory_nx((long)image, 1); 1087 - set_memory_rw((long)image, 1); 1078 + return set_memory_rox((long)image, 1); 1088 1079 } 1089 1080 1090 1081 int __weak arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags,
+20 -11
kernel/bpf/verifier.c
··· 14544 14544 struct tnum t; 14545 14545 u64 val; 14546 14546 14547 - again: 14547 + /* In case of GE/GT/SGE/JST, reuse LE/LT/SLE/SLT logic from below */ 14548 + switch (opcode) { 14549 + case BPF_JGE: 14550 + case BPF_JGT: 14551 + case BPF_JSGE: 14552 + case BPF_JSGT: 14553 + opcode = flip_opcode(opcode); 14554 + swap(reg1, reg2); 14555 + break; 14556 + default: 14557 + break; 14558 + } 14559 + 14548 14560 switch (opcode) { 14549 14561 case BPF_JEQ: 14550 14562 if (is_jmp32) { ··· 14699 14687 reg2->smin_value = max(reg1->smin_value + 1, reg2->smin_value); 14700 14688 } 14701 14689 break; 14702 - case BPF_JGE: 14703 - case BPF_JGT: 14704 - case BPF_JSGE: 14705 - case BPF_JSGT: 14706 - /* just reuse LE/LT logic above */ 14707 - opcode = flip_opcode(opcode); 14708 - swap(reg1, reg2); 14709 - goto again; 14710 14690 default: 14711 14691 return; 14712 14692 } ··· 19162 19158 if (bpf_prog_calc_tag(func[i])) 19163 19159 goto out_free; 19164 19160 func[i]->is_func = 1; 19161 + func[i]->sleepable = prog->sleepable; 19165 19162 func[i]->aux->func_idx = i; 19166 19163 /* Below members will be freed only at prog->aux */ 19167 19164 func[i]->aux->btf = prog->aux->btf; ··· 19267 19262 * bpf_prog_load will add the kallsyms for the main program. 19268 19263 */ 19269 19264 for (i = 1; i < env->subprog_cnt; i++) { 19270 - bpf_prog_lock_ro(func[i]); 19271 - bpf_prog_kallsyms_add(func[i]); 19265 + err = bpf_prog_lock_ro(func[i]); 19266 + if (err) 19267 + goto out_free; 19272 19268 } 19269 + 19270 + for (i = 1; i < env->subprog_cnt; i++) 19271 + bpf_prog_kallsyms_add(func[i]); 19273 19272 19274 19273 /* Last step: make now unused interpreter insns from main 19275 19274 * prog consistent for later dump requests, so they can
+32 -20
kernel/trace/bpf_trace.c
··· 1053 1053 { 1054 1054 u32 instr; 1055 1055 1056 - /* Being extra safe in here in case entry ip is on the page-edge. */ 1057 - if (get_kernel_nofault(instr, (u32 *) fentry_ip - 1)) 1058 - return fentry_ip; 1056 + /* We want to be extra safe in case entry ip is on the page edge, 1057 + * but otherwise we need to avoid get_kernel_nofault()'s overhead. 1058 + */ 1059 + if ((fentry_ip & ~PAGE_MASK) < ENDBR_INSN_SIZE) { 1060 + if (get_kernel_nofault(instr, (u32 *)(fentry_ip - ENDBR_INSN_SIZE))) 1061 + return fentry_ip; 1062 + } else { 1063 + instr = *(u32 *)(fentry_ip - ENDBR_INSN_SIZE); 1064 + } 1059 1065 if (is_endbr(instr)) 1060 1066 fentry_ip -= ENDBR_INSN_SIZE; 1061 1067 return fentry_ip; ··· 1531 1525 return &bpf_ktime_get_boot_ns_proto; 1532 1526 case BPF_FUNC_tail_call: 1533 1527 return &bpf_tail_call_proto; 1534 - case BPF_FUNC_get_current_pid_tgid: 1535 - return &bpf_get_current_pid_tgid_proto; 1536 1528 case BPF_FUNC_get_current_task: 1537 1529 return &bpf_get_current_task_proto; 1538 1530 case BPF_FUNC_get_current_task_btf: ··· 1586 1582 return &bpf_send_signal_thread_proto; 1587 1583 case BPF_FUNC_perf_event_read_value: 1588 1584 return &bpf_perf_event_read_value_proto; 1589 - case BPF_FUNC_get_ns_current_pid_tgid: 1590 - return &bpf_get_ns_current_pid_tgid_proto; 1591 1585 case BPF_FUNC_ringbuf_output: 1592 1586 return &bpf_ringbuf_output_proto; 1593 1587 case BPF_FUNC_ringbuf_reserve: ··· 2010 2008 return &bpf_get_stackid_proto_raw_tp; 2011 2009 case BPF_FUNC_get_stack: 2012 2010 return &bpf_get_stack_proto_raw_tp; 2011 + case BPF_FUNC_get_attach_cookie: 2012 + return &bpf_get_attach_cookie_proto_tracing; 2013 2013 default: 2014 2014 return bpf_tracing_func_proto(func_id, prog); 2015 2015 } ··· 2074 2070 case BPF_FUNC_get_func_arg_cnt: 2075 2071 return bpf_prog_has_trampoline(prog) ? &bpf_get_func_arg_cnt_proto : NULL; 2076 2072 case BPF_FUNC_get_attach_cookie: 2073 + if (prog->type == BPF_PROG_TYPE_TRACING && 2074 + prog->expected_attach_type == BPF_TRACE_RAW_TP) 2075 + return &bpf_get_attach_cookie_proto_tracing; 2077 2076 return bpf_prog_has_trampoline(prog) ? &bpf_get_attach_cookie_proto_tracing : NULL; 2078 2077 default: 2079 2078 fn = raw_tp_prog_func_proto(func_id, prog); ··· 2377 2370 } 2378 2371 2379 2372 static __always_inline 2380 - void __bpf_trace_run(struct bpf_prog *prog, u64 *args) 2373 + void __bpf_trace_run(struct bpf_raw_tp_link *link, u64 *args) 2381 2374 { 2375 + struct bpf_prog *prog = link->link.prog; 2376 + struct bpf_run_ctx *old_run_ctx; 2377 + struct bpf_trace_run_ctx run_ctx; 2378 + 2382 2379 cant_sleep(); 2383 2380 if (unlikely(this_cpu_inc_return(*(prog->active)) != 1)) { 2384 2381 bpf_prog_inc_misses_counter(prog); 2385 2382 goto out; 2386 2383 } 2384 + 2385 + run_ctx.bpf_cookie = link->cookie; 2386 + old_run_ctx = bpf_set_run_ctx(&run_ctx.run_ctx); 2387 + 2387 2388 rcu_read_lock(); 2388 2389 (void) bpf_prog_run(prog, args); 2389 2390 rcu_read_unlock(); 2391 + 2392 + bpf_reset_run_ctx(old_run_ctx); 2390 2393 out: 2391 2394 this_cpu_dec(*(prog->active)); 2392 2395 } ··· 2425 2408 #define __SEQ_0_11 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 2426 2409 2427 2410 #define BPF_TRACE_DEFN_x(x) \ 2428 - void bpf_trace_run##x(struct bpf_prog *prog, \ 2411 + void bpf_trace_run##x(struct bpf_raw_tp_link *link, \ 2429 2412 REPEAT(x, SARG, __DL_COM, __SEQ_0_11)) \ 2430 2413 { \ 2431 2414 u64 args[x]; \ 2432 2415 REPEAT(x, COPY, __DL_SEM, __SEQ_0_11); \ 2433 - __bpf_trace_run(prog, args); \ 2416 + __bpf_trace_run(link, args); \ 2434 2417 } \ 2435 2418 EXPORT_SYMBOL_GPL(bpf_trace_run##x) 2436 2419 BPF_TRACE_DEFN_x(1); ··· 2446 2429 BPF_TRACE_DEFN_x(11); 2447 2430 BPF_TRACE_DEFN_x(12); 2448 2431 2449 - static int __bpf_probe_register(struct bpf_raw_event_map *btp, struct bpf_prog *prog) 2432 + int bpf_probe_register(struct bpf_raw_event_map *btp, struct bpf_raw_tp_link *link) 2450 2433 { 2451 2434 struct tracepoint *tp = btp->tp; 2435 + struct bpf_prog *prog = link->link.prog; 2452 2436 2453 2437 /* 2454 2438 * check that program doesn't access arguments beyond what's ··· 2461 2443 if (prog->aux->max_tp_access > btp->writable_size) 2462 2444 return -EINVAL; 2463 2445 2464 - return tracepoint_probe_register_may_exist(tp, (void *)btp->bpf_func, 2465 - prog); 2446 + return tracepoint_probe_register_may_exist(tp, (void *)btp->bpf_func, link); 2466 2447 } 2467 2448 2468 - int bpf_probe_register(struct bpf_raw_event_map *btp, struct bpf_prog *prog) 2449 + int bpf_probe_unregister(struct bpf_raw_event_map *btp, struct bpf_raw_tp_link *link) 2469 2450 { 2470 - return __bpf_probe_register(btp, prog); 2471 - } 2472 - 2473 - int bpf_probe_unregister(struct bpf_raw_event_map *btp, struct bpf_prog *prog) 2474 - { 2475 - return tracepoint_probe_unregister(btp->tp, (void *)btp->bpf_func, prog); 2451 + return tracepoint_probe_unregister(btp->tp, (void *)btp->bpf_func, link); 2476 2452 } 2477 2453 2478 2454 int bpf_get_perf_event_info(const struct perf_event *event, u32 *prog_id,
+3 -1
net/bpf/bpf_dummy_struct_ops.c
··· 133 133 if (err < 0) 134 134 goto out; 135 135 136 - arch_protect_bpf_trampoline(image, PAGE_SIZE); 136 + err = arch_protect_bpf_trampoline(image, PAGE_SIZE); 137 + if (err) 138 + goto out; 137 139 prog_ret = dummy_ops_call_op(image, args); 138 140 139 141 err = dummy_ops_copy_args(args);
-2
net/core/filter.c
··· 8342 8342 return &bpf_event_output_data_proto; 8343 8343 case BPF_FUNC_get_current_uid_gid: 8344 8344 return &bpf_get_current_uid_gid_proto; 8345 - case BPF_FUNC_get_current_pid_tgid: 8346 - return &bpf_get_current_pid_tgid_proto; 8347 8345 case BPF_FUNC_sk_storage_get: 8348 8346 return &bpf_sk_storage_get_proto; 8349 8347 case BPF_FUNC_sk_storage_delete:
+6 -8
tools/bpf/bpftool/Makefile
··· 89 89 LDFLAGS += $(EXTRA_LDFLAGS) 90 90 endif 91 91 92 + HOST_CFLAGS := $(subst -I$(LIBBPF_INCLUDE),-I$(LIBBPF_BOOTSTRAP_INCLUDE),\ 93 + $(subst $(CLANG_CROSS_FLAGS),,$(CFLAGS))) 94 + HOST_LDFLAGS := $(LDFLAGS) 95 + 92 96 INSTALL ?= install 93 97 RM ?= rm -f 94 98 ··· 182 178 SRCS := $(filter-out jit_disasm.c,$(SRCS)) 183 179 endif 184 180 185 - HOST_CFLAGS = $(subst -I$(LIBBPF_INCLUDE),-I$(LIBBPF_BOOTSTRAP_INCLUDE),\ 186 - $(subst $(CLANG_CROSS_FLAGS),,$(CFLAGS))) 187 - 188 181 BPFTOOL_BOOTSTRAP := $(BOOTSTRAP_OUTPUT)bpftool 189 182 190 - BOOTSTRAP_OBJS = $(addprefix $(BOOTSTRAP_OUTPUT),main.o common.o json_writer.o gen.o btf.o xlated_dumper.o btf_dumper.o disasm.o) 183 + BOOTSTRAP_OBJS = $(addprefix $(BOOTSTRAP_OUTPUT),main.o common.o json_writer.o gen.o btf.o) 191 184 $(BOOTSTRAP_OBJS): $(LIBBPF_BOOTSTRAP) 192 185 193 186 OBJS = $(patsubst %.c,$(OUTPUT)%.o,$(SRCS)) $(OUTPUT)disasm.o ··· 232 231 233 232 CFLAGS += $(if $(BUILD_BPF_SKELS),,-DBPFTOOL_WITHOUT_SKELETONS) 234 233 235 - $(BOOTSTRAP_OUTPUT)disasm.o: $(srctree)/kernel/bpf/disasm.c 236 - $(QUIET_CC)$(HOSTCC) $(HOST_CFLAGS) -c -MMD $< -o $@ 237 - 238 234 $(OUTPUT)disasm.o: $(srctree)/kernel/bpf/disasm.c 239 235 $(QUIET_CC)$(CC) $(CFLAGS) -c -MMD $< -o $@ 240 236 241 237 $(BPFTOOL_BOOTSTRAP): $(BOOTSTRAP_OBJS) $(LIBBPF_BOOTSTRAP) 242 - $(QUIET_LINK)$(HOSTCC) $(HOST_CFLAGS) $(LDFLAGS) $(BOOTSTRAP_OBJS) $(LIBS_BOOTSTRAP) -o $@ 238 + $(QUIET_LINK)$(HOSTCC) $(HOST_CFLAGS) $(HOST_LDFLAGS) $(BOOTSTRAP_OBJS) $(LIBS_BOOTSTRAP) -o $@ 243 239 244 240 $(OUTPUT)bpftool: $(OBJS) $(LIBBPF) 245 241 $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) -o $@
+2 -1
tools/bpf/bpftool/gen.c
··· 1131 1131 continue; 1132 1132 codegen("\ 1133 1133 \n\ 1134 - obj->struct_ops.%1$s = bpf_map__initial_value(obj->maps.%1$s, NULL);\n\ 1134 + obj->struct_ops.%1$s = (typeof(obj->struct_ops.%1$s))\n\ 1135 + bpf_map__initial_value(obj->maps.%1$s, NULL);\n\ 1135 1136 \n\ 1136 1137 ", ident); 1137 1138 }
+12 -7
tools/bpf/bpftool/pids.c
··· 101 101 char buf[4096 / sizeof(*e) * sizeof(*e)]; 102 102 struct pid_iter_bpf *skel; 103 103 int err, ret, fd = -1, i; 104 - libbpf_print_fn_t default_print; 105 104 106 105 *map = hashmap__new(hash_fn_for_key_as_id, equal_fn_for_key_as_id, NULL); 107 106 if (IS_ERR(*map)) { ··· 117 118 118 119 skel->rodata->obj_type = type; 119 120 120 - /* we don't want output polluted with libbpf errors if bpf_iter is not 121 - * supported 122 - */ 123 - default_print = libbpf_set_print(libbpf_print_none); 124 - err = pid_iter_bpf__load(skel); 125 - libbpf_set_print(default_print); 121 + if (!verifier_logs) { 122 + libbpf_print_fn_t default_print; 123 + 124 + /* Unless debug information is on, we don't want the output to 125 + * be polluted with libbpf errors if bpf_iter is not supported. 126 + */ 127 + default_print = libbpf_set_print(libbpf_print_none); 128 + err = pid_iter_bpf__load(skel); 129 + libbpf_set_print(default_print); 130 + } else { 131 + err = pid_iter_bpf__load(skel); 132 + } 126 133 if (err) { 127 134 /* too bad, kernel doesn't support BPF iterators yet */ 128 135 err = 0;
+2 -2
tools/bpf/bpftool/skeleton/pid_iter.bpf.c
··· 102 102 BPF_LINK_TYPE_PERF_EVENT___local)) { 103 103 struct bpf_link *link = (struct bpf_link *) file->private_data; 104 104 105 - if (link->type == bpf_core_enum_value(enum bpf_link_type___local, 106 - BPF_LINK_TYPE_PERF_EVENT___local)) { 105 + if (BPF_CORE_READ(link, type) == bpf_core_enum_value(enum bpf_link_type___local, 106 + BPF_LINK_TYPE_PERF_EVENT___local)) { 107 107 e.has_bpf_cookie = true; 108 108 e.bpf_cookie = get_bpf_cookie(link); 109 109 }
+4
tools/include/linux/compiler.h
··· 58 58 #define noinline 59 59 #endif 60 60 61 + #ifndef __nocf_check 62 + #define __nocf_check __attribute__((nocf_check)) 63 + #endif 64 + 61 65 /* Are two types/vars the same type (ignoring qualifiers)? */ 62 66 #ifndef __same_type 63 67 # define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
+4 -2
tools/include/uapi/linux/bpf.h
··· 1662 1662 } query; 1663 1663 1664 1664 struct { /* anonymous struct used by BPF_RAW_TRACEPOINT_OPEN command */ 1665 - __u64 name; 1666 - __u32 prog_fd; 1665 + __u64 name; 1666 + __u32 prog_fd; 1667 + __u32 :32; 1668 + __aligned_u64 cookie; 1667 1669 } raw_tracepoint; 1668 1670 1669 1671 struct { /* anonymous struct for BPF_BTF_LOAD */
+14 -2
tools/lib/bpf/bpf.c
··· 785 785 if (!OPTS_ZEROED(opts, uprobe_multi)) 786 786 return libbpf_err(-EINVAL); 787 787 break; 788 + case BPF_TRACE_RAW_TP: 788 789 case BPF_TRACE_FENTRY: 789 790 case BPF_TRACE_FEXIT: 790 791 case BPF_MODIFY_RETURN: ··· 1174 1173 return bpf_obj_get_info_by_fd(link_fd, info, info_len); 1175 1174 } 1176 1175 1177 - int bpf_raw_tracepoint_open(const char *name, int prog_fd) 1176 + int bpf_raw_tracepoint_open_opts(int prog_fd, struct bpf_raw_tp_opts *opts) 1178 1177 { 1179 1178 const size_t attr_sz = offsetofend(union bpf_attr, raw_tracepoint); 1180 1179 union bpf_attr attr; 1181 1180 int fd; 1182 1181 1182 + if (!OPTS_VALID(opts, bpf_raw_tp_opts)) 1183 + return libbpf_err(-EINVAL); 1184 + 1183 1185 memset(&attr, 0, attr_sz); 1184 - attr.raw_tracepoint.name = ptr_to_u64(name); 1185 1186 attr.raw_tracepoint.prog_fd = prog_fd; 1187 + attr.raw_tracepoint.name = ptr_to_u64(OPTS_GET(opts, tp_name, NULL)); 1188 + attr.raw_tracepoint.cookie = OPTS_GET(opts, cookie, 0); 1186 1189 1187 1190 fd = sys_bpf_fd(BPF_RAW_TRACEPOINT_OPEN, &attr, attr_sz); 1188 1191 return libbpf_err_errno(fd); 1192 + } 1193 + 1194 + int bpf_raw_tracepoint_open(const char *name, int prog_fd) 1195 + { 1196 + LIBBPF_OPTS(bpf_raw_tp_opts, opts, .tp_name = name); 1197 + 1198 + return bpf_raw_tracepoint_open_opts(prog_fd, &opts); 1189 1199 } 1190 1200 1191 1201 int bpf_btf_load(const void *btf_data, size_t btf_size, struct bpf_btf_load_opts *opts)
+9
tools/lib/bpf/bpf.h
··· 617 617 __u32 query_flags, __u32 *attach_flags, 618 618 __u32 *prog_ids, __u32 *prog_cnt); 619 619 620 + struct bpf_raw_tp_opts { 621 + size_t sz; /* size of this struct for forward/backward compatibility */ 622 + const char *tp_name; 623 + __u64 cookie; 624 + size_t :0; 625 + }; 626 + #define bpf_raw_tp_opts__last_field cookie 627 + 628 + LIBBPF_API int bpf_raw_tracepoint_open_opts(int prog_fd, struct bpf_raw_tp_opts *opts); 620 629 LIBBPF_API int bpf_raw_tracepoint_open(const char *name, int prog_fd); 621 630 LIBBPF_API int bpf_task_fd_query(int pid, int fd, __u32 flags, char *buf, 622 631 __u32 *buf_len, __u32 *prog_id, __u32 *fd_type,
+92 -19
tools/lib/bpf/libbpf.c
··· 1132 1132 const char *mname; 1133 1133 1134 1134 mname = btf__name_by_offset(btf, member->name_off); 1135 + moff = member->offset / 8; 1136 + mdata = data + moff; 1137 + msize = btf__resolve_size(btf, member->type); 1138 + if (msize < 0) { 1139 + pr_warn("struct_ops init_kern %s: failed to resolve the size of member %s\n", 1140 + map->name, mname); 1141 + return msize; 1142 + } 1143 + 1135 1144 kern_member = find_member_by_name(kern_btf, kern_type, mname); 1136 1145 if (!kern_member) { 1146 + /* Skip all zeros or null fields if they are not 1147 + * presented in the kernel BTF. 1148 + */ 1149 + if (libbpf_is_mem_zeroed(mdata, msize)) { 1150 + pr_info("struct_ops %s: member %s not found in kernel, skipping it as it's set to zero\n", 1151 + map->name, mname); 1152 + continue; 1153 + } 1154 + 1137 1155 pr_warn("struct_ops init_kern %s: Cannot find member %s in kernel BTF\n", 1138 1156 map->name, mname); 1139 1157 return -ENOTSUP; ··· 1165 1147 return -ENOTSUP; 1166 1148 } 1167 1149 1168 - moff = member->offset / 8; 1169 1150 kern_moff = kern_member->offset / 8; 1170 - 1171 - mdata = data + moff; 1172 1151 kern_mdata = kern_data + kern_moff; 1173 1152 1174 1153 mtype = skip_mods_and_typedefs(btf, member->type, &mtype_id); ··· 1245 1230 continue; 1246 1231 } 1247 1232 1248 - msize = btf__resolve_size(btf, mtype_id); 1249 1233 kern_msize = btf__resolve_size(kern_btf, kern_mtype_id); 1250 - if (msize < 0 || kern_msize < 0 || msize != kern_msize) { 1234 + if (kern_msize < 0 || msize != kern_msize) { 1251 1235 pr_warn("struct_ops init_kern %s: Error in size of member %s: %zd != %zd(kernel)\n", 1252 1236 map->name, mname, (ssize_t)msize, 1253 1237 (ssize_t)kern_msize); ··· 7331 7317 char *cp, errmsg[STRERR_BUFSIZE]; 7332 7318 size_t log_buf_size = 0; 7333 7319 char *log_buf = NULL, *tmp; 7334 - int btf_fd, ret, err; 7335 7320 bool own_log_buf = true; 7336 7321 __u32 log_level = prog->log_level; 7322 + int ret, err; 7337 7323 7338 7324 if (prog->type == BPF_PROG_TYPE_UNSPEC) { 7339 7325 /* ··· 7357 7343 load_attr.prog_ifindex = prog->prog_ifindex; 7358 7344 7359 7345 /* specify func_info/line_info only if kernel supports them */ 7360 - btf_fd = btf__fd(obj->btf); 7361 - if (btf_fd >= 0 && kernel_supports(obj, FEAT_BTF_FUNC)) { 7362 - load_attr.prog_btf_fd = btf_fd; 7346 + if (obj->btf && btf__fd(obj->btf) >= 0 && kernel_supports(obj, FEAT_BTF_FUNC)) { 7347 + load_attr.prog_btf_fd = btf__fd(obj->btf); 7363 7348 load_attr.func_info = prog->func_info; 7364 7349 load_attr.func_info_rec_size = prog->func_info_rec_size; 7365 7350 load_attr.func_info_cnt = prog->func_info_cnt; ··· 8572 8559 return libbpf_err(-EINVAL); 8573 8560 } 8574 8561 8562 + if (map->fd < 0) { 8563 + pr_warn("map '%s': can't pin BPF map without FD (was it created?)\n", map->name); 8564 + return libbpf_err(-EINVAL); 8565 + } 8566 + 8575 8567 if (map->pin_path) { 8576 8568 if (path && strcmp(path, map->pin_path)) { 8577 8569 pr_warn("map '%s' already has pin path '%s' different from '%s'\n", ··· 9312 9294 SEC_DEF("sockops", SOCK_OPS, BPF_CGROUP_SOCK_OPS, SEC_ATTACHABLE_OPT), 9313 9295 SEC_DEF("sk_skb/stream_parser", SK_SKB, BPF_SK_SKB_STREAM_PARSER, SEC_ATTACHABLE_OPT), 9314 9296 SEC_DEF("sk_skb/stream_verdict",SK_SKB, BPF_SK_SKB_STREAM_VERDICT, SEC_ATTACHABLE_OPT), 9297 + SEC_DEF("sk_skb/verdict", SK_SKB, BPF_SK_SKB_VERDICT, SEC_ATTACHABLE_OPT), 9315 9298 SEC_DEF("sk_skb", SK_SKB, 0, SEC_NONE), 9316 9299 SEC_DEF("sk_msg", SK_MSG, BPF_SK_MSG_VERDICT, SEC_ATTACHABLE_OPT), 9317 9300 SEC_DEF("lirc_mode2", LIRC_MODE2, BPF_LIRC_MODE2, SEC_ATTACHABLE_OPT), ··· 10322 10303 return -EINVAL; 10323 10304 } 10324 10305 10306 + if (map->fd < 0) { 10307 + pr_warn("map '%s': can't use BPF map without FD (was it created?)\n", map->name); 10308 + return -EINVAL; 10309 + } 10310 + 10325 10311 if (!check_value_sz) 10326 10312 return 0; 10327 10313 ··· 10439 10415 int bpf_link__update_program(struct bpf_link *link, struct bpf_program *prog) 10440 10416 { 10441 10417 int ret; 10418 + int prog_fd = bpf_program__fd(prog); 10442 10419 10443 - ret = bpf_link_update(bpf_link__fd(link), bpf_program__fd(prog), NULL); 10420 + if (prog_fd < 0) { 10421 + pr_warn("prog '%s': can't use BPF program without FD (was it loaded?)\n", 10422 + prog->name); 10423 + return libbpf_err(-EINVAL); 10424 + } 10425 + 10426 + ret = bpf_link_update(bpf_link__fd(link), prog_fd, NULL); 10444 10427 return libbpf_err_errno(ret); 10445 10428 } 10446 10429 ··· 10641 10610 } 10642 10611 prog_fd = bpf_program__fd(prog); 10643 10612 if (prog_fd < 0) { 10644 - pr_warn("prog '%s': can't attach BPF program w/o FD (did you load it?)\n", 10613 + pr_warn("prog '%s': can't attach BPF program without FD (was it loaded?)\n", 10645 10614 prog->name); 10646 10615 return libbpf_err_ptr(-EINVAL); 10647 10616 } ··· 11365 11334 if (!OPTS_VALID(opts, bpf_kprobe_multi_opts)) 11366 11335 return libbpf_err_ptr(-EINVAL); 11367 11336 11337 + prog_fd = bpf_program__fd(prog); 11338 + if (prog_fd < 0) { 11339 + pr_warn("prog '%s': can't attach BPF program without FD (was it loaded?)\n", 11340 + prog->name); 11341 + return libbpf_err_ptr(-EINVAL); 11342 + } 11343 + 11368 11344 syms = OPTS_GET(opts, syms, false); 11369 11345 addrs = OPTS_GET(opts, addrs, false); 11370 11346 cnt = OPTS_GET(opts, cnt, false); ··· 11412 11374 } 11413 11375 link->detach = &bpf_link__detach_fd; 11414 11376 11415 - prog_fd = bpf_program__fd(prog); 11416 11377 link_fd = bpf_link_create(prog_fd, 0, BPF_TRACE_KPROBE_MULTI, &lopts); 11417 11378 if (link_fd < 0) { 11418 11379 err = -errno; ··· 11794 11757 if (!OPTS_VALID(opts, bpf_uprobe_multi_opts)) 11795 11758 return libbpf_err_ptr(-EINVAL); 11796 11759 11760 + prog_fd = bpf_program__fd(prog); 11761 + if (prog_fd < 0) { 11762 + pr_warn("prog '%s': can't attach BPF program without FD (was it loaded?)\n", 11763 + prog->name); 11764 + return libbpf_err_ptr(-EINVAL); 11765 + } 11766 + 11797 11767 syms = OPTS_GET(opts, syms, NULL); 11798 11768 offsets = OPTS_GET(opts, offsets, NULL); 11799 11769 ref_ctr_offsets = OPTS_GET(opts, ref_ctr_offsets, NULL); ··· 11876 11832 } 11877 11833 link->detach = &bpf_link__detach_fd; 11878 11834 11879 - prog_fd = bpf_program__fd(prog); 11880 11835 link_fd = bpf_link_create(prog_fd, 0, BPF_TRACE_UPROBE_MULTI, &lopts); 11881 11836 if (link_fd < 0) { 11882 11837 err = -errno; ··· 12119 12076 return libbpf_err_ptr(-EINVAL); 12120 12077 12121 12078 if (bpf_program__fd(prog) < 0) { 12122 - pr_warn("prog '%s': can't attach BPF program w/o FD (did you load it?)\n", 12079 + pr_warn("prog '%s': can't attach BPF program without FD (was it loaded?)\n", 12123 12080 prog->name); 12124 12081 return libbpf_err_ptr(-EINVAL); 12125 12082 } ··· 12310 12267 return libbpf_get_error(*link); 12311 12268 } 12312 12269 12313 - struct bpf_link *bpf_program__attach_raw_tracepoint(const struct bpf_program *prog, 12314 - const char *tp_name) 12270 + struct bpf_link * 12271 + bpf_program__attach_raw_tracepoint_opts(const struct bpf_program *prog, 12272 + const char *tp_name, 12273 + struct bpf_raw_tracepoint_opts *opts) 12315 12274 { 12275 + LIBBPF_OPTS(bpf_raw_tp_opts, raw_opts); 12316 12276 char errmsg[STRERR_BUFSIZE]; 12317 12277 struct bpf_link *link; 12318 12278 int prog_fd, pfd; 12279 + 12280 + if (!OPTS_VALID(opts, bpf_raw_tracepoint_opts)) 12281 + return libbpf_err_ptr(-EINVAL); 12319 12282 12320 12283 prog_fd = bpf_program__fd(prog); 12321 12284 if (prog_fd < 0) { ··· 12334 12285 return libbpf_err_ptr(-ENOMEM); 12335 12286 link->detach = &bpf_link__detach_fd; 12336 12287 12337 - pfd = bpf_raw_tracepoint_open(tp_name, prog_fd); 12288 + raw_opts.tp_name = tp_name; 12289 + raw_opts.cookie = OPTS_GET(opts, cookie, 0); 12290 + pfd = bpf_raw_tracepoint_open_opts(prog_fd, &raw_opts); 12338 12291 if (pfd < 0) { 12339 12292 pfd = -errno; 12340 12293 free(link); ··· 12346 12295 } 12347 12296 link->fd = pfd; 12348 12297 return link; 12298 + } 12299 + 12300 + struct bpf_link *bpf_program__attach_raw_tracepoint(const struct bpf_program *prog, 12301 + const char *tp_name) 12302 + { 12303 + return bpf_program__attach_raw_tracepoint_opts(prog, tp_name, NULL); 12349 12304 } 12350 12305 12351 12306 static int attach_raw_tp(const struct bpf_program *prog, long cookie, struct bpf_link **link) ··· 12715 12658 if (!prog->sec_def || !prog->sec_def->prog_attach_fn) 12716 12659 return libbpf_err_ptr(-EOPNOTSUPP); 12717 12660 12661 + if (bpf_program__fd(prog) < 0) { 12662 + pr_warn("prog '%s': can't attach BPF program without FD (was it loaded?)\n", 12663 + prog->name); 12664 + return libbpf_err_ptr(-EINVAL); 12665 + } 12666 + 12718 12667 err = prog->sec_def->prog_attach_fn(prog, prog->sec_def->cookie, &link); 12719 12668 if (err) 12720 12669 return libbpf_err_ptr(err); ··· 12761 12698 __u32 zero = 0; 12762 12699 int err, fd; 12763 12700 12764 - if (!bpf_map__is_struct_ops(map) || map->fd == -1) 12701 + if (!bpf_map__is_struct_ops(map)) 12765 12702 return libbpf_err_ptr(-EINVAL); 12703 + 12704 + if (map->fd < 0) { 12705 + pr_warn("map '%s': can't attach BPF map without FD (was it created?)\n", map->name); 12706 + return libbpf_err_ptr(-EINVAL); 12707 + } 12766 12708 12767 12709 link = calloc(1, sizeof(*link)); 12768 12710 if (!link) ··· 12815 12747 __u32 zero = 0; 12816 12748 int err; 12817 12749 12818 - if (!bpf_map__is_struct_ops(map) || !map_is_created(map)) 12750 + if (!bpf_map__is_struct_ops(map)) 12819 12751 return -EINVAL; 12752 + 12753 + if (map->fd < 0) { 12754 + pr_warn("map '%s': can't use BPF map without FD (was it created?)\n", map->name); 12755 + return -EINVAL; 12756 + } 12820 12757 12821 12758 st_ops_link = container_of(link, struct bpf_link_struct_ops, link); 12822 12759 /* Ensure the type of a link is correct */
+11
tools/lib/bpf/libbpf.h
··· 760 760 const char *tp_name, 761 761 const struct bpf_tracepoint_opts *opts); 762 762 763 + struct bpf_raw_tracepoint_opts { 764 + size_t sz; /* size of this struct for forward/backward compatibility */ 765 + __u64 cookie; 766 + size_t :0; 767 + }; 768 + #define bpf_raw_tracepoint_opts__last_field cookie 769 + 763 770 LIBBPF_API struct bpf_link * 764 771 bpf_program__attach_raw_tracepoint(const struct bpf_program *prog, 765 772 const char *tp_name); 773 + LIBBPF_API struct bpf_link * 774 + bpf_program__attach_raw_tracepoint_opts(const struct bpf_program *prog, 775 + const char *tp_name, 776 + struct bpf_raw_tracepoint_opts *opts); 766 777 767 778 struct bpf_trace_opts { 768 779 /* size of this struct, for forward/backward compatibility */
+2
tools/lib/bpf/libbpf.map
··· 410 410 411 411 LIBBPF_1.4.0 { 412 412 global: 413 + bpf_program__attach_raw_tracepoint_opts; 414 + bpf_raw_tracepoint_open_opts; 413 415 bpf_token_create; 414 416 btf__new_split; 415 417 btf_ext__raw_data;
+1 -1
tools/testing/selftests/bpf/benchs/bench_local_storage_create.c
··· 186 186 187 187 for (i = 0; i < batch_sz; i++) { 188 188 if (!pthd_results[i]) 189 - pthread_join(pthds[i], NULL);; 189 + pthread_join(pthds[i], NULL); 190 190 } 191 191 } 192 192
+40 -8
tools/testing/selftests/bpf/benchs/bench_trigger.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 /* Copyright (c) 2020 Facebook */ 3 + #define _GNU_SOURCE 4 + #include <unistd.h> 3 5 #include "bench.h" 4 6 #include "trigger_bench.skel.h" 5 7 #include "trace_helpers.h" 8 + 9 + /* adjust slot shift in inc_hits() if changing */ 10 + #define MAX_BUCKETS 256 11 + 12 + #pragma GCC diagnostic ignored "-Wattributes" 6 13 7 14 /* BPF triggering benchmarks */ 8 15 static struct trigger_ctx { 9 16 struct trigger_bench *skel; 10 17 } ctx; 11 18 12 - static struct counter base_hits; 19 + static struct counter base_hits[MAX_BUCKETS]; 20 + 21 + static __always_inline void inc_counter(struct counter *counters) 22 + { 23 + static __thread int tid = 0; 24 + unsigned slot; 25 + 26 + if (unlikely(tid == 0)) 27 + tid = syscall(SYS_gettid); 28 + 29 + /* multiplicative hashing, it's fast */ 30 + slot = 2654435769U * tid; 31 + slot >>= 24; 32 + 33 + atomic_inc(&base_hits[slot].value); /* use highest byte as an index */ 34 + } 35 + 36 + static long sum_and_reset_counters(struct counter *counters) 37 + { 38 + int i; 39 + long sum = 0; 40 + 41 + for (i = 0; i < MAX_BUCKETS; i++) 42 + sum += atomic_swap(&counters[i].value, 0); 43 + return sum; 44 + } 13 45 14 46 static void trigger_validate(void) 15 47 { ··· 55 23 { 56 24 while (true) { 57 25 (void)syscall(__NR_getpgid); 58 - atomic_inc(&base_hits.value); 26 + inc_counter(base_hits); 59 27 } 60 28 return NULL; 61 29 } 62 30 63 31 static void trigger_base_measure(struct bench_res *res) 64 32 { 65 - res->hits = atomic_swap(&base_hits.value, 0); 33 + res->hits = sum_and_reset_counters(base_hits); 66 34 } 67 35 68 36 static void *trigger_producer(void *input) ··· 74 42 75 43 static void trigger_measure(struct bench_res *res) 76 44 { 77 - res->hits = atomic_swap(&ctx.skel->bss->hits, 0); 45 + res->hits = sum_and_reset_counters(ctx.skel->bss->hits); 78 46 } 79 47 80 48 static void setup_ctx(void) ··· 169 137 * GCC doesn't generate stack setup preample for these functions due to them 170 138 * having no input arguments and doing nothing in the body. 171 139 */ 172 - __weak void uprobe_target_nop(void) 140 + __nocf_check __weak void uprobe_target_nop(void) 173 141 { 174 142 asm volatile ("nop"); 175 143 } ··· 178 146 { 179 147 } 180 148 181 - __weak int uprobe_target_push(void) 149 + __nocf_check __weak int uprobe_target_push(void) 182 150 { 183 151 /* overhead of function call is negligible compared to uprobe 184 152 * triggering, so this shouldn't affect benchmark results much ··· 187 155 return 1; 188 156 } 189 157 190 - __weak void uprobe_target_ret(void) 158 + __nocf_check __weak void uprobe_target_ret(void) 191 159 { 192 160 asm volatile (""); 193 161 } ··· 196 164 { 197 165 while (true) { 198 166 uprobe_target_nop(); 199 - atomic_inc(&base_hits.value); 167 + inc_counter(base_hits); 200 168 } 201 169 return NULL; 202 170 }
+113 -1
tools/testing/selftests/bpf/prog_tests/bpf_cookie.c
··· 573 573 close(lsm_fd); 574 574 } 575 575 576 + static void tp_btf_subtest(struct test_bpf_cookie *skel) 577 + { 578 + __u64 cookie; 579 + int prog_fd, link_fd = -1; 580 + struct bpf_link *link = NULL; 581 + LIBBPF_OPTS(bpf_link_create_opts, link_opts); 582 + LIBBPF_OPTS(bpf_raw_tp_opts, raw_tp_opts); 583 + LIBBPF_OPTS(bpf_trace_opts, trace_opts); 584 + 585 + /* There are three different ways to attach tp_btf (BTF-aware raw 586 + * tracepoint) programs. Let's test all of them. 587 + */ 588 + prog_fd = bpf_program__fd(skel->progs.handle_tp_btf); 589 + 590 + /* low-level BPF_RAW_TRACEPOINT_OPEN command wrapper */ 591 + skel->bss->tp_btf_res = 0; 592 + 593 + raw_tp_opts.cookie = cookie = 0x11000000000000L; 594 + link_fd = bpf_raw_tracepoint_open_opts(prog_fd, &raw_tp_opts); 595 + if (!ASSERT_GE(link_fd, 0, "bpf_raw_tracepoint_open_opts")) 596 + goto cleanup; 597 + 598 + usleep(1); /* trigger */ 599 + close(link_fd); /* detach */ 600 + link_fd = -1; 601 + 602 + ASSERT_EQ(skel->bss->tp_btf_res, cookie, "raw_tp_open_res"); 603 + 604 + /* low-level generic bpf_link_create() API */ 605 + skel->bss->tp_btf_res = 0; 606 + 607 + link_opts.tracing.cookie = cookie = 0x22000000000000L; 608 + link_fd = bpf_link_create(prog_fd, 0, BPF_TRACE_RAW_TP, &link_opts); 609 + if (!ASSERT_GE(link_fd, 0, "bpf_link_create")) 610 + goto cleanup; 611 + 612 + usleep(1); /* trigger */ 613 + close(link_fd); /* detach */ 614 + link_fd = -1; 615 + 616 + ASSERT_EQ(skel->bss->tp_btf_res, cookie, "link_create_res"); 617 + 618 + /* high-level bpf_link-based bpf_program__attach_trace_opts() API */ 619 + skel->bss->tp_btf_res = 0; 620 + 621 + trace_opts.cookie = cookie = 0x33000000000000L; 622 + link = bpf_program__attach_trace_opts(skel->progs.handle_tp_btf, &trace_opts); 623 + if (!ASSERT_OK_PTR(link, "attach_trace_opts")) 624 + goto cleanup; 625 + 626 + usleep(1); /* trigger */ 627 + bpf_link__destroy(link); /* detach */ 628 + link = NULL; 629 + 630 + ASSERT_EQ(skel->bss->tp_btf_res, cookie, "attach_trace_opts_res"); 631 + 632 + cleanup: 633 + if (link_fd >= 0) 634 + close(link_fd); 635 + bpf_link__destroy(link); 636 + } 637 + 638 + static void raw_tp_subtest(struct test_bpf_cookie *skel) 639 + { 640 + __u64 cookie; 641 + int prog_fd, link_fd = -1; 642 + struct bpf_link *link = NULL; 643 + LIBBPF_OPTS(bpf_raw_tp_opts, raw_tp_opts); 644 + LIBBPF_OPTS(bpf_raw_tracepoint_opts, opts); 645 + 646 + /* There are two different ways to attach raw_tp programs */ 647 + prog_fd = bpf_program__fd(skel->progs.handle_raw_tp); 648 + 649 + /* low-level BPF_RAW_TRACEPOINT_OPEN command wrapper */ 650 + skel->bss->raw_tp_res = 0; 651 + 652 + raw_tp_opts.tp_name = "sys_enter"; 653 + raw_tp_opts.cookie = cookie = 0x55000000000000L; 654 + link_fd = bpf_raw_tracepoint_open_opts(prog_fd, &raw_tp_opts); 655 + if (!ASSERT_GE(link_fd, 0, "bpf_raw_tracepoint_open_opts")) 656 + goto cleanup; 657 + 658 + usleep(1); /* trigger */ 659 + close(link_fd); /* detach */ 660 + link_fd = -1; 661 + 662 + ASSERT_EQ(skel->bss->raw_tp_res, cookie, "raw_tp_open_res"); 663 + 664 + /* high-level bpf_link-based bpf_program__attach_raw_tracepoint_opts() API */ 665 + skel->bss->raw_tp_res = 0; 666 + 667 + opts.cookie = cookie = 0x66000000000000L; 668 + link = bpf_program__attach_raw_tracepoint_opts(skel->progs.handle_raw_tp, 669 + "sys_enter", &opts); 670 + if (!ASSERT_OK_PTR(link, "attach_raw_tp_opts")) 671 + goto cleanup; 672 + 673 + usleep(1); /* trigger */ 674 + bpf_link__destroy(link); /* detach */ 675 + link = NULL; 676 + 677 + ASSERT_EQ(skel->bss->raw_tp_res, cookie, "attach_raw_tp_opts_res"); 678 + 679 + cleanup: 680 + if (link_fd >= 0) 681 + close(link_fd); 682 + bpf_link__destroy(link); 683 + } 684 + 576 685 void test_bpf_cookie(void) 577 686 { 578 687 struct test_bpf_cookie *skel; ··· 710 601 tracing_subtest(skel); 711 602 if (test__start_subtest("lsm")) 712 603 lsm_subtest(skel); 713 - 604 + if (test__start_subtest("tp_btf")) 605 + tp_btf_subtest(skel); 606 + if (test__start_subtest("raw_tp")) 607 + raw_tp_subtest(skel); 714 608 test_bpf_cookie__destroy(skel); 715 609 }
+1 -12
tools/testing/selftests/bpf/prog_tests/bpf_tcp_ca.c
··· 89 89 90 90 WRITE_ONCE(stop, 0); 91 91 92 - lfd = socket(AF_INET6, SOCK_STREAM, 0); 92 + lfd = start_server(AF_INET6, SOCK_STREAM, NULL, 0, 0); 93 93 if (!ASSERT_NEQ(lfd, -1, "socket")) 94 94 return; 95 95 ··· 103 103 settimeo(lfd, 0) || settimeo(fd, 0)) 104 104 goto done; 105 105 106 - /* bind, listen and start server thread to accept */ 107 - sa6.sin6_family = AF_INET6; 108 - sa6.sin6_addr = in6addr_loopback; 109 - err = bind(lfd, (struct sockaddr *)&sa6, addrlen); 110 - if (!ASSERT_NEQ(err, -1, "bind")) 111 - goto done; 112 - 113 106 err = getsockname(lfd, (struct sockaddr *)&sa6, &addrlen); 114 107 if (!ASSERT_NEQ(err, -1, "getsockname")) 115 - goto done; 116 - 117 - err = listen(lfd, 1); 118 - if (!ASSERT_NEQ(err, -1, "listen")) 119 108 goto done; 120 109 121 110 if (sk_stg_map) {
+1 -25
tools/testing/selftests/bpf/prog_tests/btf_map_in_map.c
··· 25 25 int map1_fd, map2_fd, map3_fd, map4_fd, map5_fd, map1_id, map2_id; 26 26 int outer_arr_fd, outer_hash_fd, outer_arr_dyn_fd; 27 27 struct test_btf_map_in_map *skel; 28 - int err, key = 0, val, i, fd; 28 + int err, key = 0, val, i; 29 29 30 30 skel = test_btf_map_in_map__open_and_load(); 31 31 if (CHECK(!skel, "skel_open", "failed to open&load skeleton\n")) ··· 101 101 map2_id = bpf_map_id(skel->maps.inner_map2); 102 102 CHECK(map1_id == 0, "map1_id", "failed to get ID 1\n"); 103 103 CHECK(map2_id == 0, "map2_id", "failed to get ID 2\n"); 104 - 105 - test_btf_map_in_map__destroy(skel); 106 - skel = NULL; 107 - 108 - /* we need to either wait for or force synchronize_rcu(), before 109 - * checking for "still exists" condition, otherwise map could still be 110 - * resolvable by ID, causing false positives. 111 - * 112 - * Older kernels (5.8 and earlier) freed map only after two 113 - * synchronize_rcu()s, so trigger two, to be entirely sure. 114 - */ 115 - CHECK(kern_sync_rcu(), "sync_rcu", "failed\n"); 116 - CHECK(kern_sync_rcu(), "sync_rcu", "failed\n"); 117 - 118 - fd = bpf_map_get_fd_by_id(map1_id); 119 - if (CHECK(fd >= 0, "map1_leak", "inner_map1 leaked!\n")) { 120 - close(fd); 121 - goto cleanup; 122 - } 123 - fd = bpf_map_get_fd_by_id(map2_id); 124 - if (CHECK(fd >= 0, "map2_leak", "inner_map2 leaked!\n")) { 125 - close(fd); 126 - goto cleanup; 127 - } 128 104 129 105 cleanup: 130 106 test_btf_map_in_map__destroy(skel);
+184 -32
tools/testing/selftests/bpf/prog_tests/ns_current_pid_tgid.c
··· 12 12 #include <sys/wait.h> 13 13 #include <sys/mount.h> 14 14 #include <sys/fcntl.h> 15 + #include "network_helpers.h" 15 16 16 17 #define STACK_SIZE (1024 * 1024) 17 18 static char child_stack[STACK_SIZE]; 18 19 19 - static int test_current_pid_tgid(void *args) 20 + static int get_pid_tgid(pid_t *pid, pid_t *tgid, 21 + struct test_ns_current_pid_tgid__bss *bss) 20 22 { 21 - struct test_ns_current_pid_tgid__bss *bss; 22 - struct test_ns_current_pid_tgid *skel; 23 - int err = -1, duration = 0; 24 - pid_t tgid, pid; 25 23 struct stat st; 24 + int err; 26 25 27 - skel = test_ns_current_pid_tgid__open_and_load(); 28 - if (CHECK(!skel, "skel_open_load", "failed to load skeleton\n")) 29 - goto cleanup; 30 - 31 - pid = syscall(SYS_gettid); 32 - tgid = getpid(); 26 + *pid = syscall(SYS_gettid); 27 + *tgid = getpid(); 33 28 34 29 err = stat("/proc/self/ns/pid", &st); 35 - if (CHECK(err, "stat", "failed /proc/self/ns/pid: %d\n", err)) 36 - goto cleanup; 30 + if (!ASSERT_OK(err, "stat /proc/self/ns/pid")) 31 + return err; 37 32 38 - bss = skel->bss; 39 33 bss->dev = st.st_dev; 40 34 bss->ino = st.st_ino; 41 35 bss->user_pid = 0; 42 36 bss->user_tgid = 0; 37 + return 0; 38 + } 39 + 40 + static int test_current_pid_tgid_tp(void *args) 41 + { 42 + struct test_ns_current_pid_tgid__bss *bss; 43 + struct test_ns_current_pid_tgid *skel; 44 + int ret = -1, err; 45 + pid_t tgid, pid; 46 + 47 + skel = test_ns_current_pid_tgid__open(); 48 + if (!ASSERT_OK_PTR(skel, "test_ns_current_pid_tgid__open")) 49 + return ret; 50 + 51 + bpf_program__set_autoload(skel->progs.tp_handler, true); 52 + 53 + err = test_ns_current_pid_tgid__load(skel); 54 + if (!ASSERT_OK(err, "test_ns_current_pid_tgid__load")) 55 + goto cleanup; 56 + 57 + bss = skel->bss; 58 + if (get_pid_tgid(&pid, &tgid, bss)) 59 + goto cleanup; 43 60 44 61 err = test_ns_current_pid_tgid__attach(skel); 45 - if (CHECK(err, "skel_attach", "skeleton attach failed: %d\n", err)) 62 + if (!ASSERT_OK(err, "test_ns_current_pid_tgid__attach")) 46 63 goto cleanup; 47 64 48 65 /* trigger tracepoint */ 49 66 usleep(1); 50 - ASSERT_EQ(bss->user_pid, pid, "pid"); 51 - ASSERT_EQ(bss->user_tgid, tgid, "tgid"); 52 - err = 0; 67 + if (!ASSERT_EQ(bss->user_pid, pid, "pid")) 68 + goto cleanup; 69 + if (!ASSERT_EQ(bss->user_tgid, tgid, "tgid")) 70 + goto cleanup; 71 + ret = 0; 53 72 54 73 cleanup: 55 - test_ns_current_pid_tgid__destroy(skel); 56 - 57 - return err; 74 + test_ns_current_pid_tgid__destroy(skel); 75 + return ret; 58 76 } 59 77 60 - static void test_ns_current_pid_tgid_new_ns(void) 78 + static int test_current_pid_tgid_cgrp(void *args) 61 79 { 62 - int wstatus, duration = 0; 80 + struct test_ns_current_pid_tgid__bss *bss; 81 + struct test_ns_current_pid_tgid *skel; 82 + int server_fd = -1, ret = -1, err; 83 + int cgroup_fd = *(int *)args; 84 + pid_t tgid, pid; 85 + 86 + skel = test_ns_current_pid_tgid__open(); 87 + if (!ASSERT_OK_PTR(skel, "test_ns_current_pid_tgid__open")) 88 + return ret; 89 + 90 + bpf_program__set_autoload(skel->progs.cgroup_bind4, true); 91 + 92 + err = test_ns_current_pid_tgid__load(skel); 93 + if (!ASSERT_OK(err, "test_ns_current_pid_tgid__load")) 94 + goto cleanup; 95 + 96 + bss = skel->bss; 97 + if (get_pid_tgid(&pid, &tgid, bss)) 98 + goto cleanup; 99 + 100 + skel->links.cgroup_bind4 = bpf_program__attach_cgroup( 101 + skel->progs.cgroup_bind4, cgroup_fd); 102 + if (!ASSERT_OK_PTR(skel->links.cgroup_bind4, "bpf_program__attach_cgroup")) 103 + goto cleanup; 104 + 105 + server_fd = start_server(AF_INET, SOCK_STREAM, NULL, 0, 0); 106 + if (!ASSERT_GE(server_fd, 0, "start_server")) 107 + goto cleanup; 108 + 109 + if (!ASSERT_EQ(bss->user_pid, pid, "pid")) 110 + goto cleanup; 111 + if (!ASSERT_EQ(bss->user_tgid, tgid, "tgid")) 112 + goto cleanup; 113 + ret = 0; 114 + 115 + cleanup: 116 + if (server_fd >= 0) 117 + close(server_fd); 118 + test_ns_current_pid_tgid__destroy(skel); 119 + return ret; 120 + } 121 + 122 + static int test_current_pid_tgid_sk_msg(void *args) 123 + { 124 + int verdict, map, server_fd = -1, client_fd = -1; 125 + struct test_ns_current_pid_tgid__bss *bss; 126 + static const char send_msg[] = "message"; 127 + struct test_ns_current_pid_tgid *skel; 128 + int ret = -1, err, key = 0; 129 + pid_t tgid, pid; 130 + 131 + skel = test_ns_current_pid_tgid__open(); 132 + if (!ASSERT_OK_PTR(skel, "test_ns_current_pid_tgid__open")) 133 + return ret; 134 + 135 + bpf_program__set_autoload(skel->progs.sk_msg, true); 136 + 137 + err = test_ns_current_pid_tgid__load(skel); 138 + if (!ASSERT_OK(err, "test_ns_current_pid_tgid__load")) 139 + goto cleanup; 140 + 141 + bss = skel->bss; 142 + if (get_pid_tgid(&pid, &tgid, skel->bss)) 143 + goto cleanup; 144 + 145 + verdict = bpf_program__fd(skel->progs.sk_msg); 146 + map = bpf_map__fd(skel->maps.sock_map); 147 + err = bpf_prog_attach(verdict, map, BPF_SK_MSG_VERDICT, 0); 148 + if (!ASSERT_OK(err, "prog_attach")) 149 + goto cleanup; 150 + 151 + server_fd = start_server(AF_INET6, SOCK_STREAM, "::1", 0, 0); 152 + if (!ASSERT_GE(server_fd, 0, "start_server")) 153 + goto cleanup; 154 + 155 + client_fd = connect_to_fd(server_fd, 0); 156 + if (!ASSERT_GE(client_fd, 0, "connect_to_fd")) 157 + goto cleanup; 158 + 159 + err = bpf_map_update_elem(map, &key, &client_fd, BPF_ANY); 160 + if (!ASSERT_OK(err, "bpf_map_update_elem")) 161 + goto cleanup; 162 + 163 + err = send(client_fd, send_msg, sizeof(send_msg), 0); 164 + if (!ASSERT_EQ(err, sizeof(send_msg), "send(msg)")) 165 + goto cleanup; 166 + 167 + if (!ASSERT_EQ(bss->user_pid, pid, "pid")) 168 + goto cleanup; 169 + if (!ASSERT_EQ(bss->user_tgid, tgid, "tgid")) 170 + goto cleanup; 171 + ret = 0; 172 + 173 + cleanup: 174 + if (server_fd >= 0) 175 + close(server_fd); 176 + if (client_fd >= 0) 177 + close(client_fd); 178 + test_ns_current_pid_tgid__destroy(skel); 179 + return ret; 180 + } 181 + 182 + static void test_ns_current_pid_tgid_new_ns(int (*fn)(void *), void *arg) 183 + { 184 + int wstatus; 63 185 pid_t cpid; 64 186 65 187 /* Create a process in a new namespace, this process 66 188 * will be the init process of this new namespace hence will be pid 1. 67 189 */ 68 - cpid = clone(test_current_pid_tgid, child_stack + STACK_SIZE, 69 - CLONE_NEWPID | SIGCHLD, NULL); 190 + cpid = clone(fn, child_stack + STACK_SIZE, 191 + CLONE_NEWPID | SIGCHLD, arg); 70 192 71 - if (CHECK(cpid == -1, "clone", "%s\n", strerror(errno))) 193 + if (!ASSERT_NEQ(cpid, -1, "clone")) 72 194 return; 73 195 74 - if (CHECK(waitpid(cpid, &wstatus, 0) == -1, "waitpid", "%s\n", strerror(errno))) 196 + if (!ASSERT_NEQ(waitpid(cpid, &wstatus, 0), -1, "waitpid")) 75 197 return; 76 198 77 - if (CHECK(WEXITSTATUS(wstatus) != 0, "newns_pidtgid", "failed")) 199 + if (!ASSERT_OK(WEXITSTATUS(wstatus), "newns_pidtgid")) 78 200 return; 201 + } 202 + 203 + static void test_in_netns(int (*fn)(void *), void *arg) 204 + { 205 + struct nstoken *nstoken = NULL; 206 + 207 + SYS(cleanup, "ip netns add ns_current_pid_tgid"); 208 + SYS(cleanup, "ip -net ns_current_pid_tgid link set dev lo up"); 209 + 210 + nstoken = open_netns("ns_current_pid_tgid"); 211 + if (!ASSERT_OK_PTR(nstoken, "open_netns")) 212 + goto cleanup; 213 + 214 + test_ns_current_pid_tgid_new_ns(fn, arg); 215 + 216 + cleanup: 217 + if (nstoken) 218 + close_netns(nstoken); 219 + SYS_NOFAIL("ip netns del ns_current_pid_tgid"); 79 220 } 80 221 81 222 /* TODO: use a different tracepoint */ 82 223 void serial_test_ns_current_pid_tgid(void) 83 224 { 84 - if (test__start_subtest("ns_current_pid_tgid_root_ns")) 85 - test_current_pid_tgid(NULL); 86 - if (test__start_subtest("ns_current_pid_tgid_new_ns")) 87 - test_ns_current_pid_tgid_new_ns(); 225 + if (test__start_subtest("root_ns_tp")) 226 + test_current_pid_tgid_tp(NULL); 227 + if (test__start_subtest("new_ns_tp")) 228 + test_ns_current_pid_tgid_new_ns(test_current_pid_tgid_tp, NULL); 229 + if (test__start_subtest("new_ns_cgrp")) { 230 + int cgroup_fd = -1; 231 + 232 + cgroup_fd = test__join_cgroup("/sock_addr"); 233 + if (ASSERT_GE(cgroup_fd, 0, "join_cgroup")) { 234 + test_in_netns(test_current_pid_tgid_cgrp, &cgroup_fd); 235 + close(cgroup_fd); 236 + } 237 + } 238 + if (test__start_subtest("new_ns_sk_msg")) 239 + test_in_netns(test_current_pid_tgid_sk_msg, NULL); 88 240 }
+47
tools/testing/selftests/bpf/prog_tests/test_struct_ops_module.c
··· 93 93 struct_ops_module__destroy(skel); 94 94 } 95 95 96 + static void test_struct_ops_not_zeroed(void) 97 + { 98 + struct struct_ops_module *skel; 99 + int err; 100 + 101 + /* zeroed is 0, and zeroed_op is null */ 102 + skel = struct_ops_module__open(); 103 + if (!ASSERT_OK_PTR(skel, "struct_ops_module_open")) 104 + return; 105 + 106 + err = struct_ops_module__load(skel); 107 + ASSERT_OK(err, "struct_ops_module_load"); 108 + 109 + struct_ops_module__destroy(skel); 110 + 111 + /* zeroed is not 0 */ 112 + skel = struct_ops_module__open(); 113 + if (!ASSERT_OK_PTR(skel, "struct_ops_module_open_not_zeroed")) 114 + return; 115 + 116 + /* libbpf should reject the testmod_zeroed since struct 117 + * bpf_testmod_ops in the kernel has no "zeroed" field and the 118 + * value of "zeroed" is non-zero. 119 + */ 120 + skel->struct_ops.testmod_zeroed->zeroed = 0xdeadbeef; 121 + err = struct_ops_module__load(skel); 122 + ASSERT_ERR(err, "struct_ops_module_load_not_zeroed"); 123 + 124 + struct_ops_module__destroy(skel); 125 + 126 + /* zeroed_op is not null */ 127 + skel = struct_ops_module__open(); 128 + if (!ASSERT_OK_PTR(skel, "struct_ops_module_open_not_zeroed_op")) 129 + return; 130 + 131 + /* libbpf should reject the testmod_zeroed since the value of its 132 + * "zeroed_op" is not null. 133 + */ 134 + skel->struct_ops.testmod_zeroed->zeroed_op = skel->progs.test_3; 135 + err = struct_ops_module__load(skel); 136 + ASSERT_ERR(err, "struct_ops_module_load_not_zeroed_op"); 137 + 138 + struct_ops_module__destroy(skel); 139 + } 140 + 96 141 void serial_test_struct_ops_module(void) 97 142 { 98 143 if (test__start_subtest("test_struct_ops_load")) 99 144 test_struct_ops_load(); 145 + if (test__start_subtest("test_struct_ops_not_zeroed")) 146 + test_struct_ops_not_zeroed(); 100 147 } 101 148
+1 -1
tools/testing/selftests/bpf/progs/iters.c
··· 673 673 674 674 static __noinline int sum(struct bpf_iter_num *it, int *arr, __u32 n) 675 675 { 676 - int *t, i, sum = 0;; 676 + int *t, i, sum = 0; 677 677 678 678 while ((t = bpf_iter_num_next(it))) { 679 679 i = *t;
+15 -1
tools/testing/selftests/bpf/progs/struct_ops_module.c
··· 23 23 test_2_result = a + b; 24 24 } 25 25 26 - SEC("struct_ops/test_3") 26 + SEC("?struct_ops/test_3") 27 27 int BPF_PROG(test_3, int a, int b) 28 28 { 29 29 test_2_result = a + b + 3; ··· 51 51 52 52 SEC(".struct_ops.link") 53 53 struct bpf_testmod_ops___v2 testmod_2 = { 54 + .test_1 = (void *)test_1, 55 + .test_2 = (void *)test_2_v2, 56 + }; 57 + 58 + struct bpf_testmod_ops___zeroed { 59 + int (*test_1)(void); 60 + void (*test_2)(int a, int b); 61 + int (*test_maybe_null)(int dummy, struct task_struct *task); 62 + void (*zeroed_op)(int a, int b); 63 + int zeroed; 64 + }; 65 + 66 + SEC(".struct_ops.link") 67 + struct bpf_testmod_ops___zeroed testmod_zeroed = { 54 68 .test_1 = (void *)test_1, 55 69 .test_2 = (void *)test_2_v2, 56 70 };
+16
tools/testing/selftests/bpf/progs/test_bpf_cookie.c
··· 15 15 __u64 uretprobe_res; 16 16 __u64 tp_res; 17 17 __u64 pe_res; 18 + __u64 raw_tp_res; 19 + __u64 tp_btf_res; 18 20 __u64 fentry_res; 19 21 __u64 fexit_res; 20 22 __u64 fmod_ret_res; ··· 86 84 int handle_pe(struct pt_regs *ctx) 87 85 { 88 86 update(ctx, &pe_res); 87 + return 0; 88 + } 89 + 90 + SEC("raw_tp/sys_enter") 91 + int handle_raw_tp(void *ctx) 92 + { 93 + update(ctx, &raw_tp_res); 94 + return 0; 95 + } 96 + 97 + SEC("tp_btf/sys_enter") 98 + int handle_tp_btf(void *ctx) 99 + { 100 + update(ctx, &tp_btf_res); 89 101 return 0; 90 102 } 91 103
+28 -3
tools/testing/selftests/bpf/progs/test_ns_current_pid_tgid.c
··· 5 5 #include <stdint.h> 6 6 #include <bpf/bpf_helpers.h> 7 7 8 + struct { 9 + __uint(type, BPF_MAP_TYPE_SOCKMAP); 10 + __uint(max_entries, 2); 11 + __type(key, __u32); 12 + __type(value, __u32); 13 + } sock_map SEC(".maps"); 14 + 8 15 __u64 user_pid = 0; 9 16 __u64 user_tgid = 0; 10 17 __u64 dev = 0; 11 18 __u64 ino = 0; 12 19 13 - SEC("tracepoint/syscalls/sys_enter_nanosleep") 14 - int handler(const void *ctx) 20 + static void get_pid_tgid(void) 15 21 { 16 22 struct bpf_pidns_info nsdata; 17 23 18 24 if (bpf_get_ns_current_pid_tgid(dev, ino, &nsdata, sizeof(struct bpf_pidns_info))) 19 - return 0; 25 + return; 20 26 21 27 user_pid = nsdata.pid; 22 28 user_tgid = nsdata.tgid; 29 + } 23 30 31 + SEC("?tracepoint/syscalls/sys_enter_nanosleep") 32 + int tp_handler(const void *ctx) 33 + { 34 + get_pid_tgid(); 24 35 return 0; 36 + } 37 + 38 + SEC("?cgroup/bind4") 39 + int cgroup_bind4(struct bpf_sock_addr *ctx) 40 + { 41 + get_pid_tgid(); 42 + return 1; 43 + } 44 + 45 + SEC("?sk_msg") 46 + int sk_msg(struct sk_msg_md *msg) 47 + { 48 + get_pid_tgid(); 49 + return SK_PASS; 25 50 } 26 51 27 52 char _license[] SEC("license") = "GPL";
+27 -12
tools/testing/selftests/bpf/progs/trigger_bench.c
··· 9 9 10 10 char _license[] SEC("license") = "GPL"; 11 11 12 - long hits = 0; 12 + #define CPU_MASK 255 13 + #define MAX_CPUS (CPU_MASK + 1) /* should match MAX_BUCKETS in benchs/bench_trigger.c */ 14 + 15 + /* matches struct counter in bench.h */ 16 + struct counter { 17 + long value; 18 + } __attribute__((aligned(128))); 19 + 20 + struct counter hits[MAX_CPUS]; 21 + 22 + static __always_inline void inc_counter(void) 23 + { 24 + int cpu = bpf_get_smp_processor_id(); 25 + 26 + __sync_add_and_fetch(&hits[cpu & CPU_MASK].value, 1); 27 + } 13 28 14 29 SEC("tp/syscalls/sys_enter_getpgid") 15 30 int bench_trigger_tp(void *ctx) 16 31 { 17 - __sync_add_and_fetch(&hits, 1); 32 + inc_counter(); 18 33 return 0; 19 34 } 20 35 ··· 37 22 int BPF_PROG(bench_trigger_raw_tp, struct pt_regs *regs, long id) 38 23 { 39 24 if (id == __NR_getpgid) 40 - __sync_add_and_fetch(&hits, 1); 25 + inc_counter(); 41 26 return 0; 42 27 } 43 28 44 29 SEC("kprobe/" SYS_PREFIX "sys_getpgid") 45 30 int bench_trigger_kprobe(void *ctx) 46 31 { 47 - __sync_add_and_fetch(&hits, 1); 32 + inc_counter(); 48 33 return 0; 49 34 } 50 35 51 36 SEC("kretprobe/" SYS_PREFIX "sys_getpgid") 52 37 int bench_trigger_kretprobe(void *ctx) 53 38 { 54 - __sync_add_and_fetch(&hits, 1); 39 + inc_counter(); 55 40 return 0; 56 41 } 57 42 58 43 SEC("kprobe.multi/" SYS_PREFIX "sys_getpgid") 59 44 int bench_trigger_kprobe_multi(void *ctx) 60 45 { 61 - __sync_add_and_fetch(&hits, 1); 46 + inc_counter(); 62 47 return 0; 63 48 } 64 49 65 50 SEC("kretprobe.multi/" SYS_PREFIX "sys_getpgid") 66 51 int bench_trigger_kretprobe_multi(void *ctx) 67 52 { 68 - __sync_add_and_fetch(&hits, 1); 53 + inc_counter(); 69 54 return 0; 70 55 } 71 56 72 57 SEC("fentry/" SYS_PREFIX "sys_getpgid") 73 58 int bench_trigger_fentry(void *ctx) 74 59 { 75 - __sync_add_and_fetch(&hits, 1); 60 + inc_counter(); 76 61 return 0; 77 62 } 78 63 79 64 SEC("fexit/" SYS_PREFIX "sys_getpgid") 80 65 int bench_trigger_fexit(void *ctx) 81 66 { 82 - __sync_add_and_fetch(&hits, 1); 67 + inc_counter(); 83 68 return 0; 84 69 } 85 70 86 71 SEC("fentry.s/" SYS_PREFIX "sys_getpgid") 87 72 int bench_trigger_fentry_sleep(void *ctx) 88 73 { 89 - __sync_add_and_fetch(&hits, 1); 74 + inc_counter(); 90 75 return 0; 91 76 } 92 77 93 78 SEC("fmod_ret/" SYS_PREFIX "sys_getpgid") 94 79 int bench_trigger_fmodret(void *ctx) 95 80 { 96 - __sync_add_and_fetch(&hits, 1); 81 + inc_counter(); 97 82 return -22; 98 83 } 99 84 100 85 SEC("uprobe") 101 86 int bench_trigger_uprobe(void *ctx) 102 87 { 103 - __sync_add_and_fetch(&hits, 1); 88 + inc_counter(); 104 89 return 0; 105 90 }
+5
tools/testing/selftests/bpf/test_cpp.cpp
··· 7 7 #include <bpf/bpf.h> 8 8 #include <bpf/btf.h> 9 9 #include "test_core_extern.skel.h" 10 + #include "struct_ops_module.skel.h" 10 11 11 12 template <typename T> 12 13 class Skeleton { ··· 99 98 { 100 99 struct btf_dump_opts opts = { }; 101 100 struct test_core_extern *skel; 101 + struct struct_ops_module *skel2; 102 102 struct btf *btf; 103 103 int fd; 104 104 ··· 119 117 /* BPF skeleton */ 120 118 skel = test_core_extern__open_and_load(); 121 119 test_core_extern__destroy(skel); 120 + 121 + skel2 = struct_ops_module__open_and_load(); 122 + struct_ops_module__destroy(skel2); 122 123 123 124 fd = bpf_enable_stats(BPF_STATS_RUN_TIME); 124 125 if (fd < 0)
+12 -1
tools/testing/selftests/bpf/test_tc_tunnel.sh
··· 72 72 server_listen() { 73 73 ip netns exec "${ns2}" nc "${netcat_opt}" -l "${port}" > "${outfile}" & 74 74 server_pid=$! 75 - sleep 0.2 76 75 } 77 76 78 77 client_connect() { ··· 90 91 echo "data mismatch" 91 92 exit 1 92 93 fi 94 + } 95 + 96 + wait_for_port() { 97 + for i in $(seq 20); do 98 + if ip netns exec "${ns2}" ss ${2:--4}OHntl | grep -q "$1"; then 99 + return 0 100 + fi 101 + sleep 0.1 102 + done 103 + return 1 93 104 } 94 105 95 106 set -e ··· 202 193 # basic communication works 203 194 echo "test basic connectivity" 204 195 server_listen 196 + wait_for_port ${port} ${netcat_opt} 205 197 client_connect 206 198 verify_data 207 199 ··· 214 204 section "encap_${tuntype}_${mac}" 215 205 echo "test bpf encap without decap (expect failure)" 216 206 server_listen 207 + wait_for_port ${port} ${netcat_opt} 217 208 ! client_connect 218 209 219 210 if [[ "$tuntype" =~ "udp" ]]; then