History

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 ... ====================

Jakub Kicinski committed 2 years ago

Commit 2a702c22 parents ee36b1e 14bb1e850 files · +867 −274Browse files

Unified · Split

50 files
  1. arch/arm/net/bpf_jit_32.c +12 −13
  2. arch/arm64/net/bpf_jit_comp.c +2 −5
  3. arch/loongarch/net/bpf_jit.c +16 −6
  4. arch/mips/net/bpf_jit_comp.c +2 −1
  5. arch/parisc/net/bpf_jit_core.c +7 −1
  6. arch/s390/net/bpf_jit_comp.c +5 −1
  7. arch/sparc/net/bpf_jit_comp_64.c +5 −1
  8. arch/x86/net/bpf_jit_comp.c +3 −7
  9. arch/x86/net/bpf_jit_comp32.c +1 −2
  10. include/linux/bpf.h +7 −2
  11. include/linux/filter.h +16 −4
  12. include/linux/trace_events.h +20 −16
  13. include/trace/bpf_probe.h +1 −2
  14. include/uapi/linux/bpf.h +4 −2
  15. kernel/bpf/bpf_struct_ops.c +6 −4
  16. kernel/bpf/cgroup.c +0 −2
  17. kernel/bpf/core.c +24 −8
  18. kernel/bpf/helpers.c +4 −0
  19. kernel/bpf/lpm_trie.c +13 −5
  20. kernel/bpf/syscall.c +11 −11
  21. kernel/bpf/trampoline.c +5 −10
  22. kernel/bpf/verifier.c +20 −11
  23. kernel/trace/bpf_trace.c +32 −20
  24. net/bpf/bpf_dummy_struct_ops.c +3 −1
  25. net/core/filter.c +0 −2
  26. tools/bpf/bpftool/Makefile +6 −8
  27. tools/bpf/bpftool/gen.c +2 −1
  28. tools/bpf/bpftool/pids.c +12 −7
  29. tools/bpf/bpftool/skeleton/pid_iter.bpf.c +2 −2
  30. tools/include/linux/compiler.h +4 −0
  31. tools/include/uapi/linux/bpf.h +4 −2
  32. tools/lib/bpf/bpf.c +14 −2
  33. tools/lib/bpf/bpf.h +9 −0
  34. tools/lib/bpf/libbpf.c +92 −19
  35. tools/lib/bpf/libbpf.h +11 −0
  36. tools/lib/bpf/libbpf.map +2 −0
  37. tools/testing/selftests/bpf/benchs/bench_local_storage_create.c +1 −1
  38. tools/testing/selftests/bpf/benchs/bench_trigger.c +40 −8
  39. tools/testing/selftests/bpf/prog_tests/bpf_cookie.c +113 −1
  40. tools/testing/selftests/bpf/prog_tests/bpf_tcp_ca.c +1 −12
  41. tools/testing/selftests/bpf/prog_tests/btf_map_in_map.c +1 −25
  42. tools/testing/selftests/bpf/prog_tests/ns_current_pid_tgid.c +183 −31
  43. tools/testing/selftests/bpf/prog_tests/test_struct_ops_module.c +47 −0
  44. tools/testing/selftests/bpf/progs/iters.c +1 −1
  45. tools/testing/selftests/bpf/progs/struct_ops_module.c +15 −1
  46. tools/testing/selftests/bpf/progs/test_bpf_cookie.c +16 −0
  47. tools/testing/selftests/bpf/progs/test_ns_current_pid_tgid.c +28 −3
  48. tools/testing/selftests/bpf/progs/trigger_bench.c +27 −12
  49. tools/testing/selftests/bpf/test_cpp.cpp +5 −0
  50. tools/testing/selftests/bpf/test_tc_tunnel.sh +12 −1
arch/arm/net/bpf_jit_32.c+12−13
@@ -2222,28 +2222,21 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog) · 2221 unmodified lines
2222 /* If building the body of the JITed code fails somehow,2222 /* If building the body of the JITed code fails somehow,
2223 * we fall back to the interpretation.2223 * we fall back to the interpretation.
2224 */2224 */
2225 if (build_body(&ctx) < 0) {2225 if (build_body(&ctx) < 0)
2226 image_ptr = NULL;2226 goto out_free;
2227 bpf_jit_binary_free(header);
2228 prog = orig_prog;
2229 goto out_imms;
2230 }
2231 build_epilogue(&ctx);2227 build_epilogue(&ctx);
2232 2228
2233 /* 3.) Extra pass to validate JITed Code */2229 /* 3.) Extra pass to validate JITed Code */
2234 if (validate_code(&ctx)) {2230 if (validate_code(&ctx))
2235 image_ptr = NULL;2231 goto out_free;
2236 bpf_jit_binary_free(header);
2237 prog = orig_prog;
2238 goto out_imms;
2239 }
2240 flush_icache_range((u32)header, (u32)(ctx.target + ctx.idx));2232 flush_icache_range((u32)header, (u32)(ctx.target + ctx.idx));
2241 2233
2242 if (bpf_jit_enable > 1)2234 if (bpf_jit_enable > 1)
2243 /* there are 2 passes here */2235 /* there are 2 passes here */
2244 bpf_jit_dump(prog->len, image_size, 2, ctx.target);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 prog->bpf_func = (void *)ctx.target;2240 prog->bpf_func = (void *)ctx.target;
2248 prog->jited = 1;2241 prog->jited = 1;
2249 prog->jited_len = image_size;2242 prog->jited_len = image_size;
@@ -2260,5 +2253,11 @@ out: · 10 unmodified lines
2260 bpf_jit_prog_release_other(prog, prog == orig_prog ?2253 bpf_jit_prog_release_other(prog, prog == orig_prog ?
2261 tmp : orig_prog);2254 tmp : orig_prog);
2262 return prog;2255 return prog;
2256
2257out_free:
2258 image_ptr = NULL;
2259 bpf_jit_binary_free(header);
2260 prog = orig_prog;
2261 goto out_imms;
2263}2262}
2264 2263
arch/arm64/net/bpf_jit_comp.c+2−5
@@ -2176,12 +2176,9 @@ void arch_free_bpf_trampoline(void *image, unsigned int size) · 2175 unmodified lines
2176 bpf_prog_pack_free(image, size);2176 bpf_prog_pack_free(image, size);
2177}2177}
2178 2178
2179void arch_protect_bpf_trampoline(void *image, unsigned int size)2179int arch_protect_bpf_trampoline(void *image, unsigned int size)
2180{
2181}
2182
2183void arch_unprotect_bpf_trampoline(void *image, unsigned int size)
2184{2180{
2181 return 0;
2185}2182}
2186 2183
2187int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *ro_image,2184int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *ro_image,
arch/loongarch/net/bpf_jit.c+16−6
@@ -1294,16 +1294,19 @@ skip_init_ctx: · 1293 unmodified lines
1294 flush_icache_range((unsigned long)header, (unsigned long)(ctx.image + ctx.idx));1294 flush_icache_range((unsigned long)header, (unsigned long)(ctx.image + ctx.idx));
1295 1295
1296 if (!prog->is_func || extra_pass) {1296 if (!prog->is_func || extra_pass) {
1297 int err;
1298
1297 if (extra_pass && ctx.idx != jit_data->ctx.idx) {1299 if (extra_pass && ctx.idx != jit_data->ctx.idx) {
1298 pr_err_once("multi-func JIT bug %d != %d\n",1300 pr_err_once("multi-func JIT bug %d != %d\n",
1299 ctx.idx, jit_data->ctx.idx);1301 ctx.idx, jit_data->ctx.idx);
1300 bpf_jit_binary_free(header);1302 goto out_free;
1301 prog->bpf_func = NULL;1303 }
1302 prog->jited = 0;1304 err = bpf_jit_binary_lock_ro(header);
1303 prog->jited_len = 0;1305 if (err) {
1304 goto out_offset;1306 pr_err_once("bpf_jit_binary_lock_ro() returned %d\n",
1307 err);
1308 goto out_free;
1305 }1309 }
1306 bpf_jit_binary_lock_ro(header);
1307 } else {1310 } else {
1308 jit_data->ctx = ctx;1311 jit_data->ctx = ctx;
1309 jit_data->image = image_ptr;1312 jit_data->image = image_ptr;
@@ -1334,6 +1337,13 @@ out: · 24 unmodified lines
1334 out_offset = -1;1337 out_offset = -1;
1335 1338
1336 return prog;1339 return prog;
1340
1341out_free:
1342 bpf_jit_binary_free(header);
1343 prog->bpf_func = NULL;
1344 prog->jited = 0;
1345 prog->jited_len = 0;
1346 goto out_offset;
1337}1347}
1338 1348
1339/* Indicate the JIT backend supports mixing bpf2bpf and tailcalls. */1349/* Indicate the JIT backend supports mixing bpf2bpf and tailcalls. */
arch/mips/net/bpf_jit_comp.c+2−1
@@ -1012,7 +1012,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog) · 1011 unmodified lines
1012 bpf_prog_fill_jited_linfo(prog, &ctx.descriptors[1]);1012 bpf_prog_fill_jited_linfo(prog, &ctx.descriptors[1]);
1013 1013
1014 /* Set as read-only exec and flush instruction cache */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 flush_icache_range((unsigned long)header,1017 flush_icache_range((unsigned long)header,
1017 (unsigned long)&ctx.target[ctx.jit_index]);1018 (unsigned long)&ctx.target[ctx.jit_index]);
1018 1019
arch/parisc/net/bpf_jit_core.c+7−1
@@ -167,7 +167,13 @@ skip_init_ctx: · 166 unmodified lines
167 bpf_flush_icache(jit_data->header, ctx->insns + ctx->ninsns);167 bpf_flush_icache(jit_data->header, ctx->insns + ctx->ninsns);
168 168
169 if (!prog->is_func || extra_pass) {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 prologue_len = ctx->epilogue_offset - ctx->body_len;177 prologue_len = ctx->epilogue_offset - ctx->body_len;
172 for (i = 0; i < prog->len; i++)178 for (i = 0; i < prog->len; i++)
173 ctx->offset[i] += prologue_len;179 ctx->offset[i] += prologue_len;
arch/s390/net/bpf_jit_comp.c+5−1
@@ -2111,7 +2111,11 @@ skip_init_ctx: · 2110 unmodified lines
2111 print_fn_code(jit.prg_buf, jit.size_prg);2111 print_fn_code(jit.prg_buf, jit.size_prg);
2112 }2112 }
2113 if (!fp->is_func || extra_pass) {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 } else {2119 } else {
2116 jit_data->header = header;2120 jit_data->header = header;
2117 jit_data->ctx = jit;2121 jit_data->ctx = jit;
arch/sparc/net/bpf_jit_comp_64.c+5−1
@@ -1602,7 +1602,11 @@ skip_init_ctx: · 1601 unmodified lines
1602 bpf_flush_icache(header, (u8 *)header + header->size);1602 bpf_flush_icache(header, (u8 *)header + header->size);
1603 1603
1604 if (!prog->is_func || extra_pass) {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 } else {1610 } else {
1607 jit_data->ctx = ctx;1611 jit_data->ctx = ctx;
1608 jit_data->image = image_ptr;1612 jit_data->image = image_ptr;
arch/x86/net/bpf_jit_comp.c+3−7
@@ -1351,8 +1351,7 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, u8 *rw_image · 1350 unmodified lines
1351 break;1351 break;
1352 1352
1353 case BPF_ALU64 | BPF_MOV | BPF_X:1353 case BPF_ALU64 | BPF_MOV | BPF_X:
1354 if (insn->off == BPF_ADDR_SPACE_CAST &&1354 if (insn_is_cast_user(insn)) {
1355 insn->imm == 1U << 16) {
1356 if (dst_reg != src_reg)1355 if (dst_reg != src_reg)
1357 /* 32-bit mov */1356 /* 32-bit mov */
1358 emit_mov_reg(&prog, false, dst_reg, src_reg);1357 emit_mov_reg(&prog, false, dst_reg, src_reg);
@@ -3004,12 +3003,9 @@ void arch_free_bpf_trampoline(void *image, unsigned int size) · 1645 unmodified lines
3004 bpf_prog_pack_free(image, size);3003 bpf_prog_pack_free(image, size);
3005}3004}
3006 3005
3007void arch_protect_bpf_trampoline(void *image, unsigned int size)3006int arch_protect_bpf_trampoline(void *image, unsigned int size)
3008{
3009}
3010
3011void arch_unprotect_bpf_trampoline(void *image, unsigned int size)
3012{3007{
3008 return 0;
3013}3009}
3014 3010
3015int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image, void *image_end,3011int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image, void *image_end,
arch/x86/net/bpf_jit_comp32.c+1−2
@@ -2600,8 +2600,7 @@ out_image: · 2599 unmodified lines
2600 if (bpf_jit_enable > 1)2600 if (bpf_jit_enable > 1)
2601 bpf_jit_dump(prog->len, proglen, pass + 1, image);2601 bpf_jit_dump(prog->len, proglen, pass + 1, image);
2602 2602
2603 if (image) {2603 if (image && !bpf_jit_binary_lock_ro(header)) {
2604 bpf_jit_binary_lock_ro(header);
2605 prog->bpf_func = (void *)image;2604 prog->bpf_func = (void *)image;
2606 prog->jited = 1;2605 prog->jited = 1;
2607 prog->jited_len = proglen;2606 prog->jited_len = proglen;
include/linux/bpf.h+7−2
@@ -1116,8 +1116,7 @@ int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image, void *i · 1115 unmodified lines
1116 void *func_addr);1116 void *func_addr);
1117void *arch_alloc_bpf_trampoline(unsigned int size);1117void *arch_alloc_bpf_trampoline(unsigned int size);
1118void arch_free_bpf_trampoline(void *image, unsigned int size);1118void arch_free_bpf_trampoline(void *image, unsigned int size);
1119void arch_protect_bpf_trampoline(void *image, unsigned int size);1119int __must_check arch_protect_bpf_trampoline(void *image, unsigned int size);
1120void arch_unprotect_bpf_trampoline(void *image, unsigned int size);
1121int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags,1120int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags,
1122 struct bpf_tramp_links *tlinks, void *func_addr);1121 struct bpf_tramp_links *tlinks, void *func_addr);
1123 1122
@@ -1608,6 +1607,12 @@ struct bpf_tracing_link { · 484 unmodified lines
1608 struct bpf_prog *tgt_prog;1607 struct bpf_prog *tgt_prog;
1609};1608};
1610 1609
1610struct bpf_raw_tp_link {
1611 struct bpf_link link;
1612 struct bpf_raw_event_map *btp;
1613 u64 cookie;
1614};
1615
1611struct bpf_link_primer {1616struct bpf_link_primer {
1612 struct bpf_link *link;1617 struct bpf_link *link;
1613 struct file *file;1618 struct file *file;
include/linux/filter.h+16−4
@@ -228,6 +228,16 @@ static inline bool insn_is_zext(const struct bpf_insn *insn) · 227 unmodified lines
228 return insn->code == (BPF_ALU | BPF_MOV | BPF_X) && insn->imm == 1;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 */
234static 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/* BPF_LD_IMM64 macro encodes single 'load 64-bit immediate' insn */241/* BPF_LD_IMM64 macro encodes single 'load 64-bit immediate' insn */
232#define BPF_LD_IMM64(DST, IMM) \242#define BPF_LD_IMM64(DST, IMM) \
233 BPF_LD_IMM64_RAW(DST, 0, IMM)243 BPF_LD_IMM64_RAW(DST, 0, IMM)
@@ -887,20 +897,22 @@ bpf_ctx_narrow_access_offset(u32 off, u32 size, u32 size_default) · 653 unmodified lines
887 897
888#define bpf_classic_proglen(fprog) (fprog->len * sizeof(fprog->filter[0]))898#define bpf_classic_proglen(fprog) (fprog->len * sizeof(fprog->filter[0]))
889 899
890static inline void bpf_prog_lock_ro(struct bpf_prog *fp)900static inline int __must_check bpf_prog_lock_ro(struct bpf_prog *fp)
891{901{
892#ifndef CONFIG_BPF_JIT_ALWAYS_ON902#ifndef CONFIG_BPF_JIT_ALWAYS_ON
893 if (!fp->jited) {903 if (!fp->jited) {
894 set_vm_flush_reset_perms(fp);904 set_vm_flush_reset_perms(fp);
895 set_memory_ro((unsigned long)fp, fp->pages);905 return set_memory_ro((unsigned long)fp, fp->pages);
896 }906 }
897#endif907#endif
908 return 0;
898}909}
899 910
900static inline void bpf_jit_binary_lock_ro(struct bpf_binary_header *hdr)911static inline int __must_check
912bpf_jit_binary_lock_ro(struct bpf_binary_header *hdr)
901{913{
902 set_vm_flush_reset_perms(hdr);914 set_vm_flush_reset_perms(hdr);
903 set_memory_rox((unsigned long)hdr, hdr->size >> PAGE_SHIFT);915 return set_memory_rox((unsigned long)hdr, hdr->size >> PAGE_SHIFT);
904}916}
905 917
906int sk_filter_trim_cap(struct sock *sk, struct sk_buff *skb, unsigned int cap);918int sk_filter_trim_cap(struct sock *sk, struct sk_buff *skb, unsigned int cap);
include/linux/trace_events.h+20−16
@@ -765,8 +765,11 @@ unsigned int trace_call_bpf(struct trace_event_call *call, void *ctx); · 764 unmodified lines
765int perf_event_attach_bpf_prog(struct perf_event *event, struct bpf_prog *prog, u64 bpf_cookie);765int perf_event_attach_bpf_prog(struct perf_event *event, struct bpf_prog *prog, u64 bpf_cookie);
766void perf_event_detach_bpf_prog(struct perf_event *event);766void perf_event_detach_bpf_prog(struct perf_event *event);
767int perf_event_query_prog_array(struct perf_event *event, void __user *info);767int perf_event_query_prog_array(struct perf_event *event, void __user *info);
768int bpf_probe_register(struct bpf_raw_event_map *btp, struct bpf_prog *prog);768
769int bpf_probe_unregister(struct bpf_raw_event_map *btp, struct bpf_prog *prog);769struct bpf_raw_tp_link;
770int bpf_probe_register(struct bpf_raw_event_map *btp, struct bpf_raw_tp_link *link);
771int bpf_probe_unregister(struct bpf_raw_event_map *btp, struct bpf_raw_tp_link *link);
772
770struct bpf_raw_event_map *bpf_get_raw_tracepoint(const char *name);773struct bpf_raw_event_map *bpf_get_raw_tracepoint(const char *name);
771void bpf_put_raw_tracepoint(struct bpf_raw_event_map *btp);774void bpf_put_raw_tracepoint(struct bpf_raw_event_map *btp);
772int bpf_get_perf_event_info(const struct perf_event *event, u32 *prog_id,775int bpf_get_perf_event_info(const struct perf_event *event, u32 *prog_id,
@@ -794,11 +797,12 @@ perf_event_query_prog_array(struct perf_event *event, void __user *info) · 21 unmodified lines
794{797{
795 return -EOPNOTSUPP;798 return -EOPNOTSUPP;
796}799}
797static inline int bpf_probe_register(struct bpf_raw_event_map *btp, struct bpf_prog *p)800struct bpf_raw_tp_link;
801static inline int bpf_probe_register(struct bpf_raw_event_map *btp, struct bpf_raw_tp_link *link)
798{802{
799 return -EOPNOTSUPP;803 return -EOPNOTSUPP;
800}804}
801static inline int bpf_probe_unregister(struct bpf_raw_event_map *btp, struct bpf_prog *p)805static inline int bpf_probe_unregister(struct bpf_raw_event_map *btp, struct bpf_raw_tp_link *link)
802{806{
803 return -EOPNOTSUPP;807 return -EOPNOTSUPP;
804}808}
@@ -909,31 +913,31 @@ void *perf_trace_buf_alloc(int size, struct pt_regs **regs, int *rctxp); · 104 unmodified lines
909int perf_event_set_bpf_prog(struct perf_event *event, struct bpf_prog *prog, u64 bpf_cookie);913int perf_event_set_bpf_prog(struct perf_event *event, struct bpf_prog *prog, u64 bpf_cookie);
910void perf_event_free_bpf_prog(struct perf_event *event);914void perf_event_free_bpf_prog(struct perf_event *event);
911 915
912void bpf_trace_run1(struct bpf_prog *prog, u64 arg1);916void bpf_trace_run1(struct bpf_raw_tp_link *link, u64 arg1);
913void bpf_trace_run2(struct bpf_prog *prog, u64 arg1, u64 arg2);917void bpf_trace_run2(struct bpf_raw_tp_link *link, u64 arg1, u64 arg2);
914void bpf_trace_run3(struct bpf_prog *prog, u64 arg1, u64 arg2,918void bpf_trace_run3(struct bpf_raw_tp_link *link, u64 arg1, u64 arg2,
915 u64 arg3);919 u64 arg3);
916void bpf_trace_run4(struct bpf_prog *prog, u64 arg1, u64 arg2,920void bpf_trace_run4(struct bpf_raw_tp_link *link, u64 arg1, u64 arg2,
917 u64 arg3, u64 arg4);921 u64 arg3, u64 arg4);
918void bpf_trace_run5(struct bpf_prog *prog, u64 arg1, u64 arg2,922void bpf_trace_run5(struct bpf_raw_tp_link *link, u64 arg1, u64 arg2,
919 u64 arg3, u64 arg4, u64 arg5);923 u64 arg3, u64 arg4, u64 arg5);
920void bpf_trace_run6(struct bpf_prog *prog, u64 arg1, u64 arg2,924void bpf_trace_run6(struct bpf_raw_tp_link *link, u64 arg1, u64 arg2,
921 u64 arg3, u64 arg4, u64 arg5, u64 arg6);925 u64 arg3, u64 arg4, u64 arg5, u64 arg6);
922void bpf_trace_run7(struct bpf_prog *prog, u64 arg1, u64 arg2,926void bpf_trace_run7(struct bpf_raw_tp_link *link, u64 arg1, u64 arg2,
923 u64 arg3, u64 arg4, u64 arg5, u64 arg6, u64 arg7);927 u64 arg3, u64 arg4, u64 arg5, u64 arg6, u64 arg7);
924void bpf_trace_run8(struct bpf_prog *prog, u64 arg1, u64 arg2,928void bpf_trace_run8(struct bpf_raw_tp_link *link, u64 arg1, u64 arg2,
925 u64 arg3, u64 arg4, u64 arg5, u64 arg6, u64 arg7,929 u64 arg3, u64 arg4, u64 arg5, u64 arg6, u64 arg7,
926 u64 arg8);930 u64 arg8);
927void bpf_trace_run9(struct bpf_prog *prog, u64 arg1, u64 arg2,931void bpf_trace_run9(struct bpf_raw_tp_link *link, u64 arg1, u64 arg2,
928 u64 arg3, u64 arg4, u64 arg5, u64 arg6, u64 arg7,932 u64 arg3, u64 arg4, u64 arg5, u64 arg6, u64 arg7,
929 u64 arg8, u64 arg9);933 u64 arg8, u64 arg9);
930void bpf_trace_run10(struct bpf_prog *prog, u64 arg1, u64 arg2,934void bpf_trace_run10(struct bpf_raw_tp_link *link, u64 arg1, u64 arg2,
931 u64 arg3, u64 arg4, u64 arg5, u64 arg6, u64 arg7,935 u64 arg3, u64 arg4, u64 arg5, u64 arg6, u64 arg7,
932 u64 arg8, u64 arg9, u64 arg10);936 u64 arg8, u64 arg9, u64 arg10);
933void bpf_trace_run11(struct bpf_prog *prog, u64 arg1, u64 arg2,937void bpf_trace_run11(struct bpf_raw_tp_link *link, u64 arg1, u64 arg2,
934 u64 arg3, u64 arg4, u64 arg5, u64 arg6, u64 arg7,938 u64 arg3, u64 arg4, u64 arg5, u64 arg6, u64 arg7,
935 u64 arg8, u64 arg9, u64 arg10, u64 arg11);939 u64 arg8, u64 arg9, u64 arg10, u64 arg11);
936void bpf_trace_run12(struct bpf_prog *prog, u64 arg1, u64 arg2,940void bpf_trace_run12(struct bpf_raw_tp_link *link, u64 arg1, u64 arg2,
937 u64 arg3, u64 arg4, u64 arg5, u64 arg6, u64 arg7,941 u64 arg3, u64 arg4, u64 arg5, u64 arg6, u64 arg7,
938 u64 arg8, u64 arg9, u64 arg10, u64 arg11, u64 arg12);942 u64 arg8, u64 arg9, u64 arg10, u64 arg11, u64 arg12);
939void perf_trace_run_bpf_submit(void *raw_data, int size, int rctx,943void perf_trace_run_bpf_submit(void *raw_data, int size, int rctx,
include/trace/bpf_probe.h+1−2
@@ -46,8 +46,7 @@ · 45 unmodified lines
46static notrace void \46static notrace void \
47__bpf_trace_##call(void *__data, proto) \47__bpf_trace_##call(void *__data, proto) \
48{ \48{ \
49 struct bpf_prog *prog = __data; \49 CONCATENATE(bpf_trace_run, COUNT_ARGS(args))(__data, CAST_TO_U64(args)); \
50 CONCATENATE(bpf_trace_run, COUNT_ARGS(args))(prog, CAST_TO_U64(args)); \
51}50}
52 51
53#undef DECLARE_EVENT_CLASS52#undef DECLARE_EVENT_CLASS
include/uapi/linux/bpf.h+4−2
@@ -1662,8 +1662,10 @@ union bpf_attr { · 1661 unmodified lines
1662 } query;1662 } query;
1663 1663
1664 struct { /* anonymous struct used by BPF_RAW_TRACEPOINT_OPEN command */1664 struct { /* anonymous struct used by BPF_RAW_TRACEPOINT_OPEN command */
1665 __u64 name;1665 __u64 name;
1666 __u32 prog_fd;1666 __u32 prog_fd;
1667 __u32 :32;
1668 __aligned_u64 cookie;
1667 } raw_tracepoint;1669 } raw_tracepoint;
1668 1670
1669 struct { /* anonymous struct for BPF_BTF_LOAD */1671 struct { /* anonymous struct for BPF_BTF_LOAD */
kernel/bpf/bpf_struct_ops.c+6−4
@@ -728,8 +728,6 @@ static long bpf_struct_ops_map_update_elem(struct bpf_map *map, void *key, · 727 unmodified lines
728 cur_image = image;728 cur_image = image;
729 trampoline_start = 0;729 trampoline_start = 0;
730 }730 }
731 if (err < 0)
732 goto reset_unlock;
733 731
734 *(void **)(kdata + moff) = image + trampoline_start + cfi_get_offset();732 *(void **)(kdata + moff) = image + trampoline_start + cfi_get_offset();
735 733
@@ -742,8 +740,12 @@ static long bpf_struct_ops_map_update_elem(struct bpf_map *map, void *key, · 6 unmodified lines
742 if (err)740 if (err)
743 goto reset_unlock;741 goto reset_unlock;
744 }742 }
745 for (i = 0; i < st_map->image_pages_cnt; i++)743 for (i = 0; i < st_map->image_pages_cnt; i++) {
746 arch_protect_bpf_trampoline(st_map->image_pages[i], PAGE_SIZE);744 err = arch_protect_bpf_trampoline(st_map->image_pages[i],
745 PAGE_SIZE);
746 if (err)
747 goto reset_unlock;
748 }
747 749
748 if (st_map->map.map_flags & BPF_F_LINK) {750 if (st_map->map.map_flags & BPF_F_LINK) {
749 err = 0;751 err = 0;
kernel/bpf/cgroup.c+0−2
@@ -2575,8 +2575,6 @@ cgroup_current_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) · 2574 unmodified lines
2575 switch (func_id) {2575 switch (func_id) {
2576 case BPF_FUNC_get_current_uid_gid:2576 case BPF_FUNC_get_current_uid_gid:
2577 return &bpf_get_current_uid_gid_proto;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 case BPF_FUNC_get_current_comm:2578 case BPF_FUNC_get_current_comm:
2581 return &bpf_get_current_comm_proto;2579 return &bpf_get_current_comm_proto;
2582#ifdef CONFIG_CGROUP_NET_CLASSID2580#ifdef CONFIG_CGROUP_NET_CLASSID
kernel/bpf/core.c+24−8
@@ -908,23 +908,30 @@ static LIST_HEAD(pack_list); · 907 unmodified lines
908static struct bpf_prog_pack *alloc_new_pack(bpf_jit_fill_hole_t bpf_fill_ill_insns)908static struct bpf_prog_pack *alloc_new_pack(bpf_jit_fill_hole_t bpf_fill_ill_insns)
909{909{
910 struct bpf_prog_pack *pack;910 struct bpf_prog_pack *pack;
911 int err;
911 912
912 pack = kzalloc(struct_size(pack, bitmap, BITS_TO_LONGS(BPF_PROG_CHUNK_COUNT)),913 pack = kzalloc(struct_size(pack, bitmap, BITS_TO_LONGS(BPF_PROG_CHUNK_COUNT)),
913 GFP_KERNEL);914 GFP_KERNEL);
914 if (!pack)915 if (!pack)
915 return NULL;916 return NULL;
916 pack->ptr = bpf_jit_alloc_exec(BPF_PROG_PACK_SIZE);917 pack->ptr = bpf_jit_alloc_exec(BPF_PROG_PACK_SIZE);
917 if (!pack->ptr) {918 if (!pack->ptr)
918 kfree(pack);919 goto out;
919 return NULL;
920 }
921 bpf_fill_ill_insns(pack->ptr, BPF_PROG_PACK_SIZE);920 bpf_fill_ill_insns(pack->ptr, BPF_PROG_PACK_SIZE);
922 bitmap_zero(pack->bitmap, BPF_PROG_PACK_SIZE / BPF_PROG_CHUNK_SIZE);921 bitmap_zero(pack->bitmap, BPF_PROG_PACK_SIZE / BPF_PROG_CHUNK_SIZE);
923 list_add_tail(&pack->list, &pack_list);
924 922
925 set_vm_flush_reset_perms(pack->ptr);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 return pack;929 return pack;
930
931out:
932 bpf_jit_free_exec(pack->ptr);
933 kfree(pack);
934 return NULL;
928}935}
929 936
930void *bpf_prog_pack_alloc(u32 size, bpf_jit_fill_hole_t bpf_fill_ill_insns)937void *bpf_prog_pack_alloc(u32 size, bpf_jit_fill_hole_t bpf_fill_ill_insns)
@@ -939,9 +946,16 @@ void *bpf_prog_pack_alloc(u32 size, bpf_jit_fill_hole_t bpf_fill_ill_insns) · 8 unmodified lines
939 size = round_up(size, PAGE_SIZE);946 size = round_up(size, PAGE_SIZE);
940 ptr = bpf_jit_alloc_exec(size);947 ptr = bpf_jit_alloc_exec(size);
941 if (ptr) {948 if (ptr) {
949 int err;
950
942 bpf_fill_ill_insns(ptr, size);951 bpf_fill_ill_insns(ptr, size);
943 set_vm_flush_reset_perms(ptr);952 set_vm_flush_reset_perms(ptr);
944 set_memory_rox((unsigned long)ptr, size / PAGE_SIZE);953 err = set_memory_rox((unsigned long)ptr,
954 size / PAGE_SIZE);
955 if (err) {
956 bpf_jit_free_exec(ptr);
957 ptr = NULL;
958 }
945 }959 }
946 goto out;960 goto out;
947 }961 }
@@ -2403,7 +2417,9 @@ struct bpf_prog *bpf_prog_select_runtime(struct bpf_prog *fp, int *err) · 1455 unmodified lines
2403 }2417 }
2404 2418
2405finalize:2419finalize:
2406 bpf_prog_lock_ro(fp);2420 *err = bpf_prog_lock_ro(fp);
2421 if (*err)
2422 return fp;
2407 2423
2408 /* The tail call compatibility check can only be done at2424 /* The tail call compatibility check can only be done at
2409 * this late stage as we need to determine, if we deal2425 * this late stage as we need to determine, if we deal
kernel/bpf/helpers.c+4−0
@@ -1730,6 +1730,10 @@ bpf_base_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) · 1729 unmodified lines
1730 return &bpf_strtol_proto;1730 return &bpf_strtol_proto;
1731 case BPF_FUNC_strtoul:1731 case BPF_FUNC_strtoul:
1732 return &bpf_strtoul_proto;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 default:1737 default:
1734 break;1738 break;
1735 }1739 }
kernel/bpf/lpm_trie.c+13−5
@@ -155,16 +155,17 @@ static inline int extract_bit(const u8 *data, size_t index) · 154 unmodified lines
155}155}
156 156
157/**157/**
158 * longest_prefix_match() - determine the longest prefix158 * __longest_prefix_match() - determine the longest prefix
159 * @trie: The trie to get internal sizes from159 * @trie: The trie to get internal sizes from
160 * @node: The node to operate on160 * @node: The node to operate on
161 * @key: The key to compare to @node161 * @key: The key to compare to @node
162 *162 *
163 * Determine the longest prefix of @node that matches the bits in @key.163 * Determine the longest prefix of @node that matches the bits in @key.
164 */164 */
165static size_t longest_prefix_match(const struct lpm_trie *trie,165static __always_inline
166 const struct lpm_trie_node *node,166size_t __longest_prefix_match(const struct lpm_trie *trie,
167 const struct bpf_lpm_trie_key_u8 *key)167 const struct lpm_trie_node *node,
168 const struct bpf_lpm_trie_key_u8 *key)
168{169{
169 u32 limit = min(node->prefixlen, key->prefixlen);170 u32 limit = min(node->prefixlen, key->prefixlen);
170 u32 prefixlen = 0, i = 0;171 u32 prefixlen = 0, i = 0;
@@ -224,6 +225,13 @@ static size_t longest_prefix_match(const struct lpm_trie *trie, · 53 unmodified lines
224 return prefixlen;225 return prefixlen;
225}226}
226 227
228static size_t longest_prefix_match(const struct lpm_trie *trie,
229 const struct lpm_trie_node *node,
230 const struct bpf_lpm_trie_key_u8 *key)
231{
232 return __longest_prefix_match(trie, node, key);
233}
234
227/* Called from syscall or from eBPF program */235/* Called from syscall or from eBPF program */
228static void *trie_lookup_elem(struct bpf_map *map, void *_key)236static void *trie_lookup_elem(struct bpf_map *map, void *_key)
229{237{
@@ -245,7 +253,7 @@ static void *trie_lookup_elem(struct bpf_map *map, void *_key) · 15 unmodified lines
245 * If it's the maximum possible prefix for this trie, we have253 * If it's the maximum possible prefix for this trie, we have
246 * an exact match and can return it directly.254 * an exact match and can return it directly.
247 */255 */
248 matchlen = longest_prefix_match(trie, node, key);256 matchlen = __longest_prefix_match(trie, node, key);
249 if (matchlen == trie->max_prefixlen) {257 if (matchlen == trie->max_prefixlen) {
250 found = node;258 found = node;
251 break;259 break;
kernel/bpf/syscall.c+11−11
@@ -3469,17 +3469,12 @@ out_put_prog: · 3468 unmodified lines
3469 return err;3469 return err;
3470}3470}
3471 3471
3472struct bpf_raw_tp_link {
3473 struct bpf_link link;
3474 struct bpf_raw_event_map *btp;
3475};
3476
3477static void bpf_raw_tp_link_release(struct bpf_link *link)3472static void bpf_raw_tp_link_release(struct bpf_link *link)
3478{3473{
3479 struct bpf_raw_tp_link *raw_tp =3474 struct bpf_raw_tp_link *raw_tp =
3480 container_of(link, struct bpf_raw_tp_link, link);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 bpf_put_raw_tracepoint(raw_tp->btp);3478 bpf_put_raw_tracepoint(raw_tp->btp);
3484}3479}
3485 3480
@@ -3779,7 +3774,7 @@ static int bpf_perf_link_attach(const union bpf_attr *attr, struct bpf_prog *pro · 293 unmodified lines
3779#endif /* CONFIG_PERF_EVENTS */3774#endif /* CONFIG_PERF_EVENTS */
3780 3775
3781static int bpf_raw_tp_link_attach(struct bpf_prog *prog,3776static int bpf_raw_tp_link_attach(struct bpf_prog *prog,
3782 const char __user *user_tp_name)3777 const char __user *user_tp_name, u64 cookie)
3783{3778{
3784 struct bpf_link_primer link_primer;3779 struct bpf_link_primer link_primer;
3785 struct bpf_raw_tp_link *link;3780 struct bpf_raw_tp_link *link;
@@ -3826,6 +3821,7 @@ static int bpf_raw_tp_link_attach(struct bpf_prog *prog, · 40 unmodified lines
3826 bpf_link_init(&link->link, BPF_LINK_TYPE_RAW_TRACEPOINT,3821 bpf_link_init(&link->link, BPF_LINK_TYPE_RAW_TRACEPOINT,
3827 &bpf_raw_tp_link_lops, prog);3822 &bpf_raw_tp_link_lops, prog);
3828 link->btp = btp;3823 link->btp = btp;
3824 link->cookie = cookie;
3829 3825
3830 err = bpf_link_prime(&link->link, &link_primer);3826 err = bpf_link_prime(&link->link, &link_primer);
3831 if (err) {3827 if (err) {
@@ -3833,7 +3829,7 @@ static int bpf_raw_tp_link_attach(struct bpf_prog *prog, · 1 unmodified line
3833 goto out_put_btp;3829 goto out_put_btp;
3834 }3830 }
3835 3831
3836 err = bpf_probe_register(link->btp, prog);3832 err = bpf_probe_register(link->btp, link);
3837 if (err) {3833 if (err) {
3838 bpf_link_cleanup(&link_primer);3834 bpf_link_cleanup(&link_primer);
3839 goto out_put_btp;3835 goto out_put_btp;
@@ -3846,11 +3842,13 @@ out_put_btp: · 6 unmodified lines
3846 return err;3842 return err;
3847}3843}
3848 3844
3849#define BPF_RAW_TRACEPOINT_OPEN_LAST_FIELD raw_tracepoint.prog_fd3845#define BPF_RAW_TRACEPOINT_OPEN_LAST_FIELD raw_tracepoint.cookie
3850 3846
3851static int bpf_raw_tracepoint_open(const union bpf_attr *attr)3847static int bpf_raw_tracepoint_open(const union bpf_attr *attr)
3852{3848{
3853 struct bpf_prog *prog;3849 struct bpf_prog *prog;
3850 void __user *tp_name;
3851 __u64 cookie;
3854 int fd;3852 int fd;
3855 3853
3856 if (CHECK_ATTR(BPF_RAW_TRACEPOINT_OPEN))3854 if (CHECK_ATTR(BPF_RAW_TRACEPOINT_OPEN))
@@ -3860,7 +3858,9 @@ static int bpf_raw_tracepoint_open(const union bpf_attr *attr) · 3 unmodified lines
3860 if (IS_ERR(prog))3858 if (IS_ERR(prog))
3861 return PTR_ERR(prog);3859 return PTR_ERR(prog);
3862 3860
3863 fd = bpf_raw_tp_link_attach(prog, u64_to_user_ptr(attr->raw_tracepoint.name));3861 tp_name = u64_to_user_ptr(attr->raw_tracepoint.name);
3862 cookie = attr->raw_tracepoint.cookie;
3863 fd = bpf_raw_tp_link_attach(prog, tp_name, cookie);
3864 if (fd < 0)3864 if (fd < 0)
3865 bpf_prog_put(prog);3865 bpf_prog_put(prog);
3866 return fd;3866 return fd;
@@ -5198,7 +5198,7 @@ static int link_create(union bpf_attr *attr, bpfptr_t uattr) · 1331 unmodified lines
5198 goto out;5198 goto out;
5199 }5199 }
5200 if (prog->expected_attach_type == BPF_TRACE_RAW_TP)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 else if (prog->expected_attach_type == BPF_TRACE_ITER)5202 else if (prog->expected_attach_type == BPF_TRACE_ITER)
5203 ret = bpf_iter_link_attach(attr, uattr, prog);5203 ret = bpf_iter_link_attach(attr, uattr, prog);
5204 else if (prog->expected_attach_type == BPF_LSM_CGROUP)5204 else if (prog->expected_attach_type == BPF_LSM_CGROUP)
kernel/bpf/trampoline.c+5−10
@@ -456,7 +456,9 @@ again: · 455 unmodified lines
456 if (err < 0)456 if (err < 0)
457 goto out_free;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 WARN_ON(tr->cur_image && total == 0);463 WARN_ON(tr->cur_image && total == 0);
462 if (tr->cur_image)464 if (tr->cur_image)
@@ -1072,17 +1074,10 @@ void __weak arch_free_bpf_trampoline(void *image, unsigned int size) · 609 unmodified lines
1072 bpf_jit_free_exec(image);1074 bpf_jit_free_exec(image);
1073}1075}
1074 1076
1075void __weak arch_protect_bpf_trampoline(void *image, unsigned int size)1077int __weak arch_protect_bpf_trampoline(void *image, unsigned int size)
1076{
1077 WARN_ON_ONCE(size > PAGE_SIZE);
1078 set_memory_rox((long)image, 1);
1079}
1080
1081void __weak arch_unprotect_bpf_trampoline(void *image, unsigned int size)
1082{1078{
1083 WARN_ON_ONCE(size > PAGE_SIZE);1079 WARN_ON_ONCE(size > PAGE_SIZE);
1084 set_memory_nx((long)image, 1);1080 return set_memory_rox((long)image, 1);
1085 set_memory_rw((long)image, 1);
1086}1081}
1087 1082
1088int __weak arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags,1083int __weak arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags,
kernel/bpf/verifier.c+20−11
@@ -14544,7 +14544,19 @@ static void regs_refine_cond_op(struct bpf_reg_state *reg1, struct bpf_reg_state · 14543 unmodified lines
14544 struct tnum t;14544 struct tnum t;
14545 u64 val;14545 u64 val;
14546 14546
14547again: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 switch (opcode) {14560 switch (opcode) {
14549 case BPF_JEQ:14561 case BPF_JEQ:
14550 if (is_jmp32) {14562 if (is_jmp32) {
@@ -14687,14 +14699,6 @@ again: · 136 unmodified lines
14687 reg2->smin_value = max(reg1->smin_value + 1, reg2->smin_value);14699 reg2->smin_value = max(reg1->smin_value + 1, reg2->smin_value);
14688 }14700 }
14689 break;14701 break;
14690 case BPF_JGE:
14691 case BPF_JGT:
14692 case BPF_JSGE:
14693 case BPF_JSGT:
14694 /* just reuse LE/LT logic above */
14695 opcode = flip_opcode(opcode);
14696 swap(reg1, reg2);
14697 goto again;
14698 default:14702 default:
14699 return;14703 return;
14700 }14704 }
@@ -19158,6 +19162,7 @@ static int jit_subprogs(struct bpf_verifier_env *env) · 4457 unmodified lines
19158 if (bpf_prog_calc_tag(func[i]))19162 if (bpf_prog_calc_tag(func[i]))
19159 goto out_free;19163 goto out_free;
19160 func[i]->is_func = 1;19164 func[i]->is_func = 1;
19165 func[i]->sleepable = prog->sleepable;
19161 func[i]->aux->func_idx = i;19166 func[i]->aux->func_idx = i;
19162 /* Below members will be freed only at prog->aux */19167 /* Below members will be freed only at prog->aux */
19163 func[i]->aux->btf = prog->aux->btf;19168 func[i]->aux->btf = prog->aux->btf;
@@ -19262,10 +19267,14 @@ static int jit_subprogs(struct bpf_verifier_env *env) · 98 unmodified lines
19262 * bpf_prog_load will add the kallsyms for the main program.19267 * bpf_prog_load will add the kallsyms for the main program.
19263 */19268 */
19264 for (i = 1; i < env->subprog_cnt; i++) {19269 for (i = 1; i < env->subprog_cnt; i++) {
19265 bpf_prog_lock_ro(func[i]);19270 err = bpf_prog_lock_ro(func[i]);
19266 bpf_prog_kallsyms_add(func[i]);19271 if (err)
19272 goto out_free;
19267 }19273 }
19268 19274
19275 for (i = 1; i < env->subprog_cnt; i++)
19276 bpf_prog_kallsyms_add(func[i]);
19277
19269 /* Last step: make now unused interpreter insns from main19278 /* Last step: make now unused interpreter insns from main
19270 * prog consistent for later dump requests, so they can19279 * prog consistent for later dump requests, so they can
19271 * later look the same as if they were interpreted only.19280 * later look the same as if they were interpreted only.
kernel/trace/bpf_trace.c+32−20
@@ -1053,9 +1053,15 @@ static unsigned long get_entry_ip(unsigned long fentry_ip) · 1052 unmodified lines
1053{1053{
1054 u32 instr;1054 u32 instr;
1055 1055
1056 /* Being extra safe in here in case entry ip is on the page-edge. */1056 /* We want to be extra safe in case entry ip is on the page edge,
1057 if (get_kernel_nofault(instr, (u32 *) fentry_ip - 1))1057 * but otherwise we need to avoid get_kernel_nofault()'s overhead.
1058 return fentry_ip;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 if (is_endbr(instr))1065 if (is_endbr(instr))
1060 fentry_ip -= ENDBR_INSN_SIZE;1066 fentry_ip -= ENDBR_INSN_SIZE;
1061 return fentry_ip;1067 return fentry_ip;
@@ -1525,8 +1531,6 @@ bpf_tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) · 463 unmodified lines
1525 return &bpf_ktime_get_boot_ns_proto;1531 return &bpf_ktime_get_boot_ns_proto;
1526 case BPF_FUNC_tail_call:1532 case BPF_FUNC_tail_call:
1527 return &bpf_tail_call_proto;1533 return &bpf_tail_call_proto;
1528 case BPF_FUNC_get_current_pid_tgid:
1529 return &bpf_get_current_pid_tgid_proto;
1530 case BPF_FUNC_get_current_task:1534 case BPF_FUNC_get_current_task:
1531 return &bpf_get_current_task_proto;1535 return &bpf_get_current_task_proto;
1532 case BPF_FUNC_get_current_task_btf:1536 case BPF_FUNC_get_current_task_btf:
@@ -1582,8 +1586,6 @@ bpf_tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) · 49 unmodified lines
1582 return &bpf_send_signal_thread_proto;1586 return &bpf_send_signal_thread_proto;
1583 case BPF_FUNC_perf_event_read_value:1587 case BPF_FUNC_perf_event_read_value:
1584 return &bpf_perf_event_read_value_proto;1588 return &bpf_perf_event_read_value_proto;
1585 case BPF_FUNC_get_ns_current_pid_tgid:
1586 return &bpf_get_ns_current_pid_tgid_proto;
1587 case BPF_FUNC_ringbuf_output:1589 case BPF_FUNC_ringbuf_output:
1588 return &bpf_ringbuf_output_proto;1590 return &bpf_ringbuf_output_proto;
1589 case BPF_FUNC_ringbuf_reserve:1591 case BPF_FUNC_ringbuf_reserve:
@@ -2008,6 +2010,8 @@ raw_tp_prog_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) · 418 unmodified lines
2008 return &bpf_get_stackid_proto_raw_tp;2010 return &bpf_get_stackid_proto_raw_tp;
2009 case BPF_FUNC_get_stack:2011 case BPF_FUNC_get_stack:
2010 return &bpf_get_stack_proto_raw_tp;2012 return &bpf_get_stack_proto_raw_tp;
2013 case BPF_FUNC_get_attach_cookie:
2014 return &bpf_get_attach_cookie_proto_tracing;
2011 default:2015 default:
2012 return bpf_tracing_func_proto(func_id, prog);2016 return bpf_tracing_func_proto(func_id, prog);
2013 }2017 }
@@ -2070,6 +2074,9 @@ tracing_prog_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) · 56 unmodified lines
2070 case BPF_FUNC_get_func_arg_cnt:2074 case BPF_FUNC_get_func_arg_cnt:
2071 return bpf_prog_has_trampoline(prog) ? &bpf_get_func_arg_cnt_proto : NULL;2075 return bpf_prog_has_trampoline(prog) ? &bpf_get_func_arg_cnt_proto : NULL;
2072 case BPF_FUNC_get_attach_cookie:2076 case BPF_FUNC_get_attach_cookie:
2077 if (prog->type == BPF_PROG_TYPE_TRACING &&
2078 prog->expected_attach_type == BPF_TRACE_RAW_TP)
2079 return &bpf_get_attach_cookie_proto_tracing;
2073 return bpf_prog_has_trampoline(prog) ? &bpf_get_attach_cookie_proto_tracing : NULL;2080 return bpf_prog_has_trampoline(prog) ? &bpf_get_attach_cookie_proto_tracing : NULL;
2074 default:2081 default:
2075 fn = raw_tp_prog_func_proto(func_id, prog);2082 fn = raw_tp_prog_func_proto(func_id, prog);
@@ -2370,16 +2377,26 @@ void bpf_put_raw_tracepoint(struct bpf_raw_event_map *btp) · 294 unmodified lines
2370}2377}
2371 2378
2372static __always_inline2379static __always_inline
2373void __bpf_trace_run(struct bpf_prog *prog, u64 *args)2380void __bpf_trace_run(struct bpf_raw_tp_link *link, u64 *args)
2374{2381{
2382 struct bpf_prog *prog = link->link.prog;
2383 struct bpf_run_ctx *old_run_ctx;
2384 struct bpf_trace_run_ctx run_ctx;
2385
2375 cant_sleep();2386 cant_sleep();
2376 if (unlikely(this_cpu_inc_return(*(prog->active)) != 1)) {2387 if (unlikely(this_cpu_inc_return(*(prog->active)) != 1)) {
2377 bpf_prog_inc_misses_counter(prog);2388 bpf_prog_inc_misses_counter(prog);
2378 goto out;2389 goto out;
2379 }2390 }
2391
2392 run_ctx.bpf_cookie = link->cookie;
2393 old_run_ctx = bpf_set_run_ctx(&run_ctx.run_ctx);
2394
2380 rcu_read_lock();2395 rcu_read_lock();
2381 (void) bpf_prog_run(prog, args);2396 (void) bpf_prog_run(prog, args);
2382 rcu_read_unlock();2397 rcu_read_unlock();
2398
2399 bpf_reset_run_ctx(old_run_ctx);
2383out:2400out:
2384 this_cpu_dec(*(prog->active));2401 this_cpu_dec(*(prog->active));
2385}2402}
@@ -2408,12 +2425,12 @@ out: · 22 unmodified lines
2408#define __SEQ_0_11 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 112425#define __SEQ_0_11 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
2409 2426
2410#define BPF_TRACE_DEFN_x(x) \2427#define BPF_TRACE_DEFN_x(x) \
2411 void bpf_trace_run##x(struct bpf_prog *prog, \2428 void bpf_trace_run##x(struct bpf_raw_tp_link *link, \
2412 REPEAT(x, SARG, __DL_COM, __SEQ_0_11)) \2429 REPEAT(x, SARG, __DL_COM, __SEQ_0_11)) \
2413 { \2430 { \
2414 u64 args[x]; \2431 u64 args[x]; \
2415 REPEAT(x, COPY, __DL_SEM, __SEQ_0_11); \2432 REPEAT(x, COPY, __DL_SEM, __SEQ_0_11); \
2416 __bpf_trace_run(prog, args); \2433 __bpf_trace_run(link, args); \
2417 } \2434 } \
2418 EXPORT_SYMBOL_GPL(bpf_trace_run##x)2435 EXPORT_SYMBOL_GPL(bpf_trace_run##x)
2419BPF_TRACE_DEFN_x(1);2436BPF_TRACE_DEFN_x(1);
@@ -2429,9 +2446,10 @@ BPF_TRACE_DEFN_x(10); · 9 unmodified lines
2429BPF_TRACE_DEFN_x(11);2446BPF_TRACE_DEFN_x(11);
2430BPF_TRACE_DEFN_x(12);2447BPF_TRACE_DEFN_x(12);
2431 2448
2432static int __bpf_probe_register(struct bpf_raw_event_map *btp, struct bpf_prog *prog)2449int bpf_probe_register(struct bpf_raw_event_map *btp, struct bpf_raw_tp_link *link)
2433{2450{
2434 struct tracepoint *tp = btp->tp;2451 struct tracepoint *tp = btp->tp;
2452 struct bpf_prog *prog = link->link.prog;
2435 2453
2436 /*2454 /*
2437 * check that program doesn't access arguments beyond what's2455 * check that program doesn't access arguments beyond what's
@@ -2443,18 +2461,12 @@ static int __bpf_probe_register(struct bpf_raw_event_map *btp, struct bpf_prog * · 5 unmodified lines
2443 if (prog->aux->max_tp_access > btp->writable_size)2461 if (prog->aux->max_tp_access > btp->writable_size)
2444 return -EINVAL;2462 return -EINVAL;
2445 2463
2446 return tracepoint_probe_register_may_exist(tp, (void *)btp->bpf_func,2464 return tracepoint_probe_register_may_exist(tp, (void *)btp->bpf_func, link);
2447 prog);
2448}
2449
2450int bpf_probe_register(struct bpf_raw_event_map *btp, struct bpf_prog *prog)
2451{
2452 return __bpf_probe_register(btp, prog);
2453}2465}
2454 2466
2455int bpf_probe_unregister(struct bpf_raw_event_map *btp, struct bpf_prog *prog)2467int bpf_probe_unregister(struct bpf_raw_event_map *btp, struct bpf_raw_tp_link *link)
2456{2468{
2457 return tracepoint_probe_unregister(btp->tp, (void *)btp->bpf_func, prog);2469 return tracepoint_probe_unregister(btp->tp, (void *)btp->bpf_func, link);
2458}2470}
2459 2471
2460int bpf_get_perf_event_info(const struct perf_event *event, u32 *prog_id,2472int bpf_get_perf_event_info(const struct perf_event *event, u32 *prog_id,
net/bpf/bpf_dummy_struct_ops.c+3−1
@@ -133,7 +133,9 @@ int bpf_struct_ops_test_run(struct bpf_prog *prog, const union bpf_attr *kattr, · 132 unmodified lines
133 if (err < 0)133 if (err < 0)
134 goto out;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 prog_ret = dummy_ops_call_op(image, args);139 prog_ret = dummy_ops_call_op(image, args);
138 140
139 err = dummy_ops_copy_args(args);141 err = dummy_ops_copy_args(args);
net/core/filter.c+0−2
@@ -8342,8 +8342,6 @@ sk_msg_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) · 8341 unmodified lines
8342 return &bpf_event_output_data_proto;8342 return &bpf_event_output_data_proto;
8343 case BPF_FUNC_get_current_uid_gid:8343 case BPF_FUNC_get_current_uid_gid:
8344 return &bpf_get_current_uid_gid_proto;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 case BPF_FUNC_sk_storage_get:8345 case BPF_FUNC_sk_storage_get:
8348 return &bpf_sk_storage_get_proto;8346 return &bpf_sk_storage_get_proto;
8349 case BPF_FUNC_sk_storage_delete:8347 case BPF_FUNC_sk_storage_delete:
tools/bpf/bpftool/Makefile+6−8
@@ -89,6 +89,10 @@ ifneq ($(EXTRA_LDFLAGS),) · 88 unmodified lines
89LDFLAGS += $(EXTRA_LDFLAGS)89LDFLAGS += $(EXTRA_LDFLAGS)
90endif90endif
91 91
92HOST_CFLAGS := $(subst -I$(LIBBPF_INCLUDE),-I$(LIBBPF_BOOTSTRAP_INCLUDE),\
93 $(subst $(CLANG_CROSS_FLAGS),,$(CFLAGS)))
94HOST_LDFLAGS := $(LDFLAGS)
95
92INSTALL ?= install96INSTALL ?= install
93RM ?= rm -f97RM ?= rm -f
94 98
@@ -178,12 +182,9 @@ ifeq ($(filter -DHAVE_LLVM_SUPPORT -DHAVE_LIBBFD_SUPPORT,$(CFLAGS)),) · 83 unmodified lines
178 SRCS := $(filter-out jit_disasm.c,$(SRCS))182 SRCS := $(filter-out jit_disasm.c,$(SRCS))
179endif183endif
180 184
181HOST_CFLAGS = $(subst -I$(LIBBPF_INCLUDE),-I$(LIBBPF_BOOTSTRAP_INCLUDE),\
182 $(subst $(CLANG_CROSS_FLAGS),,$(CFLAGS)))
183
184BPFTOOL_BOOTSTRAP := $(BOOTSTRAP_OUTPUT)bpftool185BPFTOOL_BOOTSTRAP := $(BOOTSTRAP_OUTPUT)bpftool
185 186
186BOOTSTRAP_OBJS = $(addprefix $(BOOTSTRAP_OUTPUT),main.o common.o json_writer.o gen.o btf.o xlated_dumper.o btf_dumper.o disasm.o)187BOOTSTRAP_OBJS = $(addprefix $(BOOTSTRAP_OUTPUT),main.o common.o json_writer.o gen.o btf.o)
187$(BOOTSTRAP_OBJS): $(LIBBPF_BOOTSTRAP)188$(BOOTSTRAP_OBJS): $(LIBBPF_BOOTSTRAP)
188 189
189OBJS = $(patsubst %.c,$(OUTPUT)%.o,$(SRCS)) $(OUTPUT)disasm.o190OBJS = $(patsubst %.c,$(OUTPUT)%.o,$(SRCS)) $(OUTPUT)disasm.o
@@ -231,14 +232,11 @@ endif · 41 unmodified lines
231 232
232CFLAGS += $(if $(BUILD_BPF_SKELS),,-DBPFTOOL_WITHOUT_SKELETONS)233CFLAGS += $(if $(BUILD_BPF_SKELS),,-DBPFTOOL_WITHOUT_SKELETONS)
233 234
234$(BOOTSTRAP_OUTPUT)disasm.o: $(srctree)/kernel/bpf/disasm.c
235 $(QUIET_CC)$(HOSTCC) $(HOST_CFLAGS) -c -MMD $< -o $@
236
237$(OUTPUT)disasm.o: $(srctree)/kernel/bpf/disasm.c235$(OUTPUT)disasm.o: $(srctree)/kernel/bpf/disasm.c
238 $(QUIET_CC)$(CC) $(CFLAGS) -c -MMD $< -o $@236 $(QUIET_CC)$(CC) $(CFLAGS) -c -MMD $< -o $@
239 237
240$(BPFTOOL_BOOTSTRAP): $(BOOTSTRAP_OBJS) $(LIBBPF_BOOTSTRAP)238$(BPFTOOL_BOOTSTRAP): $(BOOTSTRAP_OBJS) $(LIBBPF_BOOTSTRAP)
241 $(QUIET_LINK)$(HOSTCC) $(HOST_CFLAGS) $(LDFLAGS) $(BOOTSTRAP_OBJS) $(LIBS_BOOTSTRAP) -o $@239 $(QUIET_LINK)$(HOSTCC) $(HOST_CFLAGS) $(HOST_LDFLAGS) $(BOOTSTRAP_OBJS) $(LIBS_BOOTSTRAP) -o $@
242 240
243$(OUTPUT)bpftool: $(OBJS) $(LIBBPF)241$(OUTPUT)bpftool: $(OBJS) $(LIBBPF)
244 $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) -o $@242 $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) -o $@
tools/bpf/bpftool/gen.c+2−1
@@ -1131,7 +1131,8 @@ static void gen_st_ops_shadow_init(struct btf *btf, struct bpf_object *obj) · 1130 unmodified lines
1131 continue;1131 continue;
1132 codegen("\1132 codegen("\
1133 \n\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 \n\1136 \n\
1136 ", ident);1137 ", ident);
1137 }1138 }
tools/bpf/bpftool/pids.c+12−7
@@ -101,7 +101,6 @@ int build_obj_refs_table(struct hashmap **map, enum bpf_obj_type type) · 100 unmodified lines
101 char buf[4096 / sizeof(*e) * sizeof(*e)];101 char buf[4096 / sizeof(*e) * sizeof(*e)];
102 struct pid_iter_bpf *skel;102 struct pid_iter_bpf *skel;
103 int err, ret, fd = -1, i;103 int err, ret, fd = -1, i;
104 libbpf_print_fn_t default_print;
105 104
106 *map = hashmap__new(hash_fn_for_key_as_id, equal_fn_for_key_as_id, NULL);105 *map = hashmap__new(hash_fn_for_key_as_id, equal_fn_for_key_as_id, NULL);
107 if (IS_ERR(*map)) {106 if (IS_ERR(*map)) {
@@ -118,12 +117,18 @@ int build_obj_refs_table(struct hashmap **map, enum bpf_obj_type type) · 10 unmodified lines
118 117
119 skel->rodata->obj_type = type;118 skel->rodata->obj_type = type;
120 119
121 /* we don't want output polluted with libbpf errors if bpf_iter is not120 if (!verifier_logs) {
122 * supported121 libbpf_print_fn_t default_print;
123 */122
124 default_print = libbpf_set_print(libbpf_print_none);123 /* Unless debug information is on, we don't want the output to
125 err = pid_iter_bpf__load(skel);124 * be polluted with libbpf errors if bpf_iter is not supported.
126 libbpf_set_print(default_print);125 */
126 default_print = libbpf_set_print(libbpf_print_none);
127 err = pid_iter_bpf__load(skel);
128 libbpf_set_print(default_print);
129 } else {
130 err = pid_iter_bpf__load(skel);
131 }
127 if (err) {132 if (err) {
128 /* too bad, kernel doesn't support BPF iterators yet */133 /* too bad, kernel doesn't support BPF iterators yet */
129 err = 0;134 err = 0;
tools/bpf/bpftool/skeleton/pid_iter.bpf.c+2−2
@@ -102,8 +102,8 @@ int iter(struct bpf_iter__task_file *ctx) · 101 unmodified lines
102 BPF_LINK_TYPE_PERF_EVENT___local)) {102 BPF_LINK_TYPE_PERF_EVENT___local)) {
103 struct bpf_link *link = (struct bpf_link *) file->private_data;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,105 if (BPF_CORE_READ(link, type) == bpf_core_enum_value(enum bpf_link_type___local,
106 BPF_LINK_TYPE_PERF_EVENT___local)) {106 BPF_LINK_TYPE_PERF_EVENT___local)) {
107 e.has_bpf_cookie = true;107 e.has_bpf_cookie = true;
108 e.bpf_cookie = get_bpf_cookie(link);108 e.bpf_cookie = get_bpf_cookie(link);
109 }109 }
tools/include/linux/compiler.h+4−0
@@ -58,6 +58,10 @@ · 57 unmodified lines
58#define noinline58#define noinline
59#endif59#endif
60 60
61#ifndef __nocf_check
62#define __nocf_check __attribute__((nocf_check))
63#endif
64
61/* Are two types/vars the same type (ignoring qualifiers)? */65/* Are two types/vars the same type (ignoring qualifiers)? */
62#ifndef __same_type66#ifndef __same_type
63# define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))67# define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
tools/include/uapi/linux/bpf.h+4−2
@@ -1662,8 +1662,10 @@ union bpf_attr { · 1661 unmodified lines
1662 } query;1662 } query;
1663 1663
1664 struct { /* anonymous struct used by BPF_RAW_TRACEPOINT_OPEN command */1664 struct { /* anonymous struct used by BPF_RAW_TRACEPOINT_OPEN command */
1665 __u64 name;1665 __u64 name;
1666 __u32 prog_fd;1666 __u32 prog_fd;
1667 __u32 :32;
1668 __aligned_u64 cookie;
1667 } raw_tracepoint;1669 } raw_tracepoint;
1668 1670
1669 struct { /* anonymous struct for BPF_BTF_LOAD */1671 struct { /* anonymous struct for BPF_BTF_LOAD */
tools/lib/bpf/bpf.c+14−2
@@ -785,6 +785,7 @@ int bpf_link_create(int prog_fd, int target_fd, · 784 unmodified lines
785 if (!OPTS_ZEROED(opts, uprobe_multi))785 if (!OPTS_ZEROED(opts, uprobe_multi))
786 return libbpf_err(-EINVAL);786 return libbpf_err(-EINVAL);
787 break;787 break;
788 case BPF_TRACE_RAW_TP:
788 case BPF_TRACE_FENTRY:789 case BPF_TRACE_FENTRY:
789 case BPF_TRACE_FEXIT:790 case BPF_TRACE_FEXIT:
790 case BPF_MODIFY_RETURN:791 case BPF_MODIFY_RETURN:
@@ -1173,20 +1174,31 @@ int bpf_link_get_info_by_fd(int link_fd, struct bpf_link_info *info, __u32 *info · 382 unmodified lines
1173 return bpf_obj_get_info_by_fd(link_fd, info, info_len);1174 return bpf_obj_get_info_by_fd(link_fd, info, info_len);
1174}1175}
1175 1176
1176int bpf_raw_tracepoint_open(const char *name, int prog_fd)1177int bpf_raw_tracepoint_open_opts(int prog_fd, struct bpf_raw_tp_opts *opts)
1177{1178{
1178 const size_t attr_sz = offsetofend(union bpf_attr, raw_tracepoint);1179 const size_t attr_sz = offsetofend(union bpf_attr, raw_tracepoint);
1179 union bpf_attr attr;1180 union bpf_attr attr;
1180 int fd;1181 int fd;
1181 1182
1183 if (!OPTS_VALID(opts, bpf_raw_tp_opts))
1184 return libbpf_err(-EINVAL);
1185
1182 memset(&attr, 0, attr_sz);1186 memset(&attr, 0, attr_sz);
1183 attr.raw_tracepoint.name = ptr_to_u64(name);
1184 attr.raw_tracepoint.prog_fd = prog_fd;1187 attr.raw_tracepoint.prog_fd = prog_fd;
1188 attr.raw_tracepoint.name = ptr_to_u64(OPTS_GET(opts, tp_name, NULL));
1189 attr.raw_tracepoint.cookie = OPTS_GET(opts, cookie, 0);
1185 1190
1186 fd = sys_bpf_fd(BPF_RAW_TRACEPOINT_OPEN, &attr, attr_sz);1191 fd = sys_bpf_fd(BPF_RAW_TRACEPOINT_OPEN, &attr, attr_sz);
1187 return libbpf_err_errno(fd);1192 return libbpf_err_errno(fd);
1188}1193}
1189 1194
1195int bpf_raw_tracepoint_open(const char *name, int prog_fd)
1196{
1197 LIBBPF_OPTS(bpf_raw_tp_opts, opts, .tp_name = name);
1198
1199 return bpf_raw_tracepoint_open_opts(prog_fd, &opts);
1200}
1201
1190int bpf_btf_load(const void *btf_data, size_t btf_size, struct bpf_btf_load_opts *opts)1202int bpf_btf_load(const void *btf_data, size_t btf_size, struct bpf_btf_load_opts *opts)
1191{1203{
1192 const size_t attr_sz = offsetofend(union bpf_attr, btf_token_fd);1204 const size_t attr_sz = offsetofend(union bpf_attr, btf_token_fd);
tools/lib/bpf/bpf.h+9−0
@@ -617,6 +617,15 @@ LIBBPF_API int bpf_prog_query(int target_fd, enum bpf_attach_type type, · 616 unmodified lines
617 __u32 query_flags, __u32 *attach_flags,617 __u32 query_flags, __u32 *attach_flags,
618 __u32 *prog_ids, __u32 *prog_cnt);618 __u32 *prog_ids, __u32 *prog_cnt);
619 619
620struct 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
628LIBBPF_API int bpf_raw_tracepoint_open_opts(int prog_fd, struct bpf_raw_tp_opts *opts);
620LIBBPF_API int bpf_raw_tracepoint_open(const char *name, int prog_fd);629LIBBPF_API int bpf_raw_tracepoint_open(const char *name, int prog_fd);
621LIBBPF_API int bpf_task_fd_query(int pid, int fd, __u32 flags, char *buf,630LIBBPF_API int bpf_task_fd_query(int pid, int fd, __u32 flags, char *buf,
622 __u32 *buf_len, __u32 *prog_id, __u32 *fd_type,631 __u32 *buf_len, __u32 *prog_id, __u32 *fd_type,
tools/lib/bpf/libbpf.c+92−19
@@ -1132,8 +1132,26 @@ static int bpf_map__init_kern_struct_ops(struct bpf_map *map) · 1131 unmodified lines
1132 const char *mname;1132 const char *mname;
1133 1133
1134 mname = btf__name_by_offset(btf, member->name_off);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 kern_member = find_member_by_name(kern_btf, kern_type, mname);1144 kern_member = find_member_by_name(kern_btf, kern_type, mname);
1136 if (!kern_member) {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 pr_warn("struct_ops init_kern %s: Cannot find member %s in kernel BTF\n",1155 pr_warn("struct_ops init_kern %s: Cannot find member %s in kernel BTF\n",
1138 map->name, mname);1156 map->name, mname);
1139 return -ENOTSUP;1157 return -ENOTSUP;
@@ -1147,10 +1165,7 @@ static int bpf_map__init_kern_struct_ops(struct bpf_map *map) · 7 unmodified lines
1147 return -ENOTSUP;1165 return -ENOTSUP;
1148 }1166 }
1149 1167
1150 moff = member->offset / 8;
1151 kern_moff = kern_member->offset / 8;1168 kern_moff = kern_member->offset / 8;
1152
1153 mdata = data + moff;
1154 kern_mdata = kern_data + kern_moff;1169 kern_mdata = kern_data + kern_moff;
1155 1170
1156 mtype = skip_mods_and_typedefs(btf, member->type, &mtype_id);1171 mtype = skip_mods_and_typedefs(btf, member->type, &mtype_id);
@@ -1230,9 +1245,8 @@ static int bpf_map__init_kern_struct_ops(struct bpf_map *map) · 73 unmodified lines
1230 continue;1245 continue;
1231 }1246 }
1232 1247
1233 msize = btf__resolve_size(btf, mtype_id);
1234 kern_msize = btf__resolve_size(kern_btf, kern_mtype_id);1248 kern_msize = btf__resolve_size(kern_btf, kern_mtype_id);
1235 if (msize < 0 || kern_msize < 0 || msize != kern_msize) {1249 if (kern_msize < 0 || msize != kern_msize) {
1236 pr_warn("struct_ops init_kern %s: Error in size of member %s: %zd != %zd(kernel)\n",1250 pr_warn("struct_ops init_kern %s: Error in size of member %s: %zd != %zd(kernel)\n",
1237 map->name, mname, (ssize_t)msize,1251 map->name, mname, (ssize_t)msize,
1238 (ssize_t)kern_msize);1252 (ssize_t)kern_msize);
@@ -7317,9 +7331,9 @@ static int bpf_object_load_prog(struct bpf_object *obj, struct bpf_program *prog · 6078 unmodified lines
7317 char *cp, errmsg[STRERR_BUFSIZE];7331 char *cp, errmsg[STRERR_BUFSIZE];
7318 size_t log_buf_size = 0;7332 size_t log_buf_size = 0;
7319 char *log_buf = NULL, *tmp;7333 char *log_buf = NULL, *tmp;
7320 int btf_fd, ret, err;
7321 bool own_log_buf = true;7334 bool own_log_buf = true;
7322 __u32 log_level = prog->log_level;7335 __u32 log_level = prog->log_level;
7336 int ret, err;
7323 7337
7324 if (prog->type == BPF_PROG_TYPE_UNSPEC) {7338 if (prog->type == BPF_PROG_TYPE_UNSPEC) {
7325 /*7339 /*
@@ -7343,9 +7357,8 @@ static int bpf_object_load_prog(struct bpf_object *obj, struct bpf_program *prog · 17 unmodified lines
7343 load_attr.prog_ifindex = prog->prog_ifindex;7357 load_attr.prog_ifindex = prog->prog_ifindex;
7344 7358
7345 /* specify func_info/line_info only if kernel supports them */7359 /* specify func_info/line_info only if kernel supports them */
7346 btf_fd = btf__fd(obj->btf);7360 if (obj->btf && btf__fd(obj->btf) >= 0 && kernel_supports(obj, FEAT_BTF_FUNC)) {
7347 if (btf_fd >= 0 && kernel_supports(obj, FEAT_BTF_FUNC)) {7361 load_attr.prog_btf_fd = btf__fd(obj->btf);
7348 load_attr.prog_btf_fd = btf_fd;
7349 load_attr.func_info = prog->func_info;7362 load_attr.func_info = prog->func_info;
7350 load_attr.func_info_rec_size = prog->func_info_rec_size;7363 load_attr.func_info_rec_size = prog->func_info_rec_size;
7351 load_attr.func_info_cnt = prog->func_info_cnt;7364 load_attr.func_info_cnt = prog->func_info_cnt;
@@ -8559,6 +8572,11 @@ int bpf_map__pin(struct bpf_map *map, const char *path) · 1207 unmodified lines
8559 return libbpf_err(-EINVAL);8572 return libbpf_err(-EINVAL);
8560 }8573 }
8561 8574
8575 if (map->fd < 0) {
8576 pr_warn("map '%s': can't pin BPF map without FD (was it created?)\n", map->name);
8577 return libbpf_err(-EINVAL);
8578 }
8579
8562 if (map->pin_path) {8580 if (map->pin_path) {
8563 if (path && strcmp(path, map->pin_path)) {8581 if (path && strcmp(path, map->pin_path)) {
8564 pr_warn("map '%s' already has pin path '%s' different from '%s'\n",8582 pr_warn("map '%s' already has pin path '%s' different from '%s'\n",
@@ -9294,6 +9312,7 @@ static const struct bpf_sec_def section_defs[] = { · 729 unmodified lines
9294 SEC_DEF("sockops", SOCK_OPS, BPF_CGROUP_SOCK_OPS, SEC_ATTACHABLE_OPT),9312 SEC_DEF("sockops", SOCK_OPS, BPF_CGROUP_SOCK_OPS, SEC_ATTACHABLE_OPT),
9295 SEC_DEF("sk_skb/stream_parser", SK_SKB, BPF_SK_SKB_STREAM_PARSER, SEC_ATTACHABLE_OPT),9313 SEC_DEF("sk_skb/stream_parser", SK_SKB, BPF_SK_SKB_STREAM_PARSER, SEC_ATTACHABLE_OPT),
9296 SEC_DEF("sk_skb/stream_verdict",SK_SKB, BPF_SK_SKB_STREAM_VERDICT, SEC_ATTACHABLE_OPT),9314 SEC_DEF("sk_skb/stream_verdict",SK_SKB, BPF_SK_SKB_STREAM_VERDICT, SEC_ATTACHABLE_OPT),
9315 SEC_DEF("sk_skb/verdict", SK_SKB, BPF_SK_SKB_VERDICT, SEC_ATTACHABLE_OPT),
9297 SEC_DEF("sk_skb", SK_SKB, 0, SEC_NONE),9316 SEC_DEF("sk_skb", SK_SKB, 0, SEC_NONE),
9298 SEC_DEF("sk_msg", SK_MSG, BPF_SK_MSG_VERDICT, SEC_ATTACHABLE_OPT),9317 SEC_DEF("sk_msg", SK_MSG, BPF_SK_MSG_VERDICT, SEC_ATTACHABLE_OPT),
9299 SEC_DEF("lirc_mode2", LIRC_MODE2, BPF_LIRC_MODE2, SEC_ATTACHABLE_OPT),9318 SEC_DEF("lirc_mode2", LIRC_MODE2, BPF_LIRC_MODE2, SEC_ATTACHABLE_OPT),
@@ -10303,6 +10322,11 @@ static int validate_map_op(const struct bpf_map *map, size_t key_sz, · 1003 unmodified lines
10303 return -EINVAL;10322 return -EINVAL;
10304 }10323 }
10305 10324
10325 if (map->fd < 0) {
10326 pr_warn("map '%s': can't use BPF map without FD (was it created?)\n", map->name);
10327 return -EINVAL;
10328 }
10329
10306 if (!check_value_sz)10330 if (!check_value_sz)
10307 return 0;10331 return 0;
10308 10332
@@ -10415,8 +10439,15 @@ long libbpf_get_error(const void *ptr) · 106 unmodified lines
10415int bpf_link__update_program(struct bpf_link *link, struct bpf_program *prog)10439int bpf_link__update_program(struct bpf_link *link, struct bpf_program *prog)
10416{10440{
10417 int ret;10441 int ret;
10442 int prog_fd = bpf_program__fd(prog);
10418 10443
10419 ret = bpf_link_update(bpf_link__fd(link), bpf_program__fd(prog), NULL);10444 if (prog_fd < 0) {
10445 pr_warn("prog '%s': can't use BPF program without FD (was it loaded?)\n",
10446 prog->name);
10447 return libbpf_err(-EINVAL);
10448 }
10449
10450 ret = bpf_link_update(bpf_link__fd(link), prog_fd, NULL);
10420 return libbpf_err_errno(ret);10451 return libbpf_err_errno(ret);
10421}10452}
10422 10453
@@ -10610,7 +10641,7 @@ struct bpf_link *bpf_program__attach_perf_event_opts(const struct bpf_program *p · 187 unmodified lines
10610 }10641 }
10611 prog_fd = bpf_program__fd(prog);10642 prog_fd = bpf_program__fd(prog);
10612 if (prog_fd < 0) {10643 if (prog_fd < 0) {
10613 pr_warn("prog '%s': can't attach BPF program w/o FD (did you load it?)\n",10644 pr_warn("prog '%s': can't attach BPF program without FD (was it loaded?)\n",
10614 prog->name);10645 prog->name);
10615 return libbpf_err_ptr(-EINVAL);10646 return libbpf_err_ptr(-EINVAL);
10616 }10647 }
@@ -11334,6 +11365,13 @@ bpf_program__attach_kprobe_multi_opts(const struct bpf_program *prog, · 717 unmodified lines
11334 if (!OPTS_VALID(opts, bpf_kprobe_multi_opts))11365 if (!OPTS_VALID(opts, bpf_kprobe_multi_opts))
11335 return libbpf_err_ptr(-EINVAL);11366 return libbpf_err_ptr(-EINVAL);
11336 11367
11368 prog_fd = bpf_program__fd(prog);
11369 if (prog_fd < 0) {
11370 pr_warn("prog '%s': can't attach BPF program without FD (was it loaded?)\n",
11371 prog->name);
11372 return libbpf_err_ptr(-EINVAL);
11373 }
11374
11337 syms = OPTS_GET(opts, syms, false);11375 syms = OPTS_GET(opts, syms, false);
11338 addrs = OPTS_GET(opts, addrs, false);11376 addrs = OPTS_GET(opts, addrs, false);
11339 cnt = OPTS_GET(opts, cnt, false);11377 cnt = OPTS_GET(opts, cnt, false);
@@ -11374,7 +11412,6 @@ bpf_program__attach_kprobe_multi_opts(const struct bpf_program *prog, · 34 unmodified lines
11374 }11412 }
11375 link->detach = &bpf_link__detach_fd;11413 link->detach = &bpf_link__detach_fd;
11376 11414
11377 prog_fd = bpf_program__fd(prog);
11378 link_fd = bpf_link_create(prog_fd, 0, BPF_TRACE_KPROBE_MULTI, &lopts);11415 link_fd = bpf_link_create(prog_fd, 0, BPF_TRACE_KPROBE_MULTI, &lopts);
11379 if (link_fd < 0) {11416 if (link_fd < 0) {
11380 err = -errno;11417 err = -errno;
@@ -11757,6 +11794,13 @@ bpf_program__attach_uprobe_multi(const struct bpf_program *prog, · 376 unmodified lines
11757 if (!OPTS_VALID(opts, bpf_uprobe_multi_opts))11794 if (!OPTS_VALID(opts, bpf_uprobe_multi_opts))
11758 return libbpf_err_ptr(-EINVAL);11795 return libbpf_err_ptr(-EINVAL);
11759 11796
11797 prog_fd = bpf_program__fd(prog);
11798 if (prog_fd < 0) {
11799 pr_warn("prog '%s': can't attach BPF program without FD (was it loaded?)\n",
11800 prog->name);
11801 return libbpf_err_ptr(-EINVAL);
11802 }
11803
11760 syms = OPTS_GET(opts, syms, NULL);11804 syms = OPTS_GET(opts, syms, NULL);
11761 offsets = OPTS_GET(opts, offsets, NULL);11805 offsets = OPTS_GET(opts, offsets, NULL);
11762 ref_ctr_offsets = OPTS_GET(opts, ref_ctr_offsets, NULL);11806 ref_ctr_offsets = OPTS_GET(opts, ref_ctr_offsets, NULL);
@@ -11832,7 +11876,6 @@ bpf_program__attach_uprobe_multi(const struct bpf_program *prog, · 69 unmodified lines
11832 }11876 }
11833 link->detach = &bpf_link__detach_fd;11877 link->detach = &bpf_link__detach_fd;
11834 11878
11835 prog_fd = bpf_program__fd(prog);
11836 link_fd = bpf_link_create(prog_fd, 0, BPF_TRACE_UPROBE_MULTI, &lopts);11879 link_fd = bpf_link_create(prog_fd, 0, BPF_TRACE_UPROBE_MULTI, &lopts);
11837 if (link_fd < 0) {11880 if (link_fd < 0) {
11838 err = -errno;11881 err = -errno;
@@ -12076,7 +12119,7 @@ struct bpf_link *bpf_program__attach_usdt(const struct bpf_program *prog, · 237 unmodified lines
12076 return libbpf_err_ptr(-EINVAL);12119 return libbpf_err_ptr(-EINVAL);
12077 12120
12078 if (bpf_program__fd(prog) < 0) {12121 if (bpf_program__fd(prog) < 0) {
12079 pr_warn("prog '%s': can't attach BPF program w/o FD (did you load it?)\n",12122 pr_warn("prog '%s': can't attach BPF program without FD (was it loaded?)\n",
12080 prog->name);12123 prog->name);
12081 return libbpf_err_ptr(-EINVAL);12124 return libbpf_err_ptr(-EINVAL);
12082 }12125 }
@@ -12267,13 +12310,19 @@ static int attach_tp(const struct bpf_program *prog, long cookie, struct bpf_lin · 184 unmodified lines
12267 return libbpf_get_error(*link);12310 return libbpf_get_error(*link);
12268}12311}
12269 12312
12270struct bpf_link *bpf_program__attach_raw_tracepoint(const struct bpf_program *prog,12313struct bpf_link *
12271 const char *tp_name)12314bpf_program__attach_raw_tracepoint_opts(const struct bpf_program *prog,
12315 const char *tp_name,
12316 struct bpf_raw_tracepoint_opts *opts)
12272{12317{
12318 LIBBPF_OPTS(bpf_raw_tp_opts, raw_opts);
12273 char errmsg[STRERR_BUFSIZE];12319 char errmsg[STRERR_BUFSIZE];
12274 struct bpf_link *link;12320 struct bpf_link *link;
12275 int prog_fd, pfd;12321 int prog_fd, pfd;
12276 12322
12323 if (!OPTS_VALID(opts, bpf_raw_tracepoint_opts))
12324 return libbpf_err_ptr(-EINVAL);
12325
12277 prog_fd = bpf_program__fd(prog);12326 prog_fd = bpf_program__fd(prog);
12278 if (prog_fd < 0) {12327 if (prog_fd < 0) {
12279 pr_warn("prog '%s': can't attach before loaded\n", prog->name);12328 pr_warn("prog '%s': can't attach before loaded\n", prog->name);
@@ -12285,7 +12334,9 @@ struct bpf_link *bpf_program__attach_raw_tracepoint(const struct bpf_program *pr · 5 unmodified lines
12285 return libbpf_err_ptr(-ENOMEM);12334 return libbpf_err_ptr(-ENOMEM);
12286 link->detach = &bpf_link__detach_fd;12335 link->detach = &bpf_link__detach_fd;
12287 12336
12288 pfd = bpf_raw_tracepoint_open(tp_name, prog_fd);12337 raw_opts.tp_name = tp_name;
12338 raw_opts.cookie = OPTS_GET(opts, cookie, 0);
12339 pfd = bpf_raw_tracepoint_open_opts(prog_fd, &raw_opts);
12289 if (pfd < 0) {12340 if (pfd < 0) {
12290 pfd = -errno;12341 pfd = -errno;
12291 free(link);12342 free(link);
@@ -12297,6 +12348,12 @@ struct bpf_link *bpf_program__attach_raw_tracepoint(const struct bpf_program *pr · 5 unmodified lines
12297 return link;12348 return link;
12298}12349}
12299 12350
12351struct bpf_link *bpf_program__attach_raw_tracepoint(const struct bpf_program *prog,
12352 const char *tp_name)
12353{
12354 return bpf_program__attach_raw_tracepoint_opts(prog, tp_name, NULL);
12355}
12356
12300static int attach_raw_tp(const struct bpf_program *prog, long cookie, struct bpf_link **link)12357static int attach_raw_tp(const struct bpf_program *prog, long cookie, struct bpf_link **link)
12301{12358{
12302 static const char *const prefixes[] = {12359 static const char *const prefixes[] = {
@@ -12658,6 +12715,12 @@ struct bpf_link *bpf_program__attach(const struct bpf_program *prog) · 355 unmodified lines
12658 if (!prog->sec_def || !prog->sec_def->prog_attach_fn)12715 if (!prog->sec_def || !prog->sec_def->prog_attach_fn)
12659 return libbpf_err_ptr(-EOPNOTSUPP);12716 return libbpf_err_ptr(-EOPNOTSUPP);
12660 12717
12718 if (bpf_program__fd(prog) < 0) {
12719 pr_warn("prog '%s': can't attach BPF program without FD (was it loaded?)\n",
12720 prog->name);
12721 return libbpf_err_ptr(-EINVAL);
12722 }
12723
12661 err = prog->sec_def->prog_attach_fn(prog, prog->sec_def->cookie, &link);12724 err = prog->sec_def->prog_attach_fn(prog, prog->sec_def->cookie, &link);
12662 if (err)12725 if (err)
12663 return libbpf_err_ptr(err);12726 return libbpf_err_ptr(err);
@@ -12698,8 +12761,13 @@ struct bpf_link *bpf_map__attach_struct_ops(const struct bpf_map *map) · 34 unmodified lines
12698 __u32 zero = 0;12761 __u32 zero = 0;
12699 int err, fd;12762 int err, fd;
12700 12763
12701 if (!bpf_map__is_struct_ops(map) || map->fd == -1)12764 if (!bpf_map__is_struct_ops(map))
12765 return libbpf_err_ptr(-EINVAL);
12766
12767 if (map->fd < 0) {
12768 pr_warn("map '%s': can't attach BPF map without FD (was it created?)\n", map->name);
12702 return libbpf_err_ptr(-EINVAL);12769 return libbpf_err_ptr(-EINVAL);
12770 }
12703 12771
12704 link = calloc(1, sizeof(*link));12772 link = calloc(1, sizeof(*link));
12705 if (!link)12773 if (!link)
@@ -12747,9 +12815,14 @@ int bpf_link__update_map(struct bpf_link *link, const struct bpf_map *map) · 41 unmodified lines
12747 __u32 zero = 0;12815 __u32 zero = 0;
12748 int err;12816 int err;
12749 12817
12750 if (!bpf_map__is_struct_ops(map) || !map_is_created(map))12818 if (!bpf_map__is_struct_ops(map))
12751 return -EINVAL;12819 return -EINVAL;
12752 12820
12821 if (map->fd < 0) {
12822 pr_warn("map '%s': can't use BPF map without FD (was it created?)\n", map->name);
12823 return -EINVAL;
12824 }
12825
12753 st_ops_link = container_of(link, struct bpf_link_struct_ops, link);12826 st_ops_link = container_of(link, struct bpf_link_struct_ops, link);
12754 /* Ensure the type of a link is correct */12827 /* Ensure the type of a link is correct */
12755 if (st_ops_link->map_fd < 0)12828 if (st_ops_link->map_fd < 0)
tools/lib/bpf/libbpf.h+11−0
@@ -760,9 +760,20 @@ bpf_program__attach_tracepoint_opts(const struct bpf_program *prog, · 759 unmodified lines
760 const char *tp_name,760 const char *tp_name,
761 const struct bpf_tracepoint_opts *opts);761 const struct bpf_tracepoint_opts *opts);
762 762
763struct 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
763LIBBPF_API struct bpf_link *770LIBBPF_API struct bpf_link *
764bpf_program__attach_raw_tracepoint(const struct bpf_program *prog,771bpf_program__attach_raw_tracepoint(const struct bpf_program *prog,
765 const char *tp_name);772 const char *tp_name);
773LIBBPF_API struct bpf_link *
774bpf_program__attach_raw_tracepoint_opts(const struct bpf_program *prog,
775 const char *tp_name,
776 struct bpf_raw_tracepoint_opts *opts);
766 777
767struct bpf_trace_opts {778struct bpf_trace_opts {
768 /* size of this struct, for forward/backward compatibility */779 /* size of this struct, for forward/backward compatibility */
tools/lib/bpf/libbpf.map+2−0
@@ -410,6 +410,8 @@ LIBBPF_1.3.0 { · 409 unmodified lines
410 410
411LIBBPF_1.4.0 {411LIBBPF_1.4.0 {
412 global:412 global:
413 bpf_program__attach_raw_tracepoint_opts;
414 bpf_raw_tracepoint_open_opts;
413 bpf_token_create;415 bpf_token_create;
414 btf__new_split;416 btf__new_split;
415 btf_ext__raw_data;417 btf_ext__raw_data;
tools/testing/selftests/bpf/benchs/bench_local_storage_create.c+1−1
@@ -186,7 +186,7 @@ static void *task_producer(void *input) · 185 unmodified lines
186 186
187 for (i = 0; i < batch_sz; i++) {187 for (i = 0; i < batch_sz; i++) {
188 if (!pthd_results[i])188 if (!pthd_results[i])
189 pthread_join(pthds[i], NULL);;189 pthread_join(pthds[i], NULL);
190 }190 }
191 }191 }
192 192
tools/testing/selftests/bpf/benchs/bench_trigger.c+40−8
@@ -1,15 +1,47 @@
1// SPDX-License-Identifier: GPL-2.01// SPDX-License-Identifier: GPL-2.0
2/* Copyright (c) 2020 Facebook */2/* Copyright (c) 2020 Facebook */
3#define _GNU_SOURCE
4#include <unistd.h>
3#include "bench.h"5#include "bench.h"
4#include "trigger_bench.skel.h"6#include "trigger_bench.skel.h"
5#include "trace_helpers.h"7#include "trace_helpers.h"
6 8
9/* adjust slot shift in inc_hits() if changing */
10#define MAX_BUCKETS 256
11
12#pragma GCC diagnostic ignored "-Wattributes"
13
7/* BPF triggering benchmarks */14/* BPF triggering benchmarks */
8static struct trigger_ctx {15static struct trigger_ctx {
9 struct trigger_bench *skel;16 struct trigger_bench *skel;
10} ctx;17} ctx;
11 18
12static struct counter base_hits;19static struct counter base_hits[MAX_BUCKETS];
20
21static __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
36static 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
14static void trigger_validate(void)46static void trigger_validate(void)
15{47{
@@ -23,14 +55,14 @@ static void *trigger_base_producer(void *input) · 7 unmodified lines
23{55{
24 while (true) {56 while (true) {
25 (void)syscall(__NR_getpgid);57 (void)syscall(__NR_getpgid);
26 atomic_inc(&base_hits.value);58 inc_counter(base_hits);
27 }59 }
28 return NULL;60 return NULL;
29}61}
30 62
31static void trigger_base_measure(struct bench_res *res)63static void trigger_base_measure(struct bench_res *res)
32{64{
33 res->hits = atomic_swap(&base_hits.value, 0);65 res->hits = sum_and_reset_counters(base_hits);
34}66}
35 67
36static void *trigger_producer(void *input)68static void *trigger_producer(void *input)
@@ -42,7 +74,7 @@ static void *trigger_producer(void *input) · 5 unmodified lines
42 74
43static void trigger_measure(struct bench_res *res)75static void trigger_measure(struct bench_res *res)
44{76{
45 res->hits = atomic_swap(&ctx.skel->bss->hits, 0);77 res->hits = sum_and_reset_counters(ctx.skel->bss->hits);
46}78}
47 79
48static void setup_ctx(void)80static void setup_ctx(void)
@@ -137,7 +169,7 @@ static void trigger_fmodret_setup(void) · 88 unmodified lines
137 * GCC doesn't generate stack setup preample for these functions due to them169 * GCC doesn't generate stack setup preample for these functions due to them
138 * having no input arguments and doing nothing in the body.170 * having no input arguments and doing nothing in the body.
139 */171 */
140__weak void uprobe_target_nop(void)172__nocf_check __weak void uprobe_target_nop(void)
141{173{
142 asm volatile ("nop");174 asm volatile ("nop");
143}175}
@@ -146,7 +178,7 @@ __weak void opaque_noop_func(void) · 2 unmodified lines
146{178{
147}179}
148 180
149__weak int uprobe_target_push(void)181__nocf_check __weak int uprobe_target_push(void)
150{182{
151 /* overhead of function call is negligible compared to uprobe183 /* overhead of function call is negligible compared to uprobe
152 * triggering, so this shouldn't affect benchmark results much184 * triggering, so this shouldn't affect benchmark results much
@@ -155,7 +187,7 @@ __weak int uprobe_target_push(void) · 2 unmodified lines
155 return 1;187 return 1;
156}188}
157 189
158__weak void uprobe_target_ret(void)190__nocf_check __weak void uprobe_target_ret(void)
159{191{
160 asm volatile ("");192 asm volatile ("");
161}193}
@@ -164,7 +196,7 @@ static void *uprobe_base_producer(void *input) · 2 unmodified lines
164{196{
165 while (true) {197 while (true) {
166 uprobe_target_nop();198 uprobe_target_nop();
167 atomic_inc(&base_hits.value);199 inc_counter(base_hits);
168 }200 }
169 return NULL;201 return NULL;
170}202}
tools/testing/selftests/bpf/prog_tests/bpf_cookie.c+113−1
@@ -573,6 +573,115 @@ cleanup: · 572 unmodified lines
573 close(lsm_fd);573 close(lsm_fd);
574}574}
575 575
576static 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
632cleanup:
633 if (link_fd >= 0)
634 close(link_fd);
635 bpf_link__destroy(link);
636}
637
638static 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
679cleanup:
680 if (link_fd >= 0)
681 close(link_fd);
682 bpf_link__destroy(link);
683}
684
576void test_bpf_cookie(void)685void test_bpf_cookie(void)
577{686{
578 struct test_bpf_cookie *skel;687 struct test_bpf_cookie *skel;
@@ -601,6 +710,9 @@ void test_bpf_cookie(void) · 22 unmodified lines
601 tracing_subtest(skel);710 tracing_subtest(skel);
602 if (test__start_subtest("lsm"))711 if (test__start_subtest("lsm"))
603 lsm_subtest(skel);712 lsm_subtest(skel);
604 713 if (test__start_subtest("tp_btf"))
714 tp_btf_subtest(skel);
715 if (test__start_subtest("raw_tp"))
716 raw_tp_subtest(skel);
605 test_bpf_cookie__destroy(skel);717 test_bpf_cookie__destroy(skel);
606}718}
tools/testing/selftests/bpf/prog_tests/bpf_tcp_ca.c+1−12
@@ -89,7 +89,7 @@ static void do_test(const char *tcp_ca, const struct bpf_map *sk_stg_map) · 88 unmodified lines
89 89
90 WRITE_ONCE(stop, 0);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 if (!ASSERT_NEQ(lfd, -1, "socket"))93 if (!ASSERT_NEQ(lfd, -1, "socket"))
94 return;94 return;
95 95
@@ -103,21 +103,10 @@ static void do_test(const char *tcp_ca, const struct bpf_map *sk_stg_map) · 7 unmodified lines
103 settimeo(lfd, 0) || settimeo(fd, 0))103 settimeo(lfd, 0) || settimeo(fd, 0))
104 goto done;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 err = getsockname(lfd, (struct sockaddr *)&sa6, &addrlen);106 err = getsockname(lfd, (struct sockaddr *)&sa6, &addrlen);
114 if (!ASSERT_NEQ(err, -1, "getsockname"))107 if (!ASSERT_NEQ(err, -1, "getsockname"))
115 goto done;108 goto done;
116 109
117 err = listen(lfd, 1);
118 if (!ASSERT_NEQ(err, -1, "listen"))
119 goto done;
120
121 if (sk_stg_map) {110 if (sk_stg_map) {
122 err = bpf_map_update_elem(bpf_map__fd(sk_stg_map), &fd,111 err = bpf_map_update_elem(bpf_map__fd(sk_stg_map), &fd,
123 &expected_stg, BPF_NOEXIST);112 &expected_stg, BPF_NOEXIST);
tools/testing/selftests/bpf/prog_tests/btf_map_in_map.c+1−25
@@ -25,7 +25,7 @@ static void test_lookup_update(void) · 24 unmodified lines
25 int map1_fd, map2_fd, map3_fd, map4_fd, map5_fd, map1_id, map2_id;25 int map1_fd, map2_fd, map3_fd, map4_fd, map5_fd, map1_id, map2_id;
26 int outer_arr_fd, outer_hash_fd, outer_arr_dyn_fd;26 int outer_arr_fd, outer_hash_fd, outer_arr_dyn_fd;
27 struct test_btf_map_in_map *skel;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 skel = test_btf_map_in_map__open_and_load();30 skel = test_btf_map_in_map__open_and_load();
31 if (CHECK(!skel, "skel_open", "failed to open&load skeleton\n"))31 if (CHECK(!skel, "skel_open", "failed to open&load skeleton\n"))
@@ -102,30 +102,6 @@ static void test_lookup_update(void) · 70 unmodified lines
102 CHECK(map1_id == 0, "map1_id", "failed to get ID 1\n");102 CHECK(map1_id == 0, "map1_id", "failed to get ID 1\n");
103 CHECK(map2_id == 0, "map2_id", "failed to get ID 2\n");103 CHECK(map2_id == 0, "map2_id", "failed to get ID 2\n");
104 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
129cleanup:105cleanup:
130 test_btf_map_in_map__destroy(skel);106 test_btf_map_in_map__destroy(skel);
131}107}
tools/testing/selftests/bpf/prog_tests/ns_current_pid_tgid.c+183−31
@@ -12,77 +12,229 @@ · 11 unmodified lines
12#include <sys/wait.h>12#include <sys/wait.h>
13#include <sys/mount.h>13#include <sys/mount.h>
14#include <sys/fcntl.h>14#include <sys/fcntl.h>
15#include "network_helpers.h"
15 16
16#define STACK_SIZE (1024 * 1024)17#define STACK_SIZE (1024 * 1024)
17static char child_stack[STACK_SIZE];18static char child_stack[STACK_SIZE];
18 19
19static int test_current_pid_tgid(void *args)20static 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 struct stat st;23 struct stat st;
24 int err;
26 25
27 skel = test_ns_current_pid_tgid__open_and_load();26 *pid = syscall(SYS_gettid);
28 if (CHECK(!skel, "skel_open_load", "failed to load skeleton\n"))27 *tgid = getpid();
29 goto cleanup;
30
31 pid = syscall(SYS_gettid);
32 tgid = getpid();
33 28
34 err = stat("/proc/self/ns/pid", &st);29 err = stat("/proc/self/ns/pid", &st);
35 if (CHECK(err, "stat", "failed /proc/self/ns/pid: %d\n", err))30 if (!ASSERT_OK(err, "stat /proc/self/ns/pid"))
36 goto cleanup;31 return err;
37 32
38 bss = skel->bss;
39 bss->dev = st.st_dev;33 bss->dev = st.st_dev;
40 bss->ino = st.st_ino;34 bss->ino = st.st_ino;
41 bss->user_pid = 0;35 bss->user_pid = 0;
42 bss->user_tgid = 0;36 bss->user_tgid = 0;
37 return 0;
38}
39
40static 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 err = test_ns_current_pid_tgid__attach(skel);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 goto cleanup;63 goto cleanup;
47 64
48 /* trigger tracepoint */65 /* trigger tracepoint */
49 usleep(1);66 usleep(1);
50 ASSERT_EQ(bss->user_pid, pid, "pid");67 if (!ASSERT_EQ(bss->user_pid, pid, "pid"))
51 ASSERT_EQ(bss->user_tgid, tgid, "tgid");68 goto cleanup;
52 err = 0;69 if (!ASSERT_EQ(bss->user_tgid, tgid, "tgid"))
70 goto cleanup;
71 ret = 0;
72
73cleanup:
74 test_ns_current_pid_tgid__destroy(skel);
75 return ret;
76}
77
78static int test_current_pid_tgid_cgrp(void *args)
79{
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;
53 114
54cleanup:115cleanup:
55 test_ns_current_pid_tgid__destroy(skel);116 if (server_fd >= 0)
117 close(server_fd);
118 test_ns_current_pid_tgid__destroy(skel);
119 return ret;
120}
121
122static 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;
56 154
57 return err;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
173cleanup:
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;
58}180}
59 181
60static void test_ns_current_pid_tgid_new_ns(void)182static void test_ns_current_pid_tgid_new_ns(int (*fn)(void *), void *arg)
61{183{
62 int wstatus, duration = 0;184 int wstatus;
63 pid_t cpid;185 pid_t cpid;
64 186
65 /* Create a process in a new namespace, this process187 /* Create a process in a new namespace, this process
66 * will be the init process of this new namespace hence will be pid 1.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,190 cpid = clone(fn, child_stack + STACK_SIZE,
69 CLONE_NEWPID | SIGCHLD, NULL);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 return;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 return;197 return;
76 198
77 if (CHECK(WEXITSTATUS(wstatus) != 0, "newns_pidtgid", "failed"))199 if (!ASSERT_OK(WEXITSTATUS(wstatus), "newns_pidtgid"))
78 return;200 return;
79}201}
80 202
203static 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
216cleanup:
217 if (nstoken)
218 close_netns(nstoken);
219 SYS_NOFAIL("ip netns del ns_current_pid_tgid");
220}
221
81/* TODO: use a different tracepoint */222/* TODO: use a different tracepoint */
82void serial_test_ns_current_pid_tgid(void)223void serial_test_ns_current_pid_tgid(void)
83{224{
84 if (test__start_subtest("ns_current_pid_tgid_root_ns"))225 if (test__start_subtest("root_ns_tp"))
85 test_current_pid_tgid(NULL);226 test_current_pid_tgid_tp(NULL);
86 if (test__start_subtest("ns_current_pid_tgid_new_ns"))227 if (test__start_subtest("new_ns_tp"))
87 test_ns_current_pid_tgid_new_ns();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}
tools/testing/selftests/bpf/prog_tests/test_struct_ops_module.c+47−0
@@ -93,9 +93,56 @@ cleanup: · 92 unmodified lines
93 struct_ops_module__destroy(skel);93 struct_ops_module__destroy(skel);
94}94}
95 95
96static 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
96void serial_test_struct_ops_module(void)141void serial_test_struct_ops_module(void)
97{142{
98 if (test__start_subtest("test_struct_ops_load"))143 if (test__start_subtest("test_struct_ops_load"))
99 test_struct_ops_load();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
tools/testing/selftests/bpf/progs/iters.c+1−1
@@ -673,7 +673,7 @@ static __noinline void fill(struct bpf_iter_num *it, int *arr, __u32 n, int mul) · 672 unmodified lines
673 673
674static __noinline int sum(struct bpf_iter_num *it, int *arr, __u32 n)674static __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 while ((t = bpf_iter_num_next(it))) {678 while ((t = bpf_iter_num_next(it))) {
679 i = *t;679 i = *t;
tools/testing/selftests/bpf/progs/struct_ops_module.c+15−1
@@ -23,7 +23,7 @@ void BPF_PROG(test_2, int a, int b) · 22 unmodified lines
23 test_2_result = a + b;23 test_2_result = a + b;
24}24}
25 25
26SEC("struct_ops/test_3")26SEC("?struct_ops/test_3")
27int BPF_PROG(test_3, int a, int b)27int BPF_PROG(test_3, int a, int b)
28{28{
29 test_2_result = a + b + 3;29 test_2_result = a + b + 3;
@@ -54,3 +54,17 @@ struct bpf_testmod_ops___v2 testmod_2 = { · 24 unmodified lines
54 .test_1 = (void *)test_1,54 .test_1 = (void *)test_1,
55 .test_2 = (void *)test_2_v2,55 .test_2 = (void *)test_2_v2,
56};56};
57
58struct 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
66SEC(".struct_ops.link")
67struct bpf_testmod_ops___zeroed testmod_zeroed = {
68 .test_1 = (void *)test_1,
69 .test_2 = (void *)test_2_v2,
70};
tools/testing/selftests/bpf/progs/test_bpf_cookie.c+16−0
@@ -15,6 +15,8 @@ __u64 uprobe_res; · 14 unmodified lines
15__u64 uretprobe_res;15__u64 uretprobe_res;
16__u64 tp_res;16__u64 tp_res;
17__u64 pe_res;17__u64 pe_res;
18__u64 raw_tp_res;
19__u64 tp_btf_res;
18__u64 fentry_res;20__u64 fentry_res;
19__u64 fexit_res;21__u64 fexit_res;
20__u64 fmod_ret_res;22__u64 fmod_ret_res;
@@ -87,6 +89,20 @@ int handle_pe(struct pt_regs *ctx) · 66 unmodified lines
87 return 0;89 return 0;
88}90}
89 91
92SEC("raw_tp/sys_enter")
93int handle_raw_tp(void *ctx)
94{
95 update(ctx, &raw_tp_res);
96 return 0;
97}
98
99SEC("tp_btf/sys_enter")
100int handle_tp_btf(void *ctx)
101{
102 update(ctx, &tp_btf_res);
103 return 0;
104}
105
90SEC("fentry/bpf_fentry_test1")106SEC("fentry/bpf_fentry_test1")
91int BPF_PROG(fentry_test1, int a)107int BPF_PROG(fentry_test1, int a)
92{108{
tools/testing/selftests/bpf/progs/test_ns_current_pid_tgid.c+28−3
@@ -5,23 +5,48 @@ · 4 unmodified lines
5#include <stdint.h>5#include <stdint.h>
6#include <bpf/bpf_helpers.h>6#include <bpf/bpf_helpers.h>
7 7
8struct {
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__u64 user_pid = 0;15__u64 user_pid = 0;
9__u64 user_tgid = 0;16__u64 user_tgid = 0;
10__u64 dev = 0;17__u64 dev = 0;
11__u64 ino = 0;18__u64 ino = 0;
12 19
13SEC("tracepoint/syscalls/sys_enter_nanosleep")20static void get_pid_tgid(void)
14int handler(const void *ctx)
15{21{
16 struct bpf_pidns_info nsdata;22 struct bpf_pidns_info nsdata;
17 23
18 if (bpf_get_ns_current_pid_tgid(dev, ino, &nsdata, sizeof(struct bpf_pidns_info)))24 if (bpf_get_ns_current_pid_tgid(dev, ino, &nsdata, sizeof(struct bpf_pidns_info)))
19 return 0;25 return;
20 26
21 user_pid = nsdata.pid;27 user_pid = nsdata.pid;
22 user_tgid = nsdata.tgid;28 user_tgid = nsdata.tgid;
29}
23 30
31SEC("?tracepoint/syscalls/sys_enter_nanosleep")
32int tp_handler(const void *ctx)
33{
34 get_pid_tgid();
24 return 0;35 return 0;
25}36}
26 37
38SEC("?cgroup/bind4")
39int cgroup_bind4(struct bpf_sock_addr *ctx)
40{
41 get_pid_tgid();
42 return 1;
43}
44
45SEC("?sk_msg")
46int sk_msg(struct sk_msg_md *msg)
47{
48 get_pid_tgid();
49 return SK_PASS;
50}
51
27char _license[] SEC("license") = "GPL";52char _license[] SEC("license") = "GPL";
tools/testing/selftests/bpf/progs/trigger_bench.c+27−12
@@ -9,12 +9,27 @@ · 8 unmodified lines
9 9
10char _license[] SEC("license") = "GPL";10char _license[] SEC("license") = "GPL";
11 11
12long 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 */
16struct counter {
17 long value;
18} __attribute__((aligned(128)));
19
20struct counter hits[MAX_CPUS];
21
22static __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
14SEC("tp/syscalls/sys_enter_getpgid")29SEC("tp/syscalls/sys_enter_getpgid")
15int bench_trigger_tp(void *ctx)30int bench_trigger_tp(void *ctx)
16{31{
17 __sync_add_and_fetch(&hits, 1);32 inc_counter();
18 return 0;33 return 0;
19}34}
20 35
@@ -22,69 +37,69 @@ SEC("raw_tp/sys_enter") · 1 unmodified line
22int BPF_PROG(bench_trigger_raw_tp, struct pt_regs *regs, long id)37int BPF_PROG(bench_trigger_raw_tp, struct pt_regs *regs, long id)
23{38{
24 if (id == __NR_getpgid)39 if (id == __NR_getpgid)
25 __sync_add_and_fetch(&hits, 1);40 inc_counter();
26 return 0;41 return 0;
27}42}
28 43
29SEC("kprobe/" SYS_PREFIX "sys_getpgid")44SEC("kprobe/" SYS_PREFIX "sys_getpgid")
30int bench_trigger_kprobe(void *ctx)45int bench_trigger_kprobe(void *ctx)
31{46{
32 __sync_add_and_fetch(&hits, 1);47 inc_counter();
33 return 0;48 return 0;
34}49}
35 50
36SEC("kretprobe/" SYS_PREFIX "sys_getpgid")51SEC("kretprobe/" SYS_PREFIX "sys_getpgid")
37int bench_trigger_kretprobe(void *ctx)52int bench_trigger_kretprobe(void *ctx)
38{53{
39 __sync_add_and_fetch(&hits, 1);54 inc_counter();
40 return 0;55 return 0;
41}56}
42 57
43SEC("kprobe.multi/" SYS_PREFIX "sys_getpgid")58SEC("kprobe.multi/" SYS_PREFIX "sys_getpgid")
44int bench_trigger_kprobe_multi(void *ctx)59int bench_trigger_kprobe_multi(void *ctx)
45{60{
46 __sync_add_and_fetch(&hits, 1);61 inc_counter();
47 return 0;62 return 0;
48}63}
49 64
50SEC("kretprobe.multi/" SYS_PREFIX "sys_getpgid")65SEC("kretprobe.multi/" SYS_PREFIX "sys_getpgid")
51int bench_trigger_kretprobe_multi(void *ctx)66int bench_trigger_kretprobe_multi(void *ctx)
52{67{
53 __sync_add_and_fetch(&hits, 1);68 inc_counter();
54 return 0;69 return 0;
55}70}
56 71
57SEC("fentry/" SYS_PREFIX "sys_getpgid")72SEC("fentry/" SYS_PREFIX "sys_getpgid")
58int bench_trigger_fentry(void *ctx)73int bench_trigger_fentry(void *ctx)
59{74{
60 __sync_add_and_fetch(&hits, 1);75 inc_counter();
61 return 0;76 return 0;
62}77}
63 78
64SEC("fexit/" SYS_PREFIX "sys_getpgid")79SEC("fexit/" SYS_PREFIX "sys_getpgid")
65int bench_trigger_fexit(void *ctx)80int bench_trigger_fexit(void *ctx)
66{81{
67 __sync_add_and_fetch(&hits, 1);82 inc_counter();
68 return 0;83 return 0;
69}84}
70 85
71SEC("fentry.s/" SYS_PREFIX "sys_getpgid")86SEC("fentry.s/" SYS_PREFIX "sys_getpgid")
72int bench_trigger_fentry_sleep(void *ctx)87int bench_trigger_fentry_sleep(void *ctx)
73{88{
74 __sync_add_and_fetch(&hits, 1);89 inc_counter();
75 return 0;90 return 0;
76}91}
77 92
78SEC("fmod_ret/" SYS_PREFIX "sys_getpgid")93SEC("fmod_ret/" SYS_PREFIX "sys_getpgid")
79int bench_trigger_fmodret(void *ctx)94int bench_trigger_fmodret(void *ctx)
80{95{
81 __sync_add_and_fetch(&hits, 1);96 inc_counter();
82 return -22;97 return -22;
83}98}
84 99
85SEC("uprobe")100SEC("uprobe")
86int bench_trigger_uprobe(void *ctx)101int bench_trigger_uprobe(void *ctx)
87{102{
88 __sync_add_and_fetch(&hits, 1);103 inc_counter();
89 return 0;104 return 0;
90}105}
tools/testing/selftests/bpf/test_cpp.cpp+5−0
@@ -7,6 +7,7 @@ · 6 unmodified lines
7#include <bpf/bpf.h>7#include <bpf/bpf.h>
8#include <bpf/btf.h>8#include <bpf/btf.h>
9#include "test_core_extern.skel.h"9#include "test_core_extern.skel.h"
10#include "struct_ops_module.skel.h"
10 11
11template <typename T>12template <typename T>
12class Skeleton {13class Skeleton {
@@ -98,6 +99,7 @@ int main(int argc, char *argv[]) · 85 unmodified lines
98{99{
99 struct btf_dump_opts opts = { };100 struct btf_dump_opts opts = { };
100 struct test_core_extern *skel;101 struct test_core_extern *skel;
102 struct struct_ops_module *skel2;
101 struct btf *btf;103 struct btf *btf;
102 int fd;104 int fd;
103 105
@@ -118,6 +120,9 @@ int main(int argc, char *argv[]) · 14 unmodified lines
118 skel = test_core_extern__open_and_load();120 skel = test_core_extern__open_and_load();
119 test_core_extern__destroy(skel);121 test_core_extern__destroy(skel);
120 122
123 skel2 = struct_ops_module__open_and_load();
124 struct_ops_module__destroy(skel2);
125
121 fd = bpf_enable_stats(BPF_STATS_RUN_TIME);126 fd = bpf_enable_stats(BPF_STATS_RUN_TIME);
122 if (fd < 0)127 if (fd < 0)
123 std::cout << "FAILED to enable stats: " << fd << std::endl;128 std::cout << "FAILED to enable stats: " << fd << std::endl;
tools/testing/selftests/bpf/test_tc_tunnel.sh+12−1
@@ -72,7 +72,6 @@ cleanup() { · 71 unmodified lines
72server_listen() {72server_listen() {
73 ip netns exec "${ns2}" nc "${netcat_opt}" -l "${port}" > "${outfile}" &73 ip netns exec "${ns2}" nc "${netcat_opt}" -l "${port}" > "${outfile}" &
74 server_pid=$!74 server_pid=$!
75 sleep 0.2
76}75}
77 76
78client_connect() {77client_connect() {
@@ -93,6 +92,16 @@ verify_data() { · 14 unmodified lines
93 fi92 fi
94}93}
95 94
95wait_for_port() {
96 for i in $(seq 20); do
97 if ip netns exec "${ns2}" ss ${2:--4}OHntl | grep -q "$1"; then
98 return 0
99 fi
100 sleep 0.1
101 done
102 return 1
103}
104
96set -e105set -e
97 106
98# no arguments: automated test, run all107# no arguments: automated test, run all
@@ -193,6 +202,7 @@ setup · 94 unmodified lines
193# basic communication works202# basic communication works
194echo "test basic connectivity"203echo "test basic connectivity"
195server_listen204server_listen
205wait_for_port ${port} ${netcat_opt}
196client_connect206client_connect
197verify_data207verify_data
198 208
@@ -204,6 +214,7 @@ ip netns exec "${ns1}" tc filter add dev veth1 egress \ · 5 unmodified lines
204 section "encap_${tuntype}_${mac}"214 section "encap_${tuntype}_${mac}"
205echo "test bpf encap without decap (expect failure)"215echo "test bpf encap without decap (expect failure)"
206server_listen216server_listen
217wait_for_port ${port} ${netcat_opt}
207! client_connect218! client_connect
208 219
209if [[ "$tuntype" =~ "udp" ]]; then220if [[ "$tuntype" =~ "udp" ]]; then