History

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

Alexei Starovoitov says: ==================== pull-request: bpf-next 2021-12-30 The following pull-request contains BPF updates for your *net-next* tree. We've added 72 non-merge commits during the last 20 day(s) which contain a total of 223 files changed, 3510 insertions(+), 1591 deletions(-). The main changes are: 1) Automatic setrlimit in libbpf when bpf is memcg's in the kernel, from Andrii. 2) Beautify and de-verbose verifier logs, from Christy. 3) Composable verifier types, from Hao. 4) bpf_strncmp helper, from Hou. 5) bpf.h header dependency cleanup, from Jakub. 6) get_func_[arg|ret|arg_cnt] helpers, from Jiri. 7) Sleepable local storage, from KP. 8) Extend kfunc with PTR_TO_CTX, PTR_TO_MEM argument support, from Kumar. ====================

David S. Miller committed 4 years ago

Commit e63a0232 parents ce2b6eb 9e6b19a221 files · +3506 −1591Browse files

Showing the changes to tools (65 of 221 files). Show all

Unified · Split

65 files
  1. tools/bpf/bpftool/Makefile +7 −6
  2. tools/bpf/bpftool/feature.c +23 −3
  3. tools/bpf/bpftool/main.c +2 −0
  4. tools/bpf/resolve_btfids/Makefile +1 −0
  5. tools/bpf/runqslower/Makefile +2 −2
  6. tools/include/uapi/linux/bpf.h +39 −0
  7. tools/lib/bpf/Makefile +2 −1
  8. tools/lib/bpf/bpf.c +83 −2
  9. tools/lib/bpf/bpf.h +2 −0
  10. tools/lib/bpf/bpf_tracing.h +174 −257
  11. tools/lib/bpf/btf.h +6 −0
  12. tools/lib/bpf/btf_dump.c +2 −2
  13. tools/lib/bpf/gen_loader.c +5 −6
  14. tools/lib/bpf/libbpf.c +41 −44
  15. tools/lib/bpf/libbpf.h +73 −4
  16. tools/lib/bpf/libbpf.map +4 −0
  17. tools/lib/bpf/libbpf_internal.h +60 −0
  18. tools/lib/bpf/libbpf_legacy.h +11 −1
  19. tools/lib/bpf/libbpf_probes.c +185 −66
  20. tools/lib/bpf/relo_core.c +15 −5
  21. tools/lib/bpf/xsk.c +3 −6
  22. tools/perf/builtin-trace.c +12 −1
  23. tools/scripts/Makefile.include +12 −1
  24. tools/testing/selftests/bpf/Makefile +7 −5
  25. tools/testing/selftests/bpf/bench.c +7 −17
  26. tools/testing/selftests/bpf/bench.h +5 −4
  27. tools/testing/selftests/bpf/benchs/bench_count.c +1 −1
  28. tools/testing/selftests/bpf/benchs/bench_rename.c +8 −8
  29. tools/testing/selftests/bpf/benchs/bench_ringbufs.c +7 −7
  30. tools/testing/selftests/bpf/benchs/bench_strncmp.c +161 −0
  31. tools/testing/selftests/bpf/benchs/bench_trigger.c +12 −12
  32. tools/testing/selftests/bpf/benchs/run_bench_strncmp.sh +12 −0
  33. tools/testing/selftests/bpf/config +2 −0
  34. tools/testing/selftests/bpf/prog_tests/align.c +103 −88
  35. tools/testing/selftests/bpf/prog_tests/bpf_obj_id.c +2 −2
  36. tools/testing/selftests/bpf/prog_tests/bpf_tcp_ca.c +3 −4
  37. tools/testing/selftests/bpf/prog_tests/btf.c +0 −1
  38. tools/testing/selftests/bpf/prog_tests/connect_force_port.c +9 −9
  39. tools/testing/selftests/bpf/prog_tests/core_reloc.c +53 −26
  40. tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c +13 −4
  41. tools/testing/selftests/bpf/prog_tests/get_func_args_test.c +44 −0
  42. tools/testing/selftests/bpf/prog_tests/get_stack_raw_tp.c +2 −2
  43. tools/testing/selftests/bpf/prog_tests/ksyms_btf.c +14 −0
  44. tools/testing/selftests/bpf/prog_tests/libbpf_probes.c +124 −0
  45. tools/testing/selftests/bpf/prog_tests/select_reuseport.c +0 −1
  46. tools/testing/selftests/bpf/prog_tests/sk_lookup.c +0 −1
  47. tools/testing/selftests/bpf/prog_tests/sock_fields.c +0 −1
  48. tools/testing/selftests/bpf/prog_tests/sockopt_inherit.c +8 −7
  49. tools/testing/selftests/bpf/prog_tests/stacktrace_map.c +2 −2
  50. tools/testing/selftests/bpf/prog_tests/stacktrace_map_raw_tp.c +2 −2
  51. tools/testing/selftests/bpf/prog_tests/test_local_storage.c +6 −14
  52. tools/testing/selftests/bpf/prog_tests/test_overhead.c +10 −10
  53. tools/testing/selftests/bpf/prog_tests/test_strncmp.c +167 −0
  54. tools/testing/selftests/bpf/prog_tests/trampoline_count.c +3 −3
  55. tools/testing/selftests/bpf/progs/get_func_args_test.c +123 −0
  56. tools/testing/selftests/bpf/progs/local_storage.c +5 −19
  57. tools/testing/selftests/bpf/progs/strncmp_bench.c +50 −0
  58. tools/testing/selftests/bpf/progs/strncmp_test.c +54 −0
  59. tools/testing/selftests/bpf/progs/test_ksyms_btf_write_check.c +29 −0
  60. tools/testing/selftests/bpf/test_cpp.cpp +8 −1
  61. tools/testing/selftests/bpf/test_maps.c +0 −1
  62. tools/testing/selftests/bpf/test_progs.c +0 −2
  63. tools/testing/selftests/bpf/test_verifier.c +8 −10
  64. tools/testing/selftests/bpf/verifier/btf_ctx_access.c +12 −0
  65. tools/testing/selftests/bpf/vmtest.sh +1 −1
tools/bpf/bpftool/Makefile+7−6
@@ -57,7 +57,7 @@ $(LIBBPF_INTERNAL_HDRS): $(LIBBPF_HDRS_DIR)/%.h: $(BPF_DIR)/%.h | $(LIBBPF_HDRS_ · 56 unmodified lines
57$(LIBBPF_BOOTSTRAP): $(wildcard $(BPF_DIR)/*.[ch] $(BPF_DIR)/Makefile) | $(LIBBPF_BOOTSTRAP_OUTPUT)57$(LIBBPF_BOOTSTRAP): $(wildcard $(BPF_DIR)/*.[ch] $(BPF_DIR)/Makefile) | $(LIBBPF_BOOTSTRAP_OUTPUT)
58 $(Q)$(MAKE) -C $(BPF_DIR) OUTPUT=$(LIBBPF_BOOTSTRAP_OUTPUT) \58 $(Q)$(MAKE) -C $(BPF_DIR) OUTPUT=$(LIBBPF_BOOTSTRAP_OUTPUT) \
59 DESTDIR=$(LIBBPF_BOOTSTRAP_DESTDIR) prefix= \59 DESTDIR=$(LIBBPF_BOOTSTRAP_DESTDIR) prefix= \
60 ARCH= CC=$(HOSTCC) LD=$(HOSTLD) $@ install_headers60 ARCH= CROSS_COMPILE= CC=$(HOSTCC) LD=$(HOSTLD) $@ install_headers
61 61
62$(LIBBPF_BOOTSTRAP_INTERNAL_HDRS): $(LIBBPF_BOOTSTRAP_HDRS_DIR)/%.h: $(BPF_DIR)/%.h | $(LIBBPF_BOOTSTRAP_HDRS_DIR)62$(LIBBPF_BOOTSTRAP_INTERNAL_HDRS): $(LIBBPF_BOOTSTRAP_HDRS_DIR)/%.h: $(BPF_DIR)/%.h | $(LIBBPF_BOOTSTRAP_HDRS_DIR)
63 $(call QUIET_INSTALL, $@)63 $(call QUIET_INSTALL, $@)
@@ -152,6 +152,9 @@ CFLAGS += -DHAVE_LIBBFD_SUPPORT · 88 unmodified lines
152SRCS += $(BFD_SRCS)152SRCS += $(BFD_SRCS)
153endif153endif
154 154
155HOST_CFLAGS = $(subst -I$(LIBBPF_INCLUDE),-I$(LIBBPF_BOOTSTRAP_INCLUDE),\
156 $(subst $(CLANG_CROSS_FLAGS),,$(CFLAGS)))
157
155BPFTOOL_BOOTSTRAP := $(BOOTSTRAP_OUTPUT)bpftool158BPFTOOL_BOOTSTRAP := $(BOOTSTRAP_OUTPUT)bpftool
156 159
157BOOTSTRAP_OBJS = $(addprefix $(BOOTSTRAP_OUTPUT),main.o common.o json_writer.o gen.o btf.o xlated_dumper.o btf_dumper.o disasm.o)160BOOTSTRAP_OBJS = $(addprefix $(BOOTSTRAP_OUTPUT),main.o common.o json_writer.o gen.o btf.o xlated_dumper.o btf_dumper.o disasm.o)
@@ -202,7 +205,7 @@ endif · 44 unmodified lines
202CFLAGS += $(if $(BUILD_BPF_SKELS),,-DBPFTOOL_WITHOUT_SKELETONS)205CFLAGS += $(if $(BUILD_BPF_SKELS),,-DBPFTOOL_WITHOUT_SKELETONS)
203 206
204$(BOOTSTRAP_OUTPUT)disasm.o: $(srctree)/kernel/bpf/disasm.c207$(BOOTSTRAP_OUTPUT)disasm.o: $(srctree)/kernel/bpf/disasm.c
205 $(QUIET_CC)$(HOSTCC) $(CFLAGS) -c -MMD $< -o $@208 $(QUIET_CC)$(HOSTCC) $(HOST_CFLAGS) -c -MMD $< -o $@
206 209
207$(OUTPUT)disasm.o: $(srctree)/kernel/bpf/disasm.c210$(OUTPUT)disasm.o: $(srctree)/kernel/bpf/disasm.c
208 $(QUIET_CC)$(CC) $(CFLAGS) -c -MMD $< -o $@211 $(QUIET_CC)$(CC) $(CFLAGS) -c -MMD $< -o $@
@@ -213,15 +216,13 @@ ifneq ($(feature-zlib), 1) · 4 unmodified lines
213endif216endif
214 217
215$(BPFTOOL_BOOTSTRAP): $(BOOTSTRAP_OBJS) $(LIBBPF_BOOTSTRAP)218$(BPFTOOL_BOOTSTRAP): $(BOOTSTRAP_OBJS) $(LIBBPF_BOOTSTRAP)
216 $(QUIET_LINK)$(HOSTCC) $(CFLAGS) $(LDFLAGS) $(BOOTSTRAP_OBJS) $(LIBS_BOOTSTRAP) -o $@219 $(QUIET_LINK)$(HOSTCC) $(HOST_CFLAGS) $(LDFLAGS) $(BOOTSTRAP_OBJS) $(LIBS_BOOTSTRAP) -o $@
217 220
218$(OUTPUT)bpftool: $(OBJS) $(LIBBPF)221$(OUTPUT)bpftool: $(OBJS) $(LIBBPF)
219 $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) -o $@222 $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) -o $@
220 223
221$(BOOTSTRAP_OUTPUT)%.o: %.c $(LIBBPF_BOOTSTRAP_INTERNAL_HDRS) | $(BOOTSTRAP_OUTPUT)224$(BOOTSTRAP_OUTPUT)%.o: %.c $(LIBBPF_BOOTSTRAP_INTERNAL_HDRS) | $(BOOTSTRAP_OUTPUT)
222 $(QUIET_CC)$(HOSTCC) \225 $(QUIET_CC)$(HOSTCC) $(HOST_CFLAGS) -c -MMD $< -o $@
223 $(subst -I$(LIBBPF_INCLUDE),-I$(LIBBPF_BOOTSTRAP_INCLUDE),$(CFLAGS)) \
224 -c -MMD $< -o $@
225 226
226$(OUTPUT)%.o: %.c227$(OUTPUT)%.o: %.c
227 $(QUIET_CC)$(CC) $(CFLAGS) -c -MMD $< -o $@228 $(QUIET_CC)$(CC) $(CFLAGS) -c -MMD $< -o $@
tools/bpf/bpftool/feature.c+23−3
@@ -642,12 +642,32 @@ probe_helpers_for_progtype(enum bpf_prog_type prog_type, bool supported_type, · 641 unmodified lines
642 printf("\n");642 printf("\n");
643}643}
644 644
645static void645/*
646probe_large_insn_limit(const char *define_prefix, __u32 ifindex)646 * Probe for availability of kernel commit (5.3):
647 *
648 * c04c0d2b968a ("bpf: increase complexity limit and maximum program size")
649 */
650static void probe_large_insn_limit(const char *define_prefix, __u32 ifindex)
647{651{
652 LIBBPF_OPTS(bpf_prog_load_opts, opts,
653 .prog_ifindex = ifindex,
654 );
655 struct bpf_insn insns[BPF_MAXINSNS + 1];
648 bool res;656 bool res;
657 int i, fd;
658
659 for (i = 0; i < BPF_MAXINSNS; i++)
660 insns[i] = BPF_MOV64_IMM(BPF_REG_0, 1);
661 insns[BPF_MAXINSNS] = BPF_EXIT_INSN();
662
663 errno = 0;
664 fd = bpf_prog_load(BPF_PROG_TYPE_SCHED_CLS, NULL, "GPL",
665 insns, ARRAY_SIZE(insns), &opts);
666 res = fd >= 0 || (errno != E2BIG && errno != EINVAL);
667
668 if (fd >= 0)
669 close(fd);
649 670
650 res = bpf_probe_large_insn_limit(ifindex);
651 print_bool_feature("have_large_insn_limit",671 print_bool_feature("have_large_insn_limit",
652 "Large program size limit",672 "Large program size limit",
653 "LARGE_INSN_LIMIT",673 "LARGE_INSN_LIMIT",
tools/bpf/bpftool/main.c+2−0
@@ -408,6 +408,8 @@ int main(int argc, char **argv) · 407 unmodified lines
408 bool version_requested = false;408 bool version_requested = false;
409 int opt, ret;409 int opt, ret;
410 410
411 setlinebuf(stdout);
412
411 last_do_help = do_help;413 last_do_help = do_help;
412 pretty_output = false;414 pretty_output = false;
413 json_output = false;415 json_output = false;
tools/bpf/resolve_btfids/Makefile+1−0
@@ -19,6 +19,7 @@ CC = $(HOSTCC) · 18 unmodified lines
19LD = $(HOSTLD)19LD = $(HOSTLD)
20ARCH = $(HOSTARCH)20ARCH = $(HOSTARCH)
21RM ?= rm21RM ?= rm
22CROSS_COMPILE =
22 23
23OUTPUT ?= $(srctree)/tools/bpf/resolve_btfids/24OUTPUT ?= $(srctree)/tools/bpf/resolve_btfids/
24 25
tools/bpf/runqslower/Makefile+2−2
@@ -12,7 +12,7 @@ BPFOBJ := $(BPFOBJ_OUTPUT)libbpf.a · 11 unmodified lines
12BPF_DESTDIR := $(BPFOBJ_OUTPUT)12BPF_DESTDIR := $(BPFOBJ_OUTPUT)
13BPF_INCLUDE := $(BPF_DESTDIR)/include13BPF_INCLUDE := $(BPF_DESTDIR)/include
14INCLUDES := -I$(OUTPUT) -I$(BPF_INCLUDE) -I$(abspath ../../include/uapi)14INCLUDES := -I$(OUTPUT) -I$(BPF_INCLUDE) -I$(abspath ../../include/uapi)
15CFLAGS := -g -Wall15CFLAGS := -g -Wall $(CLANG_CROSS_FLAGS)
16 16
17# Try to detect best kernel BTF source17# Try to detect best kernel BTF source
18KERNEL_REL := $(shell uname -r)18KERNEL_REL := $(shell uname -r)
@@ -88,4 +88,4 @@ $(BPFOBJ): $(wildcard $(LIBBPF_SRC)/*.[ch] $(LIBBPF_SRC)/Makefile) | $(BPFOBJ_OU · 69 unmodified lines
88 88
89$(DEFAULT_BPFTOOL): $(BPFOBJ) | $(BPFTOOL_OUTPUT)89$(DEFAULT_BPFTOOL): $(BPFOBJ) | $(BPFTOOL_OUTPUT)
90 $(Q)$(MAKE) $(submake_extras) -C ../bpftool OUTPUT=$(BPFTOOL_OUTPUT) \90 $(Q)$(MAKE) $(submake_extras) -C ../bpftool OUTPUT=$(BPFTOOL_OUTPUT) \
91 CC=$(HOSTCC) LD=$(HOSTLD)91 ARCH= CROSS_COMPILE= CC=$(HOSTCC) LD=$(HOSTLD)
tools/include/uapi/linux/bpf.h+39−0
@@ -4983,6 +4983,41 @@ union bpf_attr { · 4982 unmodified lines
4983 * Return4983 * Return
4984 * The number of loops performed, **-EINVAL** for invalid **flags**,4984 * The number of loops performed, **-EINVAL** for invalid **flags**,
4985 * **-E2BIG** if **nr_loops** exceeds the maximum number of loops.4985 * **-E2BIG** if **nr_loops** exceeds the maximum number of loops.
4986 *
4987 * long bpf_strncmp(const char *s1, u32 s1_sz, const char *s2)
4988 * Description
4989 * Do strncmp() between **s1** and **s2**. **s1** doesn't need
4990 * to be null-terminated and **s1_sz** is the maximum storage
4991 * size of **s1**. **s2** must be a read-only string.
4992 * Return
4993 * An integer less than, equal to, or greater than zero
4994 * if the first **s1_sz** bytes of **s1** is found to be
4995 * less than, to match, or be greater than **s2**.
4996 *
4997 * long bpf_get_func_arg(void *ctx, u32 n, u64 *value)
4998 * Description
4999 * Get **n**-th argument (zero based) of the traced function (for tracing programs)
5000 * returned in **value**.
5001 *
5002 * Return
5003 * 0 on success.
5004 * **-EINVAL** if n >= arguments count of traced function.
5005 *
5006 * long bpf_get_func_ret(void *ctx, u64 *value)
5007 * Description
5008 * Get return value of the traced function (for tracing programs)
5009 * in **value**.
5010 *
5011 * Return
5012 * 0 on success.
5013 * **-EOPNOTSUPP** for tracing programs other than BPF_TRACE_FEXIT or BPF_MODIFY_RETURN.
5014 *
5015 * long bpf_get_func_arg_cnt(void *ctx)
5016 * Description
5017 * Get number of arguments of the traced function (for tracing programs).
5018 *
5019 * Return
5020 * The number of arguments of the traced function.
4986 */5021 */
4987#define __BPF_FUNC_MAPPER(FN) \5022#define __BPF_FUNC_MAPPER(FN) \
4988 FN(unspec), \5023 FN(unspec), \
@@ -5167,6 +5202,10 @@ union bpf_attr { · 178 unmodified lines
5167 FN(kallsyms_lookup_name), \5202 FN(kallsyms_lookup_name), \
5168 FN(find_vma), \5203 FN(find_vma), \
5169 FN(loop), \5204 FN(loop), \
5205 FN(strncmp), \
5206 FN(get_func_arg), \
5207 FN(get_func_ret), \
5208 FN(get_func_arg_cnt), \
5170 /* */5209 /* */
5171 5210
5172/* integer value in 'imm' field of BPF_CALL instruction selects which helper5211/* integer value in 'imm' field of BPF_CALL instruction selects which helper
tools/lib/bpf/Makefile+2−1
@@ -90,6 +90,7 @@ override CFLAGS += -Werror -Wall · 89 unmodified lines
90override CFLAGS += $(INCLUDES)90override CFLAGS += $(INCLUDES)
91override CFLAGS += -fvisibility=hidden91override CFLAGS += -fvisibility=hidden
92override CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=6492override CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
93override CFLAGS += $(CLANG_CROSS_FLAGS)
93 94
94# flags specific for shared library95# flags specific for shared library
95SHLIB_FLAGS := -DSHARED -fPIC96SHLIB_FLAGS := -DSHARED -fPIC
@@ -162,7 +163,7 @@ $(BPF_HELPER_DEFS): $(srctree)/tools/include/uapi/linux/bpf.h · 66 unmodified lines
162$(OUTPUT)libbpf.so: $(OUTPUT)libbpf.so.$(LIBBPF_VERSION)163$(OUTPUT)libbpf.so: $(OUTPUT)libbpf.so.$(LIBBPF_VERSION)
163 164
164$(OUTPUT)libbpf.so.$(LIBBPF_VERSION): $(BPF_IN_SHARED) $(VERSION_SCRIPT)165$(OUTPUT)libbpf.so.$(LIBBPF_VERSION): $(BPF_IN_SHARED) $(VERSION_SCRIPT)
165 $(QUIET_LINK)$(CC) $(LDFLAGS) \166 $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) \
166 --shared -Wl,-soname,libbpf.so.$(LIBBPF_MAJOR_VERSION) \167 --shared -Wl,-soname,libbpf.so.$(LIBBPF_MAJOR_VERSION) \
167 -Wl,--version-script=$(VERSION_SCRIPT) $< -lelf -lz -o $@168 -Wl,--version-script=$(VERSION_SCRIPT) $< -lelf -lz -o $@
168 @ln -sf $(@F) $(OUTPUT)libbpf.so169 @ln -sf $(@F) $(OUTPUT)libbpf.so
tools/lib/bpf/bpf.c+83−2
@@ -28,7 +28,9 @@ · 27 unmodified lines
28#include <asm/unistd.h>28#include <asm/unistd.h>
29#include <errno.h>29#include <errno.h>
30#include <linux/bpf.h>30#include <linux/bpf.h>
31#include <linux/filter.h>
31#include <limits.h>32#include <limits.h>
33#include <sys/resource.h>
32#include "bpf.h"34#include "bpf.h"
33#include "libbpf.h"35#include "libbpf.h"
34#include "libbpf_internal.h"36#include "libbpf_internal.h"
@@ -94,6 +96,77 @@ static inline int sys_bpf_prog_load(union bpf_attr *attr, unsigned int size, int · 59 unmodified lines
94 return fd;96 return fd;
95}97}
96 98
99/* Probe whether kernel switched from memlock-based (RLIMIT_MEMLOCK) to
100 * memcg-based memory accounting for BPF maps and progs. This was done in [0].
101 * We use the support for bpf_ktime_get_coarse_ns() helper, which was added in
102 * the same 5.11 Linux release ([1]), to detect memcg-based accounting for BPF.
103 *
104 * [0] https://lore.kernel.org/bpf/20201201215900.3569844-1-guro@fb.com/
105 * [1] d05512618056 ("bpf: Add bpf_ktime_get_coarse_ns helper")
106 */
107int probe_memcg_account(void)
108{
109 const size_t prog_load_attr_sz = offsetofend(union bpf_attr, attach_btf_obj_fd);
110 struct bpf_insn insns[] = {
111 BPF_EMIT_CALL(BPF_FUNC_ktime_get_coarse_ns),
112 BPF_EXIT_INSN(),
113 };
114 size_t insn_cnt = sizeof(insns) / sizeof(insns[0]);
115 union bpf_attr attr;
116 int prog_fd;
117
118 /* attempt loading freplace trying to use custom BTF */
119 memset(&attr, 0, prog_load_attr_sz);
120 attr.prog_type = BPF_PROG_TYPE_SOCKET_FILTER;
121 attr.insns = ptr_to_u64(insns);
122 attr.insn_cnt = insn_cnt;
123 attr.license = ptr_to_u64("GPL");
124
125 prog_fd = sys_bpf_fd(BPF_PROG_LOAD, &attr, prog_load_attr_sz);
126 if (prog_fd >= 0) {
127 close(prog_fd);
128 return 1;
129 }
130 return 0;
131}
132
133static bool memlock_bumped;
134static rlim_t memlock_rlim = RLIM_INFINITY;
135
136int libbpf_set_memlock_rlim(size_t memlock_bytes)
137{
138 if (memlock_bumped)
139 return libbpf_err(-EBUSY);
140
141 memlock_rlim = memlock_bytes;
142 return 0;
143}
144
145int bump_rlimit_memlock(void)
146{
147 struct rlimit rlim;
148
149 /* this the default in libbpf 1.0, but for now user has to opt-in explicitly */
150 if (!(libbpf_mode & LIBBPF_STRICT_AUTO_RLIMIT_MEMLOCK))
151 return 0;
152
153 /* if kernel supports memcg-based accounting, skip bumping RLIMIT_MEMLOCK */
154 if (memlock_bumped || kernel_supports(NULL, FEAT_MEMCG_ACCOUNT))
155 return 0;
156
157 memlock_bumped = true;
158
159 /* zero memlock_rlim_max disables auto-bumping RLIMIT_MEMLOCK */
160 if (memlock_rlim == 0)
161 return 0;
162
163 rlim.rlim_cur = rlim.rlim_max = memlock_rlim;
164 if (setrlimit(RLIMIT_MEMLOCK, &rlim))
165 return -errno;
166
167 return 0;
168}
169
97int bpf_map_create(enum bpf_map_type map_type,170int bpf_map_create(enum bpf_map_type map_type,
98 const char *map_name,171 const char *map_name,
99 __u32 key_size,172 __u32 key_size,
@@ -105,6 +178,8 @@ int bpf_map_create(enum bpf_map_type map_type, · 5 unmodified lines
105 union bpf_attr attr;178 union bpf_attr attr;
106 int fd;179 int fd;
107 180
181 bump_rlimit_memlock();
182
108 memset(&attr, 0, attr_sz);183 memset(&attr, 0, attr_sz);
109 184
110 if (!OPTS_VALID(opts, bpf_map_create_opts))185 if (!OPTS_VALID(opts, bpf_map_create_opts))
@@ -112,7 +187,7 @@ int bpf_map_create(enum bpf_map_type map_type, · 1 unmodified line
112 187
113 attr.map_type = map_type;188 attr.map_type = map_type;
114 if (map_name)189 if (map_name)
115 strncat(attr.map_name, map_name, sizeof(attr.map_name) - 1);190 libbpf_strlcpy(attr.map_name, map_name, sizeof(attr.map_name));
116 attr.key_size = key_size;191 attr.key_size = key_size;
117 attr.value_size = value_size;192 attr.value_size = value_size;
118 attr.max_entries = max_entries;193 attr.max_entries = max_entries;
@@ -251,6 +326,8 @@ int bpf_prog_load_v0_6_0(enum bpf_prog_type prog_type, · 132 unmodified lines
251 union bpf_attr attr;326 union bpf_attr attr;
252 char *log_buf;327 char *log_buf;
253 328
329 bump_rlimit_memlock();
330
254 if (!OPTS_VALID(opts, bpf_prog_load_opts))331 if (!OPTS_VALID(opts, bpf_prog_load_opts))
255 return libbpf_err(-EINVAL);332 return libbpf_err(-EINVAL);
256 333
@@ -271,7 +348,7 @@ int bpf_prog_load_v0_6_0(enum bpf_prog_type prog_type, · 14 unmodified lines
271 attr.kern_version = OPTS_GET(opts, kern_version, 0);348 attr.kern_version = OPTS_GET(opts, kern_version, 0);
272 349
273 if (prog_name)350 if (prog_name)
274 strncat(attr.prog_name, prog_name, sizeof(attr.prog_name) - 1);351 libbpf_strlcpy(attr.prog_name, prog_name, sizeof(attr.prog_name));
275 attr.license = ptr_to_u64(license);352 attr.license = ptr_to_u64(license);
276 353
277 if (insn_cnt > UINT_MAX)354 if (insn_cnt > UINT_MAX)
@@ -456,6 +533,8 @@ int bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns, · 178 unmodified lines
456 union bpf_attr attr;533 union bpf_attr attr;
457 int fd;534 int fd;
458 535
536 bump_rlimit_memlock();
537
459 memset(&attr, 0, sizeof(attr));538 memset(&attr, 0, sizeof(attr));
460 attr.prog_type = type;539 attr.prog_type = type;
461 attr.insn_cnt = (__u32)insns_cnt;540 attr.insn_cnt = (__u32)insns_cnt;
@@ -1056,6 +1135,8 @@ int bpf_btf_load(const void *btf_data, size_t btf_size, const struct bpf_btf_loa · 594 unmodified lines
1056 __u32 log_level;1135 __u32 log_level;
1057 int fd;1136 int fd;
1058 1137
1138 bump_rlimit_memlock();
1139
1059 memset(&attr, 0, attr_sz);1140 memset(&attr, 0, attr_sz);
1060 1141
1061 if (!OPTS_VALID(opts, bpf_btf_load_opts))1142 if (!OPTS_VALID(opts, bpf_btf_load_opts))
tools/lib/bpf/bpf.h+2−0
@@ -35,6 +35,8 @@ · 34 unmodified lines
35extern "C" {35extern "C" {
36#endif36#endif
37 37
38int libbpf_set_memlock_rlim(size_t memlock_bytes);
39
38struct bpf_map_create_opts {40struct bpf_map_create_opts {
39 size_t sz; /* size of this struct for forward/backward compatibility */41 size_t sz; /* size of this struct for forward/backward compatibility */
40 42
tools/lib/bpf/bpf_tracing.h+174−257
@@ -66,277 +66,204 @@ · 65 unmodified lines
66 66
67#if defined(__KERNEL__) || defined(__VMLINUX_H__)67#if defined(__KERNEL__) || defined(__VMLINUX_H__)
68 68
69#define PT_REGS_PARM1(x) ((x)->di)69#define __PT_PARM1_REG di
70#define PT_REGS_PARM2(x) ((x)->si)70#define __PT_PARM2_REG si
71#define PT_REGS_PARM3(x) ((x)->dx)71#define __PT_PARM3_REG dx
72#define PT_REGS_PARM4(x) ((x)->cx)72#define __PT_PARM4_REG cx
73#define PT_REGS_PARM5(x) ((x)->r8)73#define __PT_PARM5_REG r8
74#define PT_REGS_RET(x) ((x)->sp)74#define __PT_RET_REG sp
75#define PT_REGS_FP(x) ((x)->bp)75#define __PT_FP_REG bp
76#define PT_REGS_RC(x) ((x)->ax)76#define __PT_RC_REG ax
77#define PT_REGS_SP(x) ((x)->sp)77#define __PT_SP_REG sp
78#define PT_REGS_IP(x) ((x)->ip)78#define __PT_IP_REG ip
79
80#define PT_REGS_PARM1_CORE(x) BPF_CORE_READ((x), di)
81#define PT_REGS_PARM2_CORE(x) BPF_CORE_READ((x), si)
82#define PT_REGS_PARM3_CORE(x) BPF_CORE_READ((x), dx)
83#define PT_REGS_PARM4_CORE(x) BPF_CORE_READ((x), cx)
84#define PT_REGS_PARM5_CORE(x) BPF_CORE_READ((x), r8)
85#define PT_REGS_RET_CORE(x) BPF_CORE_READ((x), sp)
86#define PT_REGS_FP_CORE(x) BPF_CORE_READ((x), bp)
87#define PT_REGS_RC_CORE(x) BPF_CORE_READ((x), ax)
88#define PT_REGS_SP_CORE(x) BPF_CORE_READ((x), sp)
89#define PT_REGS_IP_CORE(x) BPF_CORE_READ((x), ip)
90 79
91#else80#else
92 81
93#ifdef __i386__82#ifdef __i386__
94/* i386 kernel is built with -mregparm=3 */
95#define PT_REGS_PARM1(x) ((x)->eax)
96#define PT_REGS_PARM2(x) ((x)->edx)
97#define PT_REGS_PARM3(x) ((x)->ecx)
98#define PT_REGS_PARM4(x) 0
99#define PT_REGS_PARM5(x) 0
100#define PT_REGS_RET(x) ((x)->esp)
101#define PT_REGS_FP(x) ((x)->ebp)
102#define PT_REGS_RC(x) ((x)->eax)
103#define PT_REGS_SP(x) ((x)->esp)
104#define PT_REGS_IP(x) ((x)->eip)
105
106#define PT_REGS_PARM1_CORE(x) BPF_CORE_READ((x), eax)
107#define PT_REGS_PARM2_CORE(x) BPF_CORE_READ((x), edx)
108#define PT_REGS_PARM3_CORE(x) BPF_CORE_READ((x), ecx)
109#define PT_REGS_PARM4_CORE(x) 0
110#define PT_REGS_PARM5_CORE(x) 0
111#define PT_REGS_RET_CORE(x) BPF_CORE_READ((x), esp)
112#define PT_REGS_FP_CORE(x) BPF_CORE_READ((x), ebp)
113#define PT_REGS_RC_CORE(x) BPF_CORE_READ((x), eax)
114#define PT_REGS_SP_CORE(x) BPF_CORE_READ((x), esp)
115#define PT_REGS_IP_CORE(x) BPF_CORE_READ((x), eip)
116
117#else
118 83
119#define PT_REGS_PARM1(x) ((x)->rdi)84#define __PT_PARM1_REG eax
120#define PT_REGS_PARM2(x) ((x)->rsi)85#define __PT_PARM2_REG edx
121#define PT_REGS_PARM3(x) ((x)->rdx)86#define __PT_PARM3_REG ecx
122#define PT_REGS_PARM4(x) ((x)->rcx)87/* i386 kernel is built with -mregparm=3 */
123#define PT_REGS_PARM5(x) ((x)->r8)88#define __PT_PARM4_REG __unsupported__
124#define PT_REGS_RET(x) ((x)->rsp)89#define __PT_PARM5_REG __unsupported__
125#define PT_REGS_FP(x) ((x)->rbp)90#define __PT_RET_REG esp
126#define PT_REGS_RC(x) ((x)->rax)91#define __PT_FP_REG ebp
127#define PT_REGS_SP(x) ((x)->rsp)92#define __PT_RC_REG eax
128#define PT_REGS_IP(x) ((x)->rip)93#define __PT_SP_REG esp
129 94#define __PT_IP_REG eip
130#define PT_REGS_PARM1_CORE(x) BPF_CORE_READ((x), rdi)95
131#define PT_REGS_PARM2_CORE(x) BPF_CORE_READ((x), rsi)96#else /* __i386__ */
132#define PT_REGS_PARM3_CORE(x) BPF_CORE_READ((x), rdx)97
133#define PT_REGS_PARM4_CORE(x) BPF_CORE_READ((x), rcx)98#define __PT_PARM1_REG rdi
134#define PT_REGS_PARM5_CORE(x) BPF_CORE_READ((x), r8)99#define __PT_PARM2_REG rsi
135#define PT_REGS_RET_CORE(x) BPF_CORE_READ((x), rsp)100#define __PT_PARM3_REG rdx
136#define PT_REGS_FP_CORE(x) BPF_CORE_READ((x), rbp)101#define __PT_PARM4_REG rcx
137#define PT_REGS_RC_CORE(x) BPF_CORE_READ((x), rax)102#define __PT_PARM5_REG r8
138#define PT_REGS_SP_CORE(x) BPF_CORE_READ((x), rsp)103#define __PT_RET_REG rsp
139#define PT_REGS_IP_CORE(x) BPF_CORE_READ((x), rip)104#define __PT_FP_REG rbp
140 105#define __PT_RC_REG rax
141#endif106#define __PT_SP_REG rsp
142#endif107#define __PT_IP_REG rip
108
109#endif /* __i386__ */
110
111#endif /* __KERNEL__ || __VMLINUX_H__ */
143 112
144#elif defined(bpf_target_s390)113#elif defined(bpf_target_s390)
145 114
146/* s390 provides user_pt_regs instead of struct pt_regs to userspace */115/* s390 provides user_pt_regs instead of struct pt_regs to userspace */
147struct pt_regs;116#define __PT_REGS_CAST(x) ((const user_pt_regs *)(x))
148#define PT_REGS_S390 const volatile user_pt_regs117#define __PT_PARM1_REG gprs[2]
149#define PT_REGS_PARM1(x) (((PT_REGS_S390 *)(x))->gprs[2])118#define __PT_PARM2_REG gprs[3]
150#define PT_REGS_PARM2(x) (((PT_REGS_S390 *)(x))->gprs[3])119#define __PT_PARM3_REG gprs[4]
151#define PT_REGS_PARM3(x) (((PT_REGS_S390 *)(x))->gprs[4])120#define __PT_PARM4_REG gprs[5]
152#define PT_REGS_PARM4(x) (((PT_REGS_S390 *)(x))->gprs[5])121#define __PT_PARM5_REG gprs[6]
153#define PT_REGS_PARM5(x) (((PT_REGS_S390 *)(x))->gprs[6])122#define __PT_RET_REG grps[14]
154#define PT_REGS_RET(x) (((PT_REGS_S390 *)(x))->gprs[14])123#define __PT_FP_REG gprs[11] /* Works only with CONFIG_FRAME_POINTER */
155/* Works only with CONFIG_FRAME_POINTER */124#define __PT_RC_REG gprs[2]
156#define PT_REGS_FP(x) (((PT_REGS_S390 *)(x))->gprs[11])125#define __PT_SP_REG gprs[15]
157#define PT_REGS_RC(x) (((PT_REGS_S390 *)(x))->gprs[2])126#define __PT_IP_REG psw.addr
158#define PT_REGS_SP(x) (((PT_REGS_S390 *)(x))->gprs[15])
159#define PT_REGS_IP(x) (((PT_REGS_S390 *)(x))->psw.addr)
160
161#define PT_REGS_PARM1_CORE(x) BPF_CORE_READ((PT_REGS_S390 *)(x), gprs[2])
162#define PT_REGS_PARM2_CORE(x) BPF_CORE_READ((PT_REGS_S390 *)(x), gprs[3])
163#define PT_REGS_PARM3_CORE(x) BPF_CORE_READ((PT_REGS_S390 *)(x), gprs[4])
164#define PT_REGS_PARM4_CORE(x) BPF_CORE_READ((PT_REGS_S390 *)(x), gprs[5])
165#define PT_REGS_PARM5_CORE(x) BPF_CORE_READ((PT_REGS_S390 *)(x), gprs[6])
166#define PT_REGS_RET_CORE(x) BPF_CORE_READ((PT_REGS_S390 *)(x), gprs[14])
167#define PT_REGS_FP_CORE(x) BPF_CORE_READ((PT_REGS_S390 *)(x), gprs[11])
168#define PT_REGS_RC_CORE(x) BPF_CORE_READ((PT_REGS_S390 *)(x), gprs[2])
169#define PT_REGS_SP_CORE(x) BPF_CORE_READ((PT_REGS_S390 *)(x), gprs[15])
170#define PT_REGS_IP_CORE(x) BPF_CORE_READ((PT_REGS_S390 *)(x), psw.addr)
171 127
172#elif defined(bpf_target_arm)128#elif defined(bpf_target_arm)
173 129
174#define PT_REGS_PARM1(x) ((x)->uregs[0])130#define __PT_PARM1_REG uregs[0]
175#define PT_REGS_PARM2(x) ((x)->uregs[1])131#define __PT_PARM2_REG uregs[1]
176#define PT_REGS_PARM3(x) ((x)->uregs[2])132#define __PT_PARM3_REG uregs[2]
177#define PT_REGS_PARM4(x) ((x)->uregs[3])133#define __PT_PARM4_REG uregs[3]
178#define PT_REGS_PARM5(x) ((x)->uregs[4])134#define __PT_PARM5_REG uregs[4]
179#define PT_REGS_RET(x) ((x)->uregs[14])135#define __PT_RET_REG uregs[14]
180#define PT_REGS_FP(x) ((x)->uregs[11]) /* Works only with CONFIG_FRAME_POINTER */136#define __PT_FP_REG uregs[11] /* Works only with CONFIG_FRAME_POINTER */
181#define PT_REGS_RC(x) ((x)->uregs[0])137#define __PT_RC_REG uregs[0]
182#define PT_REGS_SP(x) ((x)->uregs[13])138#define __PT_SP_REG uregs[13]
183#define PT_REGS_IP(x) ((x)->uregs[12])139#define __PT_IP_REG uregs[12]
184
185#define PT_REGS_PARM1_CORE(x) BPF_CORE_READ((x), uregs[0])
186#define PT_REGS_PARM2_CORE(x) BPF_CORE_READ((x), uregs[1])
187#define PT_REGS_PARM3_CORE(x) BPF_CORE_READ((x), uregs[2])
188#define PT_REGS_PARM4_CORE(x) BPF_CORE_READ((x), uregs[3])
189#define PT_REGS_PARM5_CORE(x) BPF_CORE_READ((x), uregs[4])
190#define PT_REGS_RET_CORE(x) BPF_CORE_READ((x), uregs[14])
191#define PT_REGS_FP_CORE(x) BPF_CORE_READ((x), uregs[11])
192#define PT_REGS_RC_CORE(x) BPF_CORE_READ((x), uregs[0])
193#define PT_REGS_SP_CORE(x) BPF_CORE_READ((x), uregs[13])
194#define PT_REGS_IP_CORE(x) BPF_CORE_READ((x), uregs[12])
195 140
196#elif defined(bpf_target_arm64)141#elif defined(bpf_target_arm64)
197 142
198/* arm64 provides struct user_pt_regs instead of struct pt_regs to userspace */143/* arm64 provides struct user_pt_regs instead of struct pt_regs to userspace */
199struct pt_regs;144#define __PT_REGS_CAST(x) ((const struct user_pt_regs *)(x))
200#define PT_REGS_ARM64 const volatile struct user_pt_regs145#define __PT_PARM1_REG regs[0]
201#define PT_REGS_PARM1(x) (((PT_REGS_ARM64 *)(x))->regs[0])146#define __PT_PARM2_REG regs[1]
202#define PT_REGS_PARM2(x) (((PT_REGS_ARM64 *)(x))->regs[1])147#define __PT_PARM3_REG regs[2]
203#define PT_REGS_PARM3(x) (((PT_REGS_ARM64 *)(x))->regs[2])148#define __PT_PARM4_REG regs[3]
204#define PT_REGS_PARM4(x) (((PT_REGS_ARM64 *)(x))->regs[3])149#define __PT_PARM5_REG regs[4]
205#define PT_REGS_PARM5(x) (((PT_REGS_ARM64 *)(x))->regs[4])150#define __PT_RET_REG regs[30]
206#define PT_REGS_RET(x) (((PT_REGS_ARM64 *)(x))->regs[30])151#define __PT_FP_REG regs[29] /* Works only with CONFIG_FRAME_POINTER */
207/* Works only with CONFIG_FRAME_POINTER */152#define __PT_RC_REG regs[0]
208#define PT_REGS_FP(x) (((PT_REGS_ARM64 *)(x))->regs[29])153#define __PT_SP_REG sp
209#define PT_REGS_RC(x) (((PT_REGS_ARM64 *)(x))->regs[0])154#define __PT_IP_REG pc
210#define PT_REGS_SP(x) (((PT_REGS_ARM64 *)(x))->sp)
211#define PT_REGS_IP(x) (((PT_REGS_ARM64 *)(x))->pc)
212
213#define PT_REGS_PARM1_CORE(x) BPF_CORE_READ((PT_REGS_ARM64 *)(x), regs[0])
214#define PT_REGS_PARM2_CORE(x) BPF_CORE_READ((PT_REGS_ARM64 *)(x), regs[1])
215#define PT_REGS_PARM3_CORE(x) BPF_CORE_READ((PT_REGS_ARM64 *)(x), regs[2])
216#define PT_REGS_PARM4_CORE(x) BPF_CORE_READ((PT_REGS_ARM64 *)(x), regs[3])
217#define PT_REGS_PARM5_CORE(x) BPF_CORE_READ((PT_REGS_ARM64 *)(x), regs[4])
218#define PT_REGS_RET_CORE(x) BPF_CORE_READ((PT_REGS_ARM64 *)(x), regs[30])
219#define PT_REGS_FP_CORE(x) BPF_CORE_READ((PT_REGS_ARM64 *)(x), regs[29])
220#define PT_REGS_RC_CORE(x) BPF_CORE_READ((PT_REGS_ARM64 *)(x), regs[0])
221#define PT_REGS_SP_CORE(x) BPF_CORE_READ((PT_REGS_ARM64 *)(x), sp)
222#define PT_REGS_IP_CORE(x) BPF_CORE_READ((PT_REGS_ARM64 *)(x), pc)
223 155
224#elif defined(bpf_target_mips)156#elif defined(bpf_target_mips)
225 157
226#define PT_REGS_PARM1(x) ((x)->regs[4])158#define __PT_PARM1_REG regs[4]
227#define PT_REGS_PARM2(x) ((x)->regs[5])159#define __PT_PARM2_REG regs[5]
228#define PT_REGS_PARM3(x) ((x)->regs[6])160#define __PT_PARM3_REG regs[6]
229#define PT_REGS_PARM4(x) ((x)->regs[7])161#define __PT_PARM4_REG regs[7]
230#define PT_REGS_PARM5(x) ((x)->regs[8])162#define __PT_PARM5_REG regs[8]
231#define PT_REGS_RET(x) ((x)->regs[31])163#define __PT_RET_REG regs[31]
232#define PT_REGS_FP(x) ((x)->regs[30]) /* Works only with CONFIG_FRAME_POINTER */164#define __PT_FP_REG regs[30] /* Works only with CONFIG_FRAME_POINTER */
233#define PT_REGS_RC(x) ((x)->regs[2])165#define __PT_RC_REG regs[2]
234#define PT_REGS_SP(x) ((x)->regs[29])166#define __PT_SP_REG regs[29]
235#define PT_REGS_IP(x) ((x)->cp0_epc)167#define __PT_IP_REG cp0_epc
236
237#define PT_REGS_PARM1_CORE(x) BPF_CORE_READ((x), regs[4])
238#define PT_REGS_PARM2_CORE(x) BPF_CORE_READ((x), regs[5])
239#define PT_REGS_PARM3_CORE(x) BPF_CORE_READ((x), regs[6])
240#define PT_REGS_PARM4_CORE(x) BPF_CORE_READ((x), regs[7])
241#define PT_REGS_PARM5_CORE(x) BPF_CORE_READ((x), regs[8])
242#define PT_REGS_RET_CORE(x) BPF_CORE_READ((x), regs[31])
243#define PT_REGS_FP_CORE(x) BPF_CORE_READ((x), regs[30])
244#define PT_REGS_RC_CORE(x) BPF_CORE_READ((x), regs[2])
245#define PT_REGS_SP_CORE(x) BPF_CORE_READ((x), regs[29])
246#define PT_REGS_IP_CORE(x) BPF_CORE_READ((x), cp0_epc)
247 168
248#elif defined(bpf_target_powerpc)169#elif defined(bpf_target_powerpc)
249 170
250#define PT_REGS_PARM1(x) ((x)->gpr[3])171#define __PT_PARM1_REG gpr[3]
251#define PT_REGS_PARM2(x) ((x)->gpr[4])172#define __PT_PARM2_REG gpr[4]
252#define PT_REGS_PARM3(x) ((x)->gpr[5])173#define __PT_PARM3_REG gpr[5]
253#define PT_REGS_PARM4(x) ((x)->gpr[6])174#define __PT_PARM4_REG gpr[6]
254#define PT_REGS_PARM5(x) ((x)->gpr[7])175#define __PT_PARM5_REG gpr[7]
255#define PT_REGS_RC(x) ((x)->gpr[3])176#define __PT_RET_REG regs[31]
256#define PT_REGS_SP(x) ((x)->sp)177#define __PT_FP_REG __unsupported__
257#define PT_REGS_IP(x) ((x)->nip)178#define __PT_RC_REG gpr[3]
258 179#define __PT_SP_REG sp
259#define PT_REGS_PARM1_CORE(x) BPF_CORE_READ((x), gpr[3])180#define __PT_IP_REG nip
260#define PT_REGS_PARM2_CORE(x) BPF_CORE_READ((x), gpr[4])
261#define PT_REGS_PARM3_CORE(x) BPF_CORE_READ((x), gpr[5])
262#define PT_REGS_PARM4_CORE(x) BPF_CORE_READ((x), gpr[6])
263#define PT_REGS_PARM5_CORE(x) BPF_CORE_READ((x), gpr[7])
264#define PT_REGS_RC_CORE(x) BPF_CORE_READ((x), gpr[3])
265#define PT_REGS_SP_CORE(x) BPF_CORE_READ((x), sp)
266#define PT_REGS_IP_CORE(x) BPF_CORE_READ((x), nip)
267 181
268#elif defined(bpf_target_sparc)182#elif defined(bpf_target_sparc)
269 183
270#define PT_REGS_PARM1(x) ((x)->u_regs[UREG_I0])184#define __PT_PARM1_REG u_regs[UREG_I0]
271#define PT_REGS_PARM2(x) ((x)->u_regs[UREG_I1])185#define __PT_PARM2_REG u_regs[UREG_I1]
272#define PT_REGS_PARM3(x) ((x)->u_regs[UREG_I2])186#define __PT_PARM3_REG u_regs[UREG_I2]
273#define PT_REGS_PARM4(x) ((x)->u_regs[UREG_I3])187#define __PT_PARM4_REG u_regs[UREG_I3]
274#define PT_REGS_PARM5(x) ((x)->u_regs[UREG_I4])188#define __PT_PARM5_REG u_regs[UREG_I4]
275#define PT_REGS_RET(x) ((x)->u_regs[UREG_I7])189#define __PT_RET_REG u_regs[UREG_I7]
276#define PT_REGS_RC(x) ((x)->u_regs[UREG_I0])190#define __PT_FP_REG __unsupported__
277#define PT_REGS_SP(x) ((x)->u_regs[UREG_FP])191#define __PT_RC_REG u_regs[UREG_I0]
278 192#define __PT_SP_REG u_regs[UREG_FP]
279#define PT_REGS_PARM1_CORE(x) BPF_CORE_READ((x), u_regs[UREG_I0])
280#define PT_REGS_PARM2_CORE(x) BPF_CORE_READ((x), u_regs[UREG_I1])
281#define PT_REGS_PARM3_CORE(x) BPF_CORE_READ((x), u_regs[UREG_I2])
282#define PT_REGS_PARM4_CORE(x) BPF_CORE_READ((x), u_regs[UREG_I3])
283#define PT_REGS_PARM5_CORE(x) BPF_CORE_READ((x), u_regs[UREG_I4])
284#define PT_REGS_RET_CORE(x) BPF_CORE_READ((x), u_regs[UREG_I7])
285#define PT_REGS_RC_CORE(x) BPF_CORE_READ((x), u_regs[UREG_I0])
286#define PT_REGS_SP_CORE(x) BPF_CORE_READ((x), u_regs[UREG_FP])
287
288/* Should this also be a bpf_target check for the sparc case? */193/* Should this also be a bpf_target check for the sparc case? */
289#if defined(__arch64__)194#if defined(__arch64__)
290#define PT_REGS_IP(x) ((x)->tpc)195#define __PT_IP_REG tpc
291#define PT_REGS_IP_CORE(x) BPF_CORE_READ((x), tpc)
292#else196#else
293#define PT_REGS_IP(x) ((x)->pc)197#define __PT_IP_REG pc
294#define PT_REGS_IP_CORE(x) BPF_CORE_READ((x), pc)
295#endif198#endif
296 199
297#elif defined(bpf_target_riscv)200#elif defined(bpf_target_riscv)
298 201
202#define __PT_REGS_CAST(x) ((const struct user_regs_struct *)(x))
203#define __PT_PARM1_REG a0
204#define __PT_PARM2_REG a1
205#define __PT_PARM3_REG a2
206#define __PT_PARM4_REG a3
207#define __PT_PARM5_REG a4
208#define __PT_RET_REG ra
209#define __PT_FP_REG fp
210#define __PT_RC_REG a5
211#define __PT_SP_REG sp
212#define __PT_IP_REG epc
213
214#endif
215
216#if defined(bpf_target_defined)
217
299struct pt_regs;218struct pt_regs;
300#define PT_REGS_RV const volatile struct user_regs_struct
301#define PT_REGS_PARM1(x) (((PT_REGS_RV *)(x))->a0)
302#define PT_REGS_PARM2(x) (((PT_REGS_RV *)(x))->a1)
303#define PT_REGS_PARM3(x) (((PT_REGS_RV *)(x))->a2)
304#define PT_REGS_PARM4(x) (((PT_REGS_RV *)(x))->a3)
305#define PT_REGS_PARM5(x) (((PT_REGS_RV *)(x))->a4)
306#define PT_REGS_RET(x) (((PT_REGS_RV *)(x))->ra)
307#define PT_REGS_FP(x) (((PT_REGS_RV *)(x))->s5)
308#define PT_REGS_RC(x) (((PT_REGS_RV *)(x))->a5)
309#define PT_REGS_SP(x) (((PT_REGS_RV *)(x))->sp)
310#define PT_REGS_IP(x) (((PT_REGS_RV *)(x))->epc)
311
312#define PT_REGS_PARM1_CORE(x) BPF_CORE_READ((PT_REGS_RV *)(x), a0)
313#define PT_REGS_PARM2_CORE(x) BPF_CORE_READ((PT_REGS_RV *)(x), a1)
314#define PT_REGS_PARM3_CORE(x) BPF_CORE_READ((PT_REGS_RV *)(x), a2)
315#define PT_REGS_PARM4_CORE(x) BPF_CORE_READ((PT_REGS_RV *)(x), a3)
316#define PT_REGS_PARM5_CORE(x) BPF_CORE_READ((PT_REGS_RV *)(x), a4)
317#define PT_REGS_RET_CORE(x) BPF_CORE_READ((PT_REGS_RV *)(x), ra)
318#define PT_REGS_FP_CORE(x) BPF_CORE_READ((PT_REGS_RV *)(x), fp)
319#define PT_REGS_RC_CORE(x) BPF_CORE_READ((PT_REGS_RV *)(x), a5)
320#define PT_REGS_SP_CORE(x) BPF_CORE_READ((PT_REGS_RV *)(x), sp)
321#define PT_REGS_IP_CORE(x) BPF_CORE_READ((PT_REGS_RV *)(x), epc)
322 219
220/* allow some architecutres to override `struct pt_regs` */
221#ifndef __PT_REGS_CAST
222#define __PT_REGS_CAST(x) (x)
323#endif223#endif
324 224
225#define PT_REGS_PARM1(x) (__PT_REGS_CAST(x)->__PT_PARM1_REG)
226#define PT_REGS_PARM2(x) (__PT_REGS_CAST(x)->__PT_PARM2_REG)
227#define PT_REGS_PARM3(x) (__PT_REGS_CAST(x)->__PT_PARM3_REG)
228#define PT_REGS_PARM4(x) (__PT_REGS_CAST(x)->__PT_PARM4_REG)
229#define PT_REGS_PARM5(x) (__PT_REGS_CAST(x)->__PT_PARM5_REG)
230#define PT_REGS_RET(x) (__PT_REGS_CAST(x)->__PT_RET_REG)
231#define PT_REGS_FP(x) (__PT_REGS_CAST(x)->__PT_FP_REG)
232#define PT_REGS_RC(x) (__PT_REGS_CAST(x)->__PT_RC_REG)
233#define PT_REGS_SP(x) (__PT_REGS_CAST(x)->__PT_SP_REG)
234#define PT_REGS_IP(x) (__PT_REGS_CAST(x)->__PT_IP_REG)
235
236#define PT_REGS_PARM1_CORE(x) BPF_CORE_READ(__PT_REGS_CAST(x), __PT_PARM1_REG)
237#define PT_REGS_PARM2_CORE(x) BPF_CORE_READ(__PT_REGS_CAST(x), __PT_PARM2_REG)
238#define PT_REGS_PARM3_CORE(x) BPF_CORE_READ(__PT_REGS_CAST(x), __PT_PARM3_REG)
239#define PT_REGS_PARM4_CORE(x) BPF_CORE_READ(__PT_REGS_CAST(x), __PT_PARM4_REG)
240#define PT_REGS_PARM5_CORE(x) BPF_CORE_READ(__PT_REGS_CAST(x), __PT_PARM5_REG)
241#define PT_REGS_RET_CORE(x) BPF_CORE_READ(__PT_REGS_CAST(x), __PT_RET_REG)
242#define PT_REGS_FP_CORE(x) BPF_CORE_READ(__PT_REGS_CAST(x), __PT_FP_REG)
243#define PT_REGS_RC_CORE(x) BPF_CORE_READ(__PT_REGS_CAST(x), __PT_RC_REG)
244#define PT_REGS_SP_CORE(x) BPF_CORE_READ(__PT_REGS_CAST(x), __PT_SP_REG)
245#define PT_REGS_IP_CORE(x) BPF_CORE_READ(__PT_REGS_CAST(x), __PT_IP_REG)
246
325#if defined(bpf_target_powerpc)247#if defined(bpf_target_powerpc)
248
326#define BPF_KPROBE_READ_RET_IP(ip, ctx) ({ (ip) = (ctx)->link; })249#define BPF_KPROBE_READ_RET_IP(ip, ctx) ({ (ip) = (ctx)->link; })
327#define BPF_KRETPROBE_READ_RET_IP BPF_KPROBE_READ_RET_IP250#define BPF_KRETPROBE_READ_RET_IP BPF_KPROBE_READ_RET_IP
251
328#elif defined(bpf_target_sparc)252#elif defined(bpf_target_sparc)
253
329#define BPF_KPROBE_READ_RET_IP(ip, ctx) ({ (ip) = PT_REGS_RET(ctx); })254#define BPF_KPROBE_READ_RET_IP(ip, ctx) ({ (ip) = PT_REGS_RET(ctx); })
330#define BPF_KRETPROBE_READ_RET_IP BPF_KPROBE_READ_RET_IP255#define BPF_KRETPROBE_READ_RET_IP BPF_KPROBE_READ_RET_IP
331#elif defined(bpf_target_defined)256
257#else
258
332#define BPF_KPROBE_READ_RET_IP(ip, ctx) \259#define BPF_KPROBE_READ_RET_IP(ip, ctx) \
333 ({ bpf_probe_read_kernel(&(ip), sizeof(ip), (void *)PT_REGS_RET(ctx)); })260 ({ bpf_probe_read_kernel(&(ip), sizeof(ip), (void *)PT_REGS_RET(ctx)); })
334#define BPF_KRETPROBE_READ_RET_IP(ip, ctx) \261#define BPF_KRETPROBE_READ_RET_IP(ip, ctx) \
335 ({ bpf_probe_read_kernel(&(ip), sizeof(ip), \262 ({ bpf_probe_read_kernel(&(ip), sizeof(ip), (void *)(PT_REGS_FP(ctx) + sizeof(ip))); })
336 (void *)(PT_REGS_FP(ctx) + sizeof(ip))); })263
337#endif264#endif
338 265
339#if !defined(bpf_target_defined)266#else /* defined(bpf_target_defined) */
340 267
341#define PT_REGS_PARM1(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })268#define PT_REGS_PARM1(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
342#define PT_REGS_PARM2(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })269#define PT_REGS_PARM2(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
@@ -363,7 +290,7 @@ struct pt_regs; · 20 unmodified lines
363#define BPF_KPROBE_READ_RET_IP(ip, ctx) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })290#define BPF_KPROBE_READ_RET_IP(ip, ctx) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
364#define BPF_KRETPROBE_READ_RET_IP(ip, ctx) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })291#define BPF_KRETPROBE_READ_RET_IP(ip, ctx) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
365 292
366#endif /* !defined(bpf_target_defined) */293#endif /* defined(bpf_target_defined) */
367 294
368#ifndef ___bpf_concat295#ifndef ___bpf_concat
369#define ___bpf_concat(a, b) a ## b296#define ___bpf_concat(a, b) a ## b
@@ -375,25 +302,23 @@ struct pt_regs; · 5 unmodified lines
375#define ___bpf_nth(_, _1, _2, _3, _4, _5, _6, _7, _8, _9, _a, _b, _c, N, ...) N302#define ___bpf_nth(_, _1, _2, _3, _4, _5, _6, _7, _8, _9, _a, _b, _c, N, ...) N
376#endif303#endif
377#ifndef ___bpf_narg304#ifndef ___bpf_narg
378#define ___bpf_narg(...) \305#define ___bpf_narg(...) ___bpf_nth(_, ##__VA_ARGS__, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
379 ___bpf_nth(_, ##__VA_ARGS__, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
380#endif306#endif
381 307
382#define ___bpf_ctx_cast0() ctx308#define ___bpf_ctx_cast0() ctx
383#define ___bpf_ctx_cast1(x) ___bpf_ctx_cast0(), (void *)ctx[0]309#define ___bpf_ctx_cast1(x) ___bpf_ctx_cast0(), (void *)ctx[0]
384#define ___bpf_ctx_cast2(x, args...) ___bpf_ctx_cast1(args), (void *)ctx[1]310#define ___bpf_ctx_cast2(x, args...) ___bpf_ctx_cast1(args), (void *)ctx[1]
385#define ___bpf_ctx_cast3(x, args...) ___bpf_ctx_cast2(args), (void *)ctx[2]311#define ___bpf_ctx_cast3(x, args...) ___bpf_ctx_cast2(args), (void *)ctx[2]
386#define ___bpf_ctx_cast4(x, args...) ___bpf_ctx_cast3(args), (void *)ctx[3]312#define ___bpf_ctx_cast4(x, args...) ___bpf_ctx_cast3(args), (void *)ctx[3]
387#define ___bpf_ctx_cast5(x, args...) ___bpf_ctx_cast4(args), (void *)ctx[4]313#define ___bpf_ctx_cast5(x, args...) ___bpf_ctx_cast4(args), (void *)ctx[4]
388#define ___bpf_ctx_cast6(x, args...) ___bpf_ctx_cast5(args), (void *)ctx[5]314#define ___bpf_ctx_cast6(x, args...) ___bpf_ctx_cast5(args), (void *)ctx[5]
389#define ___bpf_ctx_cast7(x, args...) ___bpf_ctx_cast6(args), (void *)ctx[6]315#define ___bpf_ctx_cast7(x, args...) ___bpf_ctx_cast6(args), (void *)ctx[6]
390#define ___bpf_ctx_cast8(x, args...) ___bpf_ctx_cast7(args), (void *)ctx[7]316#define ___bpf_ctx_cast8(x, args...) ___bpf_ctx_cast7(args), (void *)ctx[7]
391#define ___bpf_ctx_cast9(x, args...) ___bpf_ctx_cast8(args), (void *)ctx[8]317#define ___bpf_ctx_cast9(x, args...) ___bpf_ctx_cast8(args), (void *)ctx[8]
392#define ___bpf_ctx_cast10(x, args...) ___bpf_ctx_cast9(args), (void *)ctx[9]318#define ___bpf_ctx_cast10(x, args...) ___bpf_ctx_cast9(args), (void *)ctx[9]
393#define ___bpf_ctx_cast11(x, args...) ___bpf_ctx_cast10(args), (void *)ctx[10]319#define ___bpf_ctx_cast11(x, args...) ___bpf_ctx_cast10(args), (void *)ctx[10]
394#define ___bpf_ctx_cast12(x, args...) ___bpf_ctx_cast11(args), (void *)ctx[11]320#define ___bpf_ctx_cast12(x, args...) ___bpf_ctx_cast11(args), (void *)ctx[11]
395#define ___bpf_ctx_cast(args...) \321#define ___bpf_ctx_cast(args...) ___bpf_apply(___bpf_ctx_cast, ___bpf_narg(args))(args)
396 ___bpf_apply(___bpf_ctx_cast, ___bpf_narg(args))(args)
397 322
398/*323/*
399 * BPF_PROG is a convenience wrapper for generic tp_btf/fentry/fexit and324 * BPF_PROG is a convenience wrapper for generic tp_btf/fentry/fexit and
@@ -426,19 +351,13 @@ ____##name(unsigned long long *ctx, ##args) · 26 unmodified lines
426 351
427struct pt_regs;352struct pt_regs;
428 353
429#define ___bpf_kprobe_args0() ctx354#define ___bpf_kprobe_args0() ctx
430#define ___bpf_kprobe_args1(x) \355#define ___bpf_kprobe_args1(x) ___bpf_kprobe_args0(), (void *)PT_REGS_PARM1(ctx)
431 ___bpf_kprobe_args0(), (void *)PT_REGS_PARM1(ctx)356#define ___bpf_kprobe_args2(x, args...) ___bpf_kprobe_args1(args), (void *)PT_REGS_PARM2(ctx)
432#define ___bpf_kprobe_args2(x, args...) \357#define ___bpf_kprobe_args3(x, args...) ___bpf_kprobe_args2(args), (void *)PT_REGS_PARM3(ctx)
433 ___bpf_kprobe_args1(args), (void *)PT_REGS_PARM2(ctx)358#define ___bpf_kprobe_args4(x, args...) ___bpf_kprobe_args3(args), (void *)PT_REGS_PARM4(ctx)
434#define ___bpf_kprobe_args3(x, args...) \359#define ___bpf_kprobe_args5(x, args...) ___bpf_kprobe_args4(args), (void *)PT_REGS_PARM5(ctx)
435 ___bpf_kprobe_args2(args), (void *)PT_REGS_PARM3(ctx)360#define ___bpf_kprobe_args(args...) ___bpf_apply(___bpf_kprobe_args, ___bpf_narg(args))(args)
436#define ___bpf_kprobe_args4(x, args...) \
437 ___bpf_kprobe_args3(args), (void *)PT_REGS_PARM4(ctx)
438#define ___bpf_kprobe_args5(x, args...) \
439 ___bpf_kprobe_args4(args), (void *)PT_REGS_PARM5(ctx)
440#define ___bpf_kprobe_args(args...) \
441 ___bpf_apply(___bpf_kprobe_args, ___bpf_narg(args))(args)
442 361
443/*362/*
444 * BPF_KPROBE serves the same purpose for kprobes as BPF_PROG for363 * BPF_KPROBE serves the same purpose for kprobes as BPF_PROG for
@@ -464,11 +383,9 @@ typeof(name(0)) name(struct pt_regs *ctx) \ · 19 unmodified lines
464static __attribute__((always_inline)) typeof(name(0)) \383static __attribute__((always_inline)) typeof(name(0)) \
465____##name(struct pt_regs *ctx, ##args)384____##name(struct pt_regs *ctx, ##args)
466 385
467#define ___bpf_kretprobe_args0() ctx386#define ___bpf_kretprobe_args0() ctx
468#define ___bpf_kretprobe_args1(x) \387#define ___bpf_kretprobe_args1(x) ___bpf_kretprobe_args0(), (void *)PT_REGS_RC(ctx)
469 ___bpf_kretprobe_args0(), (void *)PT_REGS_RC(ctx)388#define ___bpf_kretprobe_args(args...) ___bpf_apply(___bpf_kretprobe_args, ___bpf_narg(args))(args)
470#define ___bpf_kretprobe_args(args...) \
471 ___bpf_apply(___bpf_kretprobe_args, ___bpf_narg(args))(args)
472 389
473/*390/*
474 * BPF_KRETPROBE is similar to BPF_KPROBE, except, it only provides optional391 * BPF_KRETPROBE is similar to BPF_KPROBE, except, it only provides optional
tools/lib/bpf/btf.h+6−0
@@ -313,12 +313,18 @@ LIBBPF_API struct btf_dump *btf_dump__new_deprecated(const struct btf *btf, · 312 unmodified lines
313 *313 *
314 * The rest works just like in case of ___libbpf_override() usage with symbol314 * The rest works just like in case of ___libbpf_override() usage with symbol
315 * versioning.315 * versioning.
316 *
317 * C++ compilers don't support __builtin_types_compatible_p(), so at least
318 * don't screw up compilation for them and let C++ users pick btf_dump__new
319 * vs btf_dump__new_deprecated explicitly.
316 */320 */
321#ifndef __cplusplus
317#define btf_dump__new(a1, a2, a3, a4) __builtin_choose_expr( \322#define btf_dump__new(a1, a2, a3, a4) __builtin_choose_expr( \
318 __builtin_types_compatible_p(typeof(a4), btf_dump_printf_fn_t) || \323 __builtin_types_compatible_p(typeof(a4), btf_dump_printf_fn_t) || \
319 __builtin_types_compatible_p(typeof(a4), void(void *, const char *, va_list)), \324 __builtin_types_compatible_p(typeof(a4), void(void *, const char *, va_list)), \
320 btf_dump__new_deprecated((void *)a1, (void *)a2, (void *)a3, (void *)a4), \325 btf_dump__new_deprecated((void *)a1, (void *)a2, (void *)a3, (void *)a4), \
321 btf_dump__new((void *)a1, (void *)a2, (void *)a3, (void *)a4))326 btf_dump__new((void *)a1, (void *)a2, (void *)a3, (void *)a4))
327#endif
322 328
323LIBBPF_API void btf_dump__free(struct btf_dump *d);329LIBBPF_API void btf_dump__free(struct btf_dump *d);
324 330
tools/lib/bpf/btf_dump.c+2−2
@@ -2321,8 +2321,8 @@ int btf_dump__dump_type_data(struct btf_dump *d, __u32 id, · 2320 unmodified lines
2321 if (!opts->indent_str)2321 if (!opts->indent_str)
2322 d->typed_dump->indent_str[0] = '\t';2322 d->typed_dump->indent_str[0] = '\t';
2323 else2323 else
2324 strncat(d->typed_dump->indent_str, opts->indent_str,2324 libbpf_strlcpy(d->typed_dump->indent_str, opts->indent_str,
2325 sizeof(d->typed_dump->indent_str) - 1);2325 sizeof(d->typed_dump->indent_str));
2326 2326
2327 d->typed_dump->compact = OPTS_GET(opts, compact, false);2327 d->typed_dump->compact = OPTS_GET(opts, compact, false);
2328 d->typed_dump->skip_names = OPTS_GET(opts, skip_names, false);2328 d->typed_dump->skip_names = OPTS_GET(opts, skip_names, false);
tools/lib/bpf/gen_loader.c+5−6
@@ -371,8 +371,9 @@ int bpf_gen__finish(struct bpf_gen *gen, int nr_progs, int nr_maps) · 370 unmodified lines
371{371{
372 int i;372 int i;
373 373
374 if (nr_progs != gen->nr_progs || nr_maps != gen->nr_maps) {374 if (nr_progs < gen->nr_progs || nr_maps != gen->nr_maps) {
375 pr_warn("progs/maps mismatch\n");375 pr_warn("nr_progs %d/%d nr_maps %d/%d mismatch\n",
376 nr_progs, gen->nr_progs, nr_maps, gen->nr_maps);
376 gen->error = -EFAULT;377 gen->error = -EFAULT;
377 return gen->error;378 return gen->error;
378 }379 }
@@ -462,8 +463,7 @@ void bpf_gen__map_create(struct bpf_gen *gen, · 83 unmodified lines
462 attr.map_flags = map_attr->map_flags;463 attr.map_flags = map_attr->map_flags;
463 attr.map_extra = map_attr->map_extra;464 attr.map_extra = map_attr->map_extra;
464 if (map_name)465 if (map_name)
465 memcpy(attr.map_name, map_name,466 libbpf_strlcpy(attr.map_name, map_name, sizeof(attr.map_name));
466 min((unsigned)strlen(map_name), BPF_OBJ_NAME_LEN - 1));
467 attr.numa_node = map_attr->numa_node;467 attr.numa_node = map_attr->numa_node;
468 attr.map_ifindex = map_attr->map_ifindex;468 attr.map_ifindex = map_attr->map_ifindex;
469 attr.max_entries = max_entries;469 attr.max_entries = max_entries;
@@ -969,8 +969,7 @@ void bpf_gen__prog_load(struct bpf_gen *gen, · 499 unmodified lines
969 core_relos = add_data(gen, gen->core_relos,969 core_relos = add_data(gen, gen->core_relos,
970 attr.core_relo_cnt * attr.core_relo_rec_size);970 attr.core_relo_cnt * attr.core_relo_rec_size);
971 971
972 memcpy(attr.prog_name, prog_name,972 libbpf_strlcpy(attr.prog_name, prog_name, sizeof(attr.prog_name));
973 min((unsigned)strlen(prog_name), BPF_OBJ_NAME_LEN - 1));
974 prog_load_attr = add_data(gen, &attr, attr_size);973 prog_load_attr = add_data(gen, &attr, attr_size);
975 974
976 /* populate union bpf_attr with a pointer to license */975 /* populate union bpf_attr with a pointer to license */
tools/lib/bpf/libbpf.c+41−44
@@ -187,42 +187,6 @@ const char *libbpf_version_string(void) · 186 unmodified lines
187#undef __S187#undef __S
188}188}
189 189
190enum kern_feature_id {
191 /* v4.14: kernel support for program & map names. */
192 FEAT_PROG_NAME,
193 /* v5.2: kernel support for global data sections. */
194 FEAT_GLOBAL_DATA,
195 /* BTF support */
196 FEAT_BTF,
197 /* BTF_KIND_FUNC and BTF_KIND_FUNC_PROTO support */
198 FEAT_BTF_FUNC,
199 /* BTF_KIND_VAR and BTF_KIND_DATASEC support */
200 FEAT_BTF_DATASEC,
201 /* BTF_FUNC_GLOBAL is supported */
202 FEAT_BTF_GLOBAL_FUNC,
203 /* BPF_F_MMAPABLE is supported for arrays */
204 FEAT_ARRAY_MMAP,
205 /* kernel support for expected_attach_type in BPF_PROG_LOAD */
206 FEAT_EXP_ATTACH_TYPE,
207 /* bpf_probe_read_{kernel,user}[_str] helpers */
208 FEAT_PROBE_READ_KERN,
209 /* BPF_PROG_BIND_MAP is supported */
210 FEAT_PROG_BIND_MAP,
211 /* Kernel support for module BTFs */
212 FEAT_MODULE_BTF,
213 /* BTF_KIND_FLOAT support */
214 FEAT_BTF_FLOAT,
215 /* BPF perf link support */
216 FEAT_PERF_LINK,
217 /* BTF_KIND_DECL_TAG support */
218 FEAT_BTF_DECL_TAG,
219 /* BTF_KIND_TYPE_TAG support */
220 FEAT_BTF_TYPE_TAG,
221 __FEAT_CNT,
222};
223
224static bool kernel_supports(const struct bpf_object *obj, enum kern_feature_id feat_id);
225
226enum reloc_type {190enum reloc_type {
227 RELO_LD64,191 RELO_LD64,
228 RELO_CALL,192 RELO_CALL,
@@ -831,11 +795,36 @@ bpf_object__add_programs(struct bpf_object *obj, Elf_Data *sec_data, · 602 unmodified lines
831 return 0;795 return 0;
832}796}
833 797
834static __u32 get_kernel_version(void)798__u32 get_kernel_version(void)
835{799{
800 /* On Ubuntu LINUX_VERSION_CODE doesn't correspond to info.release,
801 * but Ubuntu provides /proc/version_signature file, as described at
802 * https://ubuntu.com/kernel, with an example contents below, which we
803 * can use to get a proper LINUX_VERSION_CODE.
804 *
805 * Ubuntu 5.4.0-12.15-generic 5.4.8
806 *
807 * In the above, 5.4.8 is what kernel is actually expecting, while
808 * uname() call will return 5.4.0 in info.release.
809 */
810 const char *ubuntu_kver_file = "/proc/version_signature";
836 __u32 major, minor, patch;811 __u32 major, minor, patch;
837 struct utsname info;812 struct utsname info;
838 813
814 if (access(ubuntu_kver_file, R_OK) == 0) {
815 FILE *f;
816
817 f = fopen(ubuntu_kver_file, "r");
818 if (f) {
819 if (fscanf(f, "%*s %*s %d.%d.%d\n", &major, &minor, &patch) == 3) {
820 fclose(f);
821 return KERNEL_VERSION(major, minor, patch);
822 }
823 fclose(f);
824 }
825 /* something went wrong, fall back to uname() approach */
826 }
827
839 uname(&info);828 uname(&info);
840 if (sscanf(info.release, "%u.%u.%u", &major, &minor, &patch) != 3)829 if (sscanf(info.release, "%u.%u.%u", &major, &minor, &patch) != 3)
841 return 0;830 return 0;
@@ -1201,12 +1190,10 @@ static struct bpf_object *bpf_object__new(const char *path, · 359 unmodified lines
1201 1190
1202 strcpy(obj->path, path);1191 strcpy(obj->path, path);
1203 if (obj_name) {1192 if (obj_name) {
1204 strncpy(obj->name, obj_name, sizeof(obj->name) - 1);1193 libbpf_strlcpy(obj->name, obj_name, sizeof(obj->name));
1205 obj->name[sizeof(obj->name) - 1] = 0;
1206 } else {1194 } else {
1207 /* Using basename() GNU version which doesn't modify arg. */1195 /* Using basename() GNU version which doesn't modify arg. */
1208 strncpy(obj->name, basename((void *)path),1196 libbpf_strlcpy(obj->name, basename((void *)path), sizeof(obj->name));
1209 sizeof(obj->name) - 1);
1210 end = strchr(obj->name, '.');1197 end = strchr(obj->name, '.');
1211 if (end)1198 if (end)
1212 *end = 0;1199 *end = 0;
@@ -1358,7 +1345,10 @@ static int bpf_object__check_endianness(struct bpf_object *obj) · 145 unmodified lines
1358static int1345static int
1359bpf_object__init_license(struct bpf_object *obj, void *data, size_t size)1346bpf_object__init_license(struct bpf_object *obj, void *data, size_t size)
1360{1347{
1361 memcpy(obj->license, data, min(size, sizeof(obj->license) - 1));1348 /* libbpf_strlcpy() only copies first N - 1 bytes, so size + 1 won't
1349 * go over allowed ELF data section buffer
1350 */
1351 libbpf_strlcpy(obj->license, data, min(size + 1, sizeof(obj->license)));
1362 pr_debug("license of %s is %s\n", obj->path, obj->license);1352 pr_debug("license of %s is %s\n", obj->path, obj->license);
1363 return 0;1353 return 0;
1364}1354}
@@ -4354,6 +4344,10 @@ bpf_object__probe_loading(struct bpf_object *obj) · 2989 unmodified lines
4354 if (obj->gen_loader)4344 if (obj->gen_loader)
4355 return 0;4345 return 0;
4356 4346
4347 ret = bump_rlimit_memlock();
4348 if (ret)
4349 pr_warn("Failed to bump RLIMIT_MEMLOCK (err = %d), you might need to do it explicitly!\n", ret);
4350
4357 /* make sure basic loading works */4351 /* make sure basic loading works */
4358 ret = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, NULL, "GPL", insns, insn_cnt, NULL);4352 ret = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, NULL, "GPL", insns, insn_cnt, NULL);
4359 if (ret < 0)4353 if (ret < 0)
@@ -4720,14 +4714,17 @@ static struct kern_feature_desc { · 360 unmodified lines
4720 [FEAT_BTF_TYPE_TAG] = {4714 [FEAT_BTF_TYPE_TAG] = {
4721 "BTF_KIND_TYPE_TAG support", probe_kern_btf_type_tag,4715 "BTF_KIND_TYPE_TAG support", probe_kern_btf_type_tag,
4722 },4716 },
4717 [FEAT_MEMCG_ACCOUNT] = {
4718 "memcg-based memory accounting", probe_memcg_account,
4719 },
4723};4720};
4724 4721
4725static bool kernel_supports(const struct bpf_object *obj, enum kern_feature_id feat_id)4722bool kernel_supports(const struct bpf_object *obj, enum kern_feature_id feat_id)
4726{4723{
4727 struct kern_feature_desc *feat = &feature_probes[feat_id];4724 struct kern_feature_desc *feat = &feature_probes[feat_id];
4728 int ret;4725 int ret;
4729 4726
4730 if (obj->gen_loader)4727 if (obj && obj->gen_loader)
4731 /* To generate loader program assume the latest kernel4728 /* To generate loader program assume the latest kernel
4732 * to avoid doing extra prog_load, map_create syscalls.4729 * to avoid doing extra prog_load, map_create syscalls.
4733 */4730 */
tools/lib/bpf/libbpf.h+73−4
@@ -227,6 +227,7 @@ struct btf; · 226 unmodified lines
227LIBBPF_API struct btf *bpf_object__btf(const struct bpf_object *obj);227LIBBPF_API struct btf *bpf_object__btf(const struct bpf_object *obj);
228LIBBPF_API int bpf_object__btf_fd(const struct bpf_object *obj);228LIBBPF_API int bpf_object__btf_fd(const struct bpf_object *obj);
229 229
230LIBBPF_DEPRECATED_SINCE(0, 7, "use bpf_object__find_program_by_name() instead")
230LIBBPF_API struct bpf_program *231LIBBPF_API struct bpf_program *
231bpf_object__find_program_by_title(const struct bpf_object *obj,232bpf_object__find_program_by_title(const struct bpf_object *obj,
232 const char *title);233 const char *title);
@@ -339,7 +340,31 @@ LIBBPF_DEPRECATED_SINCE(0, 7, "multi-instance bpf_program support is deprecated" · 106 unmodified lines
339LIBBPF_API int bpf_program__unpin_instance(struct bpf_program *prog,340LIBBPF_API int bpf_program__unpin_instance(struct bpf_program *prog,
340 const char *path,341 const char *path,
341 int instance);342 int instance);
343
344/**
345 * @brief **bpf_program__pin()** pins the BPF program to a file
346 * in the BPF FS specified by a path. This increments the programs
347 * reference count, allowing it to stay loaded after the process
348 * which loaded it has exited.
349 *
350 * @param prog BPF program to pin, must already be loaded
351 * @param path file path in a BPF file system
352 * @return 0, on success; negative error code, otherwise
353 */
342LIBBPF_API int bpf_program__pin(struct bpf_program *prog, const char *path);354LIBBPF_API int bpf_program__pin(struct bpf_program *prog, const char *path);
355
356/**
357 * @brief **bpf_program__unpin()** unpins the BPF program from a file
358 * in the BPFFS specified by a path. This decrements the programs
359 * reference count.
360 *
361 * The file pinning the BPF program can also be unlinked by a different
362 * process in which case this function will return an error.
363 *
364 * @param prog BPF program to unpin
365 * @param path file path to the pin in a BPF file system
366 * @return 0, on success; negative error code, otherwise
367 */
343LIBBPF_API int bpf_program__unpin(struct bpf_program *prog, const char *path);368LIBBPF_API int bpf_program__unpin(struct bpf_program *prog, const char *path);
344LIBBPF_API void bpf_program__unload(struct bpf_program *prog);369LIBBPF_API void bpf_program__unload(struct bpf_program *prog);
345 370
@@ -1027,13 +1052,57 @@ bpf_prog_linfo__lfind(const struct bpf_prog_linfo *prog_linfo, · 681 unmodified lines
1027 * user, causing subsequent probes to fail. In this case, the caller may want1052 * user, causing subsequent probes to fail. In this case, the caller may want
1028 * to adjust that limit with setrlimit().1053 * to adjust that limit with setrlimit().
1029 */1054 */
1030LIBBPF_API bool bpf_probe_prog_type(enum bpf_prog_type prog_type,1055LIBBPF_DEPRECATED_SINCE(0, 8, "use libbpf_probe_bpf_prog_type() instead")
1031 __u32 ifindex);1056LIBBPF_API bool bpf_probe_prog_type(enum bpf_prog_type prog_type, __u32 ifindex);
1057LIBBPF_DEPRECATED_SINCE(0, 8, "use libbpf_probe_bpf_map_type() instead")
1032LIBBPF_API bool bpf_probe_map_type(enum bpf_map_type map_type, __u32 ifindex);1058LIBBPF_API bool bpf_probe_map_type(enum bpf_map_type map_type, __u32 ifindex);
1033LIBBPF_API bool bpf_probe_helper(enum bpf_func_id id,1059LIBBPF_DEPRECATED_SINCE(0, 8, "use libbpf_probe_bpf_helper() instead")
1034 enum bpf_prog_type prog_type, __u32 ifindex);1060LIBBPF_API bool bpf_probe_helper(enum bpf_func_id id, enum bpf_prog_type prog_type, __u32 ifindex);
1061LIBBPF_DEPRECATED_SINCE(0, 8, "implement your own or use bpftool for feature detection")
1035LIBBPF_API bool bpf_probe_large_insn_limit(__u32 ifindex);1062LIBBPF_API bool bpf_probe_large_insn_limit(__u32 ifindex);
1036 1063
1064/**
1065 * @brief **libbpf_probe_bpf_prog_type()** detects if host kernel supports
1066 * BPF programs of a given type.
1067 * @param prog_type BPF program type to detect kernel support for
1068 * @param opts reserved for future extensibility, should be NULL
1069 * @return 1, if given program type is supported; 0, if given program type is
1070 * not supported; negative error code if feature detection failed or can't be
1071 * performed
1072 *
1073 * Make sure the process has required set of CAP_* permissions (or runs as
1074 * root) when performing feature checking.
1075 */
1076LIBBPF_API int libbpf_probe_bpf_prog_type(enum bpf_prog_type prog_type, const void *opts);
1077/**
1078 * @brief **libbpf_probe_bpf_map_type()** detects if host kernel supports
1079 * BPF maps of a given type.
1080 * @param map_type BPF map type to detect kernel support for
1081 * @param opts reserved for future extensibility, should be NULL
1082 * @return 1, if given map type is supported; 0, if given map type is
1083 * not supported; negative error code if feature detection failed or can't be
1084 * performed
1085 *
1086 * Make sure the process has required set of CAP_* permissions (or runs as
1087 * root) when performing feature checking.
1088 */
1089LIBBPF_API int libbpf_probe_bpf_map_type(enum bpf_map_type map_type, const void *opts);
1090/**
1091 * @brief **libbpf_probe_bpf_helper()** detects if host kernel supports the
1092 * use of a given BPF helper from specified BPF program type.
1093 * @param prog_type BPF program type used to check the support of BPF helper
1094 * @param helper_id BPF helper ID (enum bpf_func_id) to check support for
1095 * @param opts reserved for future extensibility, should be NULL
1096 * @return 1, if given combination of program type and helper is supported; 0,
1097 * if the combination is not supported; negative error code if feature
1098 * detection for provided input arguments failed or can't be performed
1099 *
1100 * Make sure the process has required set of CAP_* permissions (or runs as
1101 * root) when performing feature checking.
1102 */
1103LIBBPF_API int libbpf_probe_bpf_helper(enum bpf_prog_type prog_type,
1104 enum bpf_func_id helper_id, const void *opts);
1105
1037/*1106/*
1038 * Get bpf_prog_info in continuous memory1107 * Get bpf_prog_info in continuous memory
1039 *1108 *
tools/lib/bpf/libbpf.map+4−0
@@ -427,4 +427,8 @@ LIBBPF_0.7.0 { · 426 unmodified lines
427 bpf_program__log_level;427 bpf_program__log_level;
428 bpf_program__set_log_buf;428 bpf_program__set_log_buf;
429 bpf_program__set_log_level;429 bpf_program__set_log_level;
430 libbpf_probe_bpf_helper;
431 libbpf_probe_bpf_map_type;
432 libbpf_probe_bpf_prog_type;
433 libbpf_set_memlock_rlim_max;
430};434};
tools/lib/bpf/libbpf_internal.h+60−0
@@ -169,6 +169,27 @@ static inline void *libbpf_reallocarray(void *ptr, size_t nmemb, size_t size) · 168 unmodified lines
169 return realloc(ptr, total);169 return realloc(ptr, total);
170}170}
171 171
172/* Copy up to sz - 1 bytes from zero-terminated src string and ensure that dst
173 * is zero-terminated string no matter what (unless sz == 0, in which case
174 * it's a no-op). It's conceptually close to FreeBSD's strlcpy(), but differs
175 * in what is returned. Given this is internal helper, it's trivial to extend
176 * this, when necessary. Use this instead of strncpy inside libbpf source code.
177 */
178static inline void libbpf_strlcpy(char *dst, const char *src, size_t sz)
179{
180 size_t i;
181
182 if (sz == 0)
183 return;
184
185 sz--;
186 for (i = 0; i < sz && src[i]; i++)
187 dst[i] = src[i];
188 dst[i] = '\0';
189}
190
191__u32 get_kernel_version(void);
192
172struct btf;193struct btf;
173struct btf_type;194struct btf_type;
174 195
@@ -272,6 +293,45 @@ static inline bool libbpf_validate_opts(const char *opts, · 97 unmodified lines
272 (opts)->sz - __off); \293 (opts)->sz - __off); \
273})294})
274 295
296enum kern_feature_id {
297 /* v4.14: kernel support for program & map names. */
298 FEAT_PROG_NAME,
299 /* v5.2: kernel support for global data sections. */
300 FEAT_GLOBAL_DATA,
301 /* BTF support */
302 FEAT_BTF,
303 /* BTF_KIND_FUNC and BTF_KIND_FUNC_PROTO support */
304 FEAT_BTF_FUNC,
305 /* BTF_KIND_VAR and BTF_KIND_DATASEC support */
306 FEAT_BTF_DATASEC,
307 /* BTF_FUNC_GLOBAL is supported */
308 FEAT_BTF_GLOBAL_FUNC,
309 /* BPF_F_MMAPABLE is supported for arrays */
310 FEAT_ARRAY_MMAP,
311 /* kernel support for expected_attach_type in BPF_PROG_LOAD */
312 FEAT_EXP_ATTACH_TYPE,
313 /* bpf_probe_read_{kernel,user}[_str] helpers */
314 FEAT_PROBE_READ_KERN,
315 /* BPF_PROG_BIND_MAP is supported */
316 FEAT_PROG_BIND_MAP,
317 /* Kernel support for module BTFs */
318 FEAT_MODULE_BTF,
319 /* BTF_KIND_FLOAT support */
320 FEAT_BTF_FLOAT,
321 /* BPF perf link support */
322 FEAT_PERF_LINK,
323 /* BTF_KIND_DECL_TAG support */
324 FEAT_BTF_DECL_TAG,
325 /* BTF_KIND_TYPE_TAG support */
326 FEAT_BTF_TYPE_TAG,
327 /* memcg-based accounting for BPF maps and progs */
328 FEAT_MEMCG_ACCOUNT,
329 __FEAT_CNT,
330};
331
332int probe_memcg_account(void);
333bool kernel_supports(const struct bpf_object *obj, enum kern_feature_id feat_id);
334int bump_rlimit_memlock(void);
275 335
276int parse_cpu_mask_str(const char *s, bool **mask, int *mask_sz);336int parse_cpu_mask_str(const char *s, bool **mask, int *mask_sz);
277int parse_cpu_mask_file(const char *fcpu, bool **mask, int *mask_sz);337int parse_cpu_mask_file(const char *fcpu, bool **mask, int *mask_sz);
tools/lib/bpf/libbpf_legacy.h+11−1
@@ -45,7 +45,6 @@ enum libbpf_strict_mode { · 44 unmodified lines
45 * (positive) error code.45 * (positive) error code.
46 */46 */
47 LIBBPF_STRICT_DIRECT_ERRS = 0x02,47 LIBBPF_STRICT_DIRECT_ERRS = 0x02,
48
49 /*48 /*
50 * Enforce strict BPF program section (SEC()) names.49 * Enforce strict BPF program section (SEC()) names.
51 * E.g., while prefiously SEC("xdp_whatever") or SEC("perf_event_blah") were50 * E.g., while prefiously SEC("xdp_whatever") or SEC("perf_event_blah") were
@@ -63,6 +62,17 @@ enum libbpf_strict_mode { · 11 unmodified lines
63 * Clients can maintain it on their own if it is valuable for them.62 * Clients can maintain it on their own if it is valuable for them.
64 */63 */
65 LIBBPF_STRICT_NO_OBJECT_LIST = 0x08,64 LIBBPF_STRICT_NO_OBJECT_LIST = 0x08,
65 /*
66 * Automatically bump RLIMIT_MEMLOCK using setrlimit() before the
67 * first BPF program or map creation operation. This is done only if
68 * kernel is too old to support memcg-based memory accounting for BPF
69 * subsystem. By default, RLIMIT_MEMLOCK limit is set to RLIM_INFINITY,
70 * but it can be overriden with libbpf_set_memlock_rlim_max() API.
71 * Note that libbpf_set_memlock_rlim_max() needs to be called before
72 * the very first bpf_prog_load(), bpf_map_create() or bpf_object__load()
73 * operation.
74 */
75 LIBBPF_STRICT_AUTO_RLIMIT_MEMLOCK = 0x10,
66 76
67 __LIBBPF_STRICT_LAST,77 __LIBBPF_STRICT_LAST,
68};78};
tools/lib/bpf/libbpf_probes.c+185−66
@@ -48,28 +48,20 @@ static int get_vendor_id(int ifindex) · 47 unmodified lines
48 return strtol(buf, NULL, 0);48 return strtol(buf, NULL, 0);
49}49}
50 50
51static int get_kernel_version(void)51static int probe_prog_load(enum bpf_prog_type prog_type,
52 const struct bpf_insn *insns, size_t insns_cnt,
53 char *log_buf, size_t log_buf_sz,
54 __u32 ifindex)
52{55{
53 int version, subversion, patchlevel;56 LIBBPF_OPTS(bpf_prog_load_opts, opts,
54 struct utsname utsn;57 .log_buf = log_buf,
55 58 .log_size = log_buf_sz,
56 /* Return 0 on failure, and attempt to probe with empty kversion */59 .log_level = log_buf ? 1 : 0,
57 if (uname(&utsn))60 .prog_ifindex = ifindex,
58 return 0;61 );
59 62 int fd, err, exp_err = 0;
60 if (sscanf(utsn.release, "%d.%d.%d",63 const char *exp_msg = NULL;
61 &version, &subversion, &patchlevel) != 3)64 char buf[4096];
62 return 0;
63
64 return (version << 16) + (subversion << 8) + patchlevel;
65}
66
67static void
68probe_load(enum bpf_prog_type prog_type, const struct bpf_insn *insns,
69 size_t insns_cnt, char *buf, size_t buf_len, __u32 ifindex)
70{
71 LIBBPF_OPTS(bpf_prog_load_opts, opts);
72 int fd;
73 65
74 switch (prog_type) {66 switch (prog_type) {
75 case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:67 case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
@@ -84,6 +76,38 @@ probe_load(enum bpf_prog_type prog_type, const struct bpf_insn *insns, · 8 unmodified lines
84 case BPF_PROG_TYPE_KPROBE:76 case BPF_PROG_TYPE_KPROBE:
85 opts.kern_version = get_kernel_version();77 opts.kern_version = get_kernel_version();
86 break;78 break;
79 case BPF_PROG_TYPE_LIRC_MODE2:
80 opts.expected_attach_type = BPF_LIRC_MODE2;
81 break;
82 case BPF_PROG_TYPE_TRACING:
83 case BPF_PROG_TYPE_LSM:
84 opts.log_buf = buf;
85 opts.log_size = sizeof(buf);
86 opts.log_level = 1;
87 if (prog_type == BPF_PROG_TYPE_TRACING)
88 opts.expected_attach_type = BPF_TRACE_FENTRY;
89 else
90 opts.expected_attach_type = BPF_MODIFY_RETURN;
91 opts.attach_btf_id = 1;
92
93 exp_err = -EINVAL;
94 exp_msg = "attach_btf_id 1 is not a function";
95 break;
96 case BPF_PROG_TYPE_EXT:
97 opts.log_buf = buf;
98 opts.log_size = sizeof(buf);
99 opts.log_level = 1;
100 opts.attach_btf_id = 1;
101
102 exp_err = -EINVAL;
103 exp_msg = "Cannot replace kernel functions";
104 break;
105 case BPF_PROG_TYPE_SYSCALL:
106 opts.prog_flags = BPF_F_SLEEPABLE;
107 break;
108 case BPF_PROG_TYPE_STRUCT_OPS:
109 exp_err = -524; /* -ENOTSUPP */
110 break;
87 case BPF_PROG_TYPE_UNSPEC:111 case BPF_PROG_TYPE_UNSPEC:
88 case BPF_PROG_TYPE_SOCKET_FILTER:112 case BPF_PROG_TYPE_SOCKET_FILTER:
89 case BPF_PROG_TYPE_SCHED_CLS:113 case BPF_PROG_TYPE_SCHED_CLS:
@@ -103,25 +127,42 @@ probe_load(enum bpf_prog_type prog_type, const struct bpf_insn *insns, · 13 unmodified lines
103 case BPF_PROG_TYPE_RAW_TRACEPOINT:127 case BPF_PROG_TYPE_RAW_TRACEPOINT:
104 case BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE:128 case BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE:
105 case BPF_PROG_TYPE_LWT_SEG6LOCAL:129 case BPF_PROG_TYPE_LWT_SEG6LOCAL:
106 case BPF_PROG_TYPE_LIRC_MODE2:
107 case BPF_PROG_TYPE_SK_REUSEPORT:130 case BPF_PROG_TYPE_SK_REUSEPORT:
108 case BPF_PROG_TYPE_FLOW_DISSECTOR:131 case BPF_PROG_TYPE_FLOW_DISSECTOR:
109 case BPF_PROG_TYPE_CGROUP_SYSCTL:132 case BPF_PROG_TYPE_CGROUP_SYSCTL:
110 case BPF_PROG_TYPE_TRACING:
111 case BPF_PROG_TYPE_STRUCT_OPS:
112 case BPF_PROG_TYPE_EXT:
113 case BPF_PROG_TYPE_LSM:
114 default:
115 break;133 break;
134 default:
135 return -EOPNOTSUPP;
116 }136 }
117 137
118 opts.prog_ifindex = ifindex;138 fd = bpf_prog_load(prog_type, NULL, "GPL", insns, insns_cnt, &opts);
119 opts.log_buf = buf;139 err = -errno;
120 opts.log_size = buf_len;
121
122 fd = bpf_prog_load(prog_type, NULL, "GPL", insns, insns_cnt, NULL);
123 if (fd >= 0)140 if (fd >= 0)
124 close(fd);141 close(fd);
142 if (exp_err) {
143 if (fd >= 0 || err != exp_err)
144 return 0;
145 if (exp_msg && !strstr(buf, exp_msg))
146 return 0;
147 return 1;
148 }
149 return fd >= 0 ? 1 : 0;
150}
151
152int libbpf_probe_bpf_prog_type(enum bpf_prog_type prog_type, const void *opts)
153{
154 struct bpf_insn insns[] = {
155 BPF_MOV64_IMM(BPF_REG_0, 0),
156 BPF_EXIT_INSN()
157 };
158 const size_t insn_cnt = ARRAY_SIZE(insns);
159 int ret;
160
161 if (opts)
162 return libbpf_err(-EINVAL);
163
164 ret = probe_prog_load(prog_type, insns, insn_cnt, NULL, 0, 0);
165 return libbpf_err(ret);
125}166}
126 167
127bool bpf_probe_prog_type(enum bpf_prog_type prog_type, __u32 ifindex)168bool bpf_probe_prog_type(enum bpf_prog_type prog_type, __u32 ifindex)
@@ -131,12 +172,16 @@ bool bpf_probe_prog_type(enum bpf_prog_type prog_type, __u32 ifindex) · 3 unmodified lines
131 BPF_EXIT_INSN()172 BPF_EXIT_INSN()
132 };173 };
133 174
175 /* prefer libbpf_probe_bpf_prog_type() unless offload is requested */
176 if (ifindex == 0)
177 return libbpf_probe_bpf_prog_type(prog_type, NULL) == 1;
178
134 if (ifindex && prog_type == BPF_PROG_TYPE_SCHED_CLS)179 if (ifindex && prog_type == BPF_PROG_TYPE_SCHED_CLS)
135 /* nfp returns -EINVAL on exit(0) with TC offload */180 /* nfp returns -EINVAL on exit(0) with TC offload */
136 insns[0].imm = 2;181 insns[0].imm = 2;
137 182
138 errno = 0;183 errno = 0;
139 probe_load(prog_type, insns, ARRAY_SIZE(insns), NULL, 0, ifindex);184 probe_prog_load(prog_type, insns, ARRAY_SIZE(insns), NULL, 0, ifindex);
140 185
141 return errno != EINVAL && errno != EOPNOTSUPP;186 return errno != EINVAL && errno != EOPNOTSUPP;
142}187}
@@ -197,16 +242,18 @@ static int load_local_storage_btf(void) · 54 unmodified lines
197 strs, sizeof(strs));242 strs, sizeof(strs));
198}243}
199 244
200bool bpf_probe_map_type(enum bpf_map_type map_type, __u32 ifindex)245static int probe_map_create(enum bpf_map_type map_type, __u32 ifindex)
201{246{
202 int key_size, value_size, max_entries, map_flags;247 LIBBPF_OPTS(bpf_map_create_opts, opts);
248 int key_size, value_size, max_entries;
203 __u32 btf_key_type_id = 0, btf_value_type_id = 0;249 __u32 btf_key_type_id = 0, btf_value_type_id = 0;
204 int fd = -1, btf_fd = -1, fd_inner;250 int fd = -1, btf_fd = -1, fd_inner = -1, exp_err = 0, err;
251
252 opts.map_ifindex = ifindex;
205 253
206 key_size = sizeof(__u32);254 key_size = sizeof(__u32);
207 value_size = sizeof(__u32);255 value_size = sizeof(__u32);
208 max_entries = 1;256 max_entries = 1;
209 map_flags = 0;
210 257
211 switch (map_type) {258 switch (map_type) {
212 case BPF_MAP_TYPE_STACK_TRACE:259 case BPF_MAP_TYPE_STACK_TRACE:
@@ -215,7 +262,7 @@ bool bpf_probe_map_type(enum bpf_map_type map_type, __u32 ifindex) · 2 unmodified lines
215 case BPF_MAP_TYPE_LPM_TRIE:262 case BPF_MAP_TYPE_LPM_TRIE:
216 key_size = sizeof(__u64);263 key_size = sizeof(__u64);
217 value_size = sizeof(__u64);264 value_size = sizeof(__u64);
218 map_flags = BPF_F_NO_PREALLOC;265 opts.map_flags = BPF_F_NO_PREALLOC;
219 break;266 break;
220 case BPF_MAP_TYPE_CGROUP_STORAGE:267 case BPF_MAP_TYPE_CGROUP_STORAGE:
221 case BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE:268 case BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE:
@@ -234,17 +281,25 @@ bool bpf_probe_map_type(enum bpf_map_type map_type, __u32 ifindex) · 12 unmodified lines
234 btf_value_type_id = 3;281 btf_value_type_id = 3;
235 value_size = 8;282 value_size = 8;
236 max_entries = 0;283 max_entries = 0;
237 map_flags = BPF_F_NO_PREALLOC;284 opts.map_flags = BPF_F_NO_PREALLOC;
238 btf_fd = load_local_storage_btf();285 btf_fd = load_local_storage_btf();
239 if (btf_fd < 0)286 if (btf_fd < 0)
240 return false;287 return btf_fd;
241 break;288 break;
242 case BPF_MAP_TYPE_RINGBUF:289 case BPF_MAP_TYPE_RINGBUF:
243 key_size = 0;290 key_size = 0;
244 value_size = 0;291 value_size = 0;
245 max_entries = 4096;292 max_entries = 4096;
246 break;293 break;
247 case BPF_MAP_TYPE_UNSPEC:294 case BPF_MAP_TYPE_STRUCT_OPS:
295 /* we'll get -ENOTSUPP for invalid BTF type ID for struct_ops */
296 opts.btf_vmlinux_value_type_id = 1;
297 exp_err = -524; /* -ENOTSUPP */
298 break;
299 case BPF_MAP_TYPE_BLOOM_FILTER:
300 key_size = 0;
301 max_entries = 1;
302 break;
248 case BPF_MAP_TYPE_HASH:303 case BPF_MAP_TYPE_HASH:
249 case BPF_MAP_TYPE_ARRAY:304 case BPF_MAP_TYPE_ARRAY:
250 case BPF_MAP_TYPE_PROG_ARRAY:305 case BPF_MAP_TYPE_PROG_ARRAY:
@@ -263,49 +318,114 @@ bool bpf_probe_map_type(enum bpf_map_type map_type, __u32 ifindex) · 12 unmodified lines
263 case BPF_MAP_TYPE_XSKMAP:318 case BPF_MAP_TYPE_XSKMAP:
264 case BPF_MAP_TYPE_SOCKHASH:319 case BPF_MAP_TYPE_SOCKHASH:
265 case BPF_MAP_TYPE_REUSEPORT_SOCKARRAY:320 case BPF_MAP_TYPE_REUSEPORT_SOCKARRAY:
266 case BPF_MAP_TYPE_STRUCT_OPS:
267 default:
268 break;321 break;
322 case BPF_MAP_TYPE_UNSPEC:
323 default:
324 return -EOPNOTSUPP;
269 }325 }
270 326
271 if (map_type == BPF_MAP_TYPE_ARRAY_OF_MAPS ||327 if (map_type == BPF_MAP_TYPE_ARRAY_OF_MAPS ||
272 map_type == BPF_MAP_TYPE_HASH_OF_MAPS) {328 map_type == BPF_MAP_TYPE_HASH_OF_MAPS) {
273 LIBBPF_OPTS(bpf_map_create_opts, opts);
274
275 /* TODO: probe for device, once libbpf has a function to create329 /* TODO: probe for device, once libbpf has a function to create
276 * map-in-map for offload330 * map-in-map for offload
277 */331 */
278 if (ifindex)332 if (ifindex)
279 return false;333 goto cleanup;
280 334
281 fd_inner = bpf_map_create(BPF_MAP_TYPE_HASH, NULL,335 fd_inner = bpf_map_create(BPF_MAP_TYPE_HASH, NULL,
282 sizeof(__u32), sizeof(__u32), 1, NULL);336 sizeof(__u32), sizeof(__u32), 1, NULL);
283 if (fd_inner < 0)337 if (fd_inner < 0)
284 return false;338 goto cleanup;
285 339
286 opts.inner_map_fd = fd_inner;340 opts.inner_map_fd = fd_inner;
287 fd = bpf_map_create(map_type, NULL, sizeof(__u32), sizeof(__u32), 1, &opts);341 }
288 close(fd_inner);
289 } else {
290 LIBBPF_OPTS(bpf_map_create_opts, opts);
291
292 /* Note: No other restriction on map type probes for offload */
293 opts.map_flags = map_flags;
294 opts.map_ifindex = ifindex;
295 if (btf_fd >= 0) {
296 opts.btf_fd = btf_fd;
297 opts.btf_key_type_id = btf_key_type_id;
298 opts.btf_value_type_id = btf_value_type_id;
299 }
300 342
301 fd = bpf_map_create(map_type, NULL, key_size, value_size, max_entries, &opts);343 if (btf_fd >= 0) {
344 opts.btf_fd = btf_fd;
345 opts.btf_key_type_id = btf_key_type_id;
346 opts.btf_value_type_id = btf_value_type_id;
302 }347 }
348
349 fd = bpf_map_create(map_type, NULL, key_size, value_size, max_entries, &opts);
350 err = -errno;
351
352cleanup:
303 if (fd >= 0)353 if (fd >= 0)
304 close(fd);354 close(fd);
355 if (fd_inner >= 0)
356 close(fd_inner);
305 if (btf_fd >= 0)357 if (btf_fd >= 0)
306 close(btf_fd);358 close(btf_fd);
307 359
308 return fd >= 0;360 if (exp_err)
361 return fd < 0 && err == exp_err ? 1 : 0;
362 else
363 return fd >= 0 ? 1 : 0;
364}
365
366int libbpf_probe_bpf_map_type(enum bpf_map_type map_type, const void *opts)
367{
368 int ret;
369
370 if (opts)
371 return libbpf_err(-EINVAL);
372
373 ret = probe_map_create(map_type, 0);
374 return libbpf_err(ret);
375}
376
377bool bpf_probe_map_type(enum bpf_map_type map_type, __u32 ifindex)
378{
379 return probe_map_create(map_type, ifindex) == 1;
380}
381
382int libbpf_probe_bpf_helper(enum bpf_prog_type prog_type, enum bpf_func_id helper_id,
383 const void *opts)
384{
385 struct bpf_insn insns[] = {
386 BPF_EMIT_CALL((__u32)helper_id),
387 BPF_EXIT_INSN(),
388 };
389 const size_t insn_cnt = ARRAY_SIZE(insns);
390 char buf[4096];
391 int ret;
392
393 if (opts)
394 return libbpf_err(-EINVAL);
395
396 /* we can't successfully load all prog types to check for BPF helper
397 * support, so bail out with -EOPNOTSUPP error
398 */
399 switch (prog_type) {
400 case BPF_PROG_TYPE_TRACING:
401 case BPF_PROG_TYPE_EXT:
402 case BPF_PROG_TYPE_LSM:
403 case BPF_PROG_TYPE_STRUCT_OPS:
404 return -EOPNOTSUPP;
405 default:
406 break;
407 }
408
409 buf[0] = '\0';
410 ret = probe_prog_load(prog_type, insns, insn_cnt, buf, sizeof(buf), 0);
411 if (ret < 0)
412 return libbpf_err(ret);
413
414 /* If BPF verifier doesn't recognize BPF helper ID (enum bpf_func_id)
415 * at all, it will emit something like "invalid func unknown#181".
416 * If BPF verifier recognizes BPF helper but it's not supported for
417 * given BPF program type, it will emit "unknown func bpf_sys_bpf#166".
418 * In both cases, provided combination of BPF program type and BPF
419 * helper is not supported by the kernel.
420 * In all other cases, probe_prog_load() above will either succeed (e.g.,
421 * because BPF helper happens to accept no input arguments or it
422 * accepts one input argument and initial PTR_TO_CTX is fine for
423 * that), or we'll get some more specific BPF verifier error about
424 * some unsatisfied conditions.
425 */
426 if (ret == 0 && (strstr(buf, "invalid func ") || strstr(buf, "unknown func ")))
427 return 0;
428 return 1; /* assume supported */
309}429}
310 430
311bool bpf_probe_helper(enum bpf_func_id id, enum bpf_prog_type prog_type,431bool bpf_probe_helper(enum bpf_func_id id, enum bpf_prog_type prog_type,
@@ -318,8 +438,7 @@ bool bpf_probe_helper(enum bpf_func_id id, enum bpf_prog_type prog_type, · 6 unmodified lines
318 char buf[4096] = {};438 char buf[4096] = {};
319 bool res;439 bool res;
320 440
321 probe_load(prog_type, insns, ARRAY_SIZE(insns), buf, sizeof(buf),441 probe_prog_load(prog_type, insns, ARRAY_SIZE(insns), buf, sizeof(buf), ifindex);
322 ifindex);
323 res = !grep(buf, "invalid func ") && !grep(buf, "unknown func ");442 res = !grep(buf, "invalid func ") && !grep(buf, "unknown func ");
324 443
325 if (ifindex) {444 if (ifindex) {
@@ -351,8 +470,8 @@ bool bpf_probe_large_insn_limit(__u32 ifindex) · 25 unmodified lines
351 insns[BPF_MAXINSNS] = BPF_EXIT_INSN();470 insns[BPF_MAXINSNS] = BPF_EXIT_INSN();
352 471
353 errno = 0;472 errno = 0;
354 probe_load(BPF_PROG_TYPE_SCHED_CLS, insns, ARRAY_SIZE(insns), NULL, 0,473 probe_prog_load(BPF_PROG_TYPE_SCHED_CLS, insns, ARRAY_SIZE(insns), NULL, 0,
355 ifindex);474 ifindex);
356 475
357 return errno != E2BIG && errno != EINVAL;476 return errno != E2BIG && errno != EINVAL;
358}477}
tools/lib/bpf/relo_core.c+15−5
@@ -709,10 +709,14 @@ static int bpf_core_calc_field_relo(const char *prog_name, · 708 unmodified lines
709 709
710static int bpf_core_calc_type_relo(const struct bpf_core_relo *relo,710static int bpf_core_calc_type_relo(const struct bpf_core_relo *relo,
711 const struct bpf_core_spec *spec,711 const struct bpf_core_spec *spec,
712 __u32 *val)712 __u32 *val, bool *validate)
713{713{
714 __s64 sz;714 __s64 sz;
715 715
716 /* by default, always check expected value in bpf_insn */
717 if (validate)
718 *validate = true;
719
716 /* type-based relos return zero when target type is not found */720 /* type-based relos return zero when target type is not found */
717 if (!spec) {721 if (!spec) {
718 *val = 0;722 *val = 0;
@@ -722,6 +726,11 @@ static int bpf_core_calc_type_relo(const struct bpf_core_relo *relo, · 3 unmodified lines
722 switch (relo->kind) {726 switch (relo->kind) {
723 case BPF_CORE_TYPE_ID_TARGET:727 case BPF_CORE_TYPE_ID_TARGET:
724 *val = spec->root_type_id;728 *val = spec->root_type_id;
729 /* type ID, embedded in bpf_insn, might change during linking,
730 * so enforcing it is pointless
731 */
732 if (validate)
733 *validate = false;
725 break;734 break;
726 case BPF_CORE_TYPE_EXISTS:735 case BPF_CORE_TYPE_EXISTS:
727 *val = 1;736 *val = 1;
@@ -861,8 +870,8 @@ static int bpf_core_calc_relo(const char *prog_name, · 133 unmodified lines
861 res->fail_memsz_adjust = true;870 res->fail_memsz_adjust = true;
862 }871 }
863 } else if (core_relo_is_type_based(relo->kind)) {872 } else if (core_relo_is_type_based(relo->kind)) {
864 err = bpf_core_calc_type_relo(relo, local_spec, &res->orig_val);873 err = bpf_core_calc_type_relo(relo, local_spec, &res->orig_val, &res->validate);
865 err = err ?: bpf_core_calc_type_relo(relo, targ_spec, &res->new_val);874 err = err ?: bpf_core_calc_type_relo(relo, targ_spec, &res->new_val, NULL);
866 } else if (core_relo_is_enumval_based(relo->kind)) {875 } else if (core_relo_is_enumval_based(relo->kind)) {
867 err = bpf_core_calc_enumval_relo(relo, local_spec, &res->orig_val);876 err = bpf_core_calc_enumval_relo(relo, local_spec, &res->orig_val);
868 err = err ?: bpf_core_calc_enumval_relo(relo, targ_spec, &res->new_val);877 err = err ?: bpf_core_calc_enumval_relo(relo, targ_spec, &res->new_val);
@@ -1213,7 +1222,9 @@ int bpf_core_apply_relo_insn(const char *prog_name, struct bpf_insn *insn, · 344 unmodified lines
1213 1222
1214 /* TYPE_ID_LOCAL relo is special and doesn't need candidate search */1223 /* TYPE_ID_LOCAL relo is special and doesn't need candidate search */
1215 if (relo->kind == BPF_CORE_TYPE_ID_LOCAL) {1224 if (relo->kind == BPF_CORE_TYPE_ID_LOCAL) {
1216 targ_res.validate = true;1225 /* bpf_insn's imm value could get out of sync during linking */
1226 memset(&targ_res, 0, sizeof(targ_res));
1227 targ_res.validate = false;
1217 targ_res.poison = false;1228 targ_res.poison = false;
1218 targ_res.orig_val = local_spec->root_type_id;1229 targ_res.orig_val = local_spec->root_type_id;
1219 targ_res.new_val = local_spec->root_type_id;1230 targ_res.new_val = local_spec->root_type_id;
@@ -1227,7 +1238,6 @@ int bpf_core_apply_relo_insn(const char *prog_name, struct bpf_insn *insn, · 7 unmodified lines
1227 return -EOPNOTSUPP;1238 return -EOPNOTSUPP;
1228 }1239 }
1229 1240
1230
1231 for (i = 0, j = 0; i < cands->len; i++) {1241 for (i = 0, j = 0; i < cands->len; i++) {
1232 err = bpf_core_spec_match(local_spec, cands->cands[i].btf,1242 err = bpf_core_spec_match(local_spec, cands->cands[i].btf,
1233 cands->cands[i].id, cand_spec);1243 cands->cands[i].id, cand_spec);
tools/lib/bpf/xsk.c+3−6
@@ -548,8 +548,7 @@ static int xsk_get_max_queues(struct xsk_socket *xsk) · 547 unmodified lines
548 return -errno;548 return -errno;
549 549
550 ifr.ifr_data = (void *)&channels;550 ifr.ifr_data = (void *)&channels;
551 memcpy(ifr.ifr_name, ctx->ifname, IFNAMSIZ - 1);551 libbpf_strlcpy(ifr.ifr_name, ctx->ifname, IFNAMSIZ);
552 ifr.ifr_name[IFNAMSIZ - 1] = '\0';
553 err = ioctl(fd, SIOCETHTOOL, &ifr);552 err = ioctl(fd, SIOCETHTOOL, &ifr);
554 if (err && errno != EOPNOTSUPP) {553 if (err && errno != EOPNOTSUPP) {
555 ret = -errno;554 ret = -errno;
@@ -768,8 +767,7 @@ static int xsk_create_xsk_struct(int ifindex, struct xsk_socket *xsk) · 212 unmodified lines
768 }767 }
769 768
770 ctx->ifindex = ifindex;769 ctx->ifindex = ifindex;
771 memcpy(ctx->ifname, ifname, IFNAMSIZ -1);770 libbpf_strlcpy(ctx->ifname, ifname, IFNAMSIZ);
772 ctx->ifname[IFNAMSIZ - 1] = 0;
773 771
774 xsk->ctx = ctx;772 xsk->ctx = ctx;
775 xsk->ctx->has_bpf_link = xsk_probe_bpf_link();773 xsk->ctx->has_bpf_link = xsk_probe_bpf_link();
@@ -951,8 +949,7 @@ static struct xsk_ctx *xsk_create_ctx(struct xsk_socket *xsk, · 175 unmodified lines
951 ctx->refcount = 1;949 ctx->refcount = 1;
952 ctx->umem = umem;950 ctx->umem = umem;
953 ctx->queue_id = queue_id;951 ctx->queue_id = queue_id;
954 memcpy(ctx->ifname, ifname, IFNAMSIZ - 1);952 libbpf_strlcpy(ctx->ifname, ifname, IFNAMSIZ);
955 ctx->ifname[IFNAMSIZ - 1] = '\0';
956 953
957 ctx->fill = fill;954 ctx->fill = fill;
958 ctx->comp = comp;955 ctx->comp = comp;
tools/perf/builtin-trace.c+12−1
@@ -3257,10 +3257,21 @@ static void trace__set_bpf_map_syscalls(struct trace *trace) · 3256 unmodified lines
3257 3257
3258static struct bpf_program *trace__find_bpf_program_by_title(struct trace *trace, const char *name)3258static struct bpf_program *trace__find_bpf_program_by_title(struct trace *trace, const char *name)
3259{3259{
3260 struct bpf_program *pos, *prog = NULL;
3261 const char *sec_name;
3262
3260 if (trace->bpf_obj == NULL)3263 if (trace->bpf_obj == NULL)
3261 return NULL;3264 return NULL;
3262 3265
3263 return bpf_object__find_program_by_title(trace->bpf_obj, name);3266 bpf_object__for_each_program(pos, trace->bpf_obj) {
3267 sec_name = bpf_program__section_name(pos);
3268 if (sec_name && !strcmp(sec_name, name)) {
3269 prog = pos;
3270 break;
3271 }
3272 }
3273
3274 return prog;
3264}3275}
3265 3276
3266static struct bpf_program *trace__find_syscall_bpf_prog(struct trace *trace, struct syscall *sc,3277static struct bpf_program *trace__find_syscall_bpf_prog(struct trace *trace, struct syscall *sc,
tools/scripts/Makefile.include+12−1
@@ -87,7 +87,18 @@ LLVM_STRIP ?= llvm-strip · 86 unmodified lines
87 87
88ifeq ($(CC_NO_CLANG), 1)88ifeq ($(CC_NO_CLANG), 1)
89EXTRA_WARNINGS += -Wstrict-aliasing=389EXTRA_WARNINGS += -Wstrict-aliasing=3
90endif90
91else ifneq ($(CROSS_COMPILE),)
92CLANG_CROSS_FLAGS := --target=$(notdir $(CROSS_COMPILE:%-=%))
93GCC_TOOLCHAIN_DIR := $(dir $(shell which $(CROSS_COMPILE)gcc))
94ifneq ($(GCC_TOOLCHAIN_DIR),)
95CLANG_CROSS_FLAGS += --prefix=$(GCC_TOOLCHAIN_DIR)$(notdir $(CROSS_COMPILE))
96CLANG_CROSS_FLAGS += --sysroot=$(shell $(CROSS_COMPILE)gcc -print-sysroot)
97CLANG_CROSS_FLAGS += --gcc-toolchain=$(realpath $(GCC_TOOLCHAIN_DIR)/..)
98endif # GCC_TOOLCHAIN_DIR
99CFLAGS += $(CLANG_CROSS_FLAGS)
100AFLAGS += $(CLANG_CROSS_FLAGS)
101endif # CROSS_COMPILE
91 102
92# Hack to avoid type-punned warnings on old systems such as RHEL5:103# Hack to avoid type-punned warnings on old systems such as RHEL5:
93# We should be changing CFLAGS and checking gcc version, but this104# We should be changing CFLAGS and checking gcc version, but this
tools/testing/selftests/bpf/Makefile+7−5
@@ -170,7 +170,7 @@ $(OUTPUT)/%:%.c · 169 unmodified lines
170 170
171$(OUTPUT)/urandom_read: urandom_read.c171$(OUTPUT)/urandom_read: urandom_read.c
172 $(call msg,BINARY,,$@)172 $(call msg,BINARY,,$@)
173 $(Q)$(CC) $(LDFLAGS) $< $(LDLIBS) -Wl,--build-id=sha1 -o $@173 $(Q)$(CC) $(CFLAGS) $(LDFLAGS) $< $(LDLIBS) -Wl,--build-id=sha1 -o $@
174 174
175$(OUTPUT)/bpf_testmod.ko: $(VMLINUX_BTF) $(wildcard bpf_testmod/Makefile bpf_testmod/*.[ch])175$(OUTPUT)/bpf_testmod.ko: $(VMLINUX_BTF) $(wildcard bpf_testmod/Makefile bpf_testmod/*.[ch])
176 $(call msg,MOD,,$@)176 $(call msg,MOD,,$@)
@@ -217,7 +217,7 @@ BPFTOOL ?= $(DEFAULT_BPFTOOL) · 40 unmodified lines
217$(DEFAULT_BPFTOOL): $(wildcard $(BPFTOOLDIR)/*.[ch] $(BPFTOOLDIR)/Makefile) \217$(DEFAULT_BPFTOOL): $(wildcard $(BPFTOOLDIR)/*.[ch] $(BPFTOOLDIR)/Makefile) \
218 $(HOST_BPFOBJ) | $(HOST_BUILD_DIR)/bpftool218 $(HOST_BPFOBJ) | $(HOST_BUILD_DIR)/bpftool
219 $(Q)$(MAKE) $(submake_extras) -C $(BPFTOOLDIR) \219 $(Q)$(MAKE) $(submake_extras) -C $(BPFTOOLDIR) \
220 CC=$(HOSTCC) LD=$(HOSTLD) \220 ARCH= CROSS_COMPILE= CC=$(HOSTCC) LD=$(HOSTLD) \
221 EXTRA_CFLAGS='-g -O0' \221 EXTRA_CFLAGS='-g -O0' \
222 OUTPUT=$(HOST_BUILD_DIR)/bpftool/ \222 OUTPUT=$(HOST_BUILD_DIR)/bpftool/ \
223 LIBBPF_OUTPUT=$(HOST_BUILD_DIR)/libbpf/ \223 LIBBPF_OUTPUT=$(HOST_BUILD_DIR)/libbpf/ \
@@ -248,7 +248,7 @@ $(HOST_BPFOBJ): $(wildcard $(BPFDIR)/*.[ch] $(BPFDIR)/Makefile) \ · 24 unmodified lines
248 $(APIDIR)/linux/bpf.h \248 $(APIDIR)/linux/bpf.h \
249 | $(HOST_BUILD_DIR)/libbpf249 | $(HOST_BUILD_DIR)/libbpf
250 $(Q)$(MAKE) $(submake_extras) -C $(BPFDIR) \250 $(Q)$(MAKE) $(submake_extras) -C $(BPFDIR) \
251 EXTRA_CFLAGS='-g -O0' \251 EXTRA_CFLAGS='-g -O0' ARCH= CROSS_COMPILE= \
252 OUTPUT=$(HOST_BUILD_DIR)/libbpf/ CC=$(HOSTCC) LD=$(HOSTLD) \252 OUTPUT=$(HOST_BUILD_DIR)/libbpf/ CC=$(HOSTCC) LD=$(HOSTLD) \
253 DESTDIR=$(HOST_SCRATCH_DIR)/ prefix= all install_headers253 DESTDIR=$(HOST_SCRATCH_DIR)/ prefix= all install_headers
254endif254endif
@@ -537,6 +537,7 @@ $(OUTPUT)/bench_ringbufs.o: $(OUTPUT)/ringbuf_bench.skel.h \ · 282 unmodified lines
537 $(OUTPUT)/perfbuf_bench.skel.h537 $(OUTPUT)/perfbuf_bench.skel.h
538$(OUTPUT)/bench_bloom_filter_map.o: $(OUTPUT)/bloom_filter_bench.skel.h538$(OUTPUT)/bench_bloom_filter_map.o: $(OUTPUT)/bloom_filter_bench.skel.h
539$(OUTPUT)/bench_bpf_loop.o: $(OUTPUT)/bpf_loop_bench.skel.h539$(OUTPUT)/bench_bpf_loop.o: $(OUTPUT)/bpf_loop_bench.skel.h
540$(OUTPUT)/bench_strncmp.o: $(OUTPUT)/strncmp_bench.skel.h
540$(OUTPUT)/bench.o: bench.h testing_helpers.h $(BPFOBJ)541$(OUTPUT)/bench.o: bench.h testing_helpers.h $(BPFOBJ)
541$(OUTPUT)/bench: LDLIBS += -lm542$(OUTPUT)/bench: LDLIBS += -lm
542$(OUTPUT)/bench: $(OUTPUT)/bench.o \543$(OUTPUT)/bench: $(OUTPUT)/bench.o \
@@ -547,9 +548,10 @@ $(OUTPUT)/bench: $(OUTPUT)/bench.o \ · 4 unmodified lines
547 $(OUTPUT)/bench_trigger.o \548 $(OUTPUT)/bench_trigger.o \
548 $(OUTPUT)/bench_ringbufs.o \549 $(OUTPUT)/bench_ringbufs.o \
549 $(OUTPUT)/bench_bloom_filter_map.o \550 $(OUTPUT)/bench_bloom_filter_map.o \
550 $(OUTPUT)/bench_bpf_loop.o551 $(OUTPUT)/bench_bpf_loop.o \
552 $(OUTPUT)/bench_strncmp.o
551 $(call msg,BINARY,,$@)553 $(call msg,BINARY,,$@)
552 $(Q)$(CC) $(LDFLAGS) $(filter %.a %.o,$^) $(LDLIBS) -o $@554 $(Q)$(CC) $(CFLAGS) $(LDFLAGS) $(filter %.a %.o,$^) $(LDLIBS) -o $@
553 555
554EXTRA_CLEAN := $(TEST_CUSTOM_PROGS) $(SCRATCH_DIR) $(HOST_SCRATCH_DIR) \556EXTRA_CLEAN := $(TEST_CUSTOM_PROGS) $(SCRATCH_DIR) $(HOST_SCRATCH_DIR) \
555 prog_tests/tests.h map_tests/tests.h verifier/tests.h \557 prog_tests/tests.h map_tests/tests.h verifier/tests.h \
tools/testing/selftests/bpf/bench.c+7−17
@@ -29,26 +29,10 @@ static int libbpf_print_fn(enum libbpf_print_level level, · 28 unmodified lines
29 return vfprintf(stderr, format, args);29 return vfprintf(stderr, format, args);
30}30}
31 31
32static int bump_memlock_rlimit(void)32void setup_libbpf(void)
33{33{
34 struct rlimit rlim_new = {
35 .rlim_cur = RLIM_INFINITY,
36 .rlim_max = RLIM_INFINITY,
37 };
38
39 return setrlimit(RLIMIT_MEMLOCK, &rlim_new);
40}
41
42void setup_libbpf()
43{
44 int err;
45
46 libbpf_set_strict_mode(LIBBPF_STRICT_ALL);34 libbpf_set_strict_mode(LIBBPF_STRICT_ALL);
47 libbpf_set_print(libbpf_print_fn);35 libbpf_set_print(libbpf_print_fn);
48
49 err = bump_memlock_rlimit();
50 if (err)
51 fprintf(stderr, "failed to increase RLIMIT_MEMLOCK: %d", err);
52}36}
53 37
54void false_hits_report_progress(int iter, struct bench_res *res, long delta_ns)38void false_hits_report_progress(int iter, struct bench_res *res, long delta_ns)
@@ -205,11 +189,13 @@ static const struct argp_option opts[] = { · 150 unmodified lines
205extern struct argp bench_ringbufs_argp;189extern struct argp bench_ringbufs_argp;
206extern struct argp bench_bloom_map_argp;190extern struct argp bench_bloom_map_argp;
207extern struct argp bench_bpf_loop_argp;191extern struct argp bench_bpf_loop_argp;
192extern struct argp bench_strncmp_argp;
208 193
209static const struct argp_child bench_parsers[] = {194static const struct argp_child bench_parsers[] = {
210 { &bench_ringbufs_argp, 0, "Ring buffers benchmark", 0 },195 { &bench_ringbufs_argp, 0, "Ring buffers benchmark", 0 },
211 { &bench_bloom_map_argp, 0, "Bloom filter map benchmark", 0 },196 { &bench_bloom_map_argp, 0, "Bloom filter map benchmark", 0 },
212 { &bench_bpf_loop_argp, 0, "bpf_loop helper benchmark", 0 },197 { &bench_bpf_loop_argp, 0, "bpf_loop helper benchmark", 0 },
198 { &bench_strncmp_argp, 0, "bpf_strncmp helper benchmark", 0 },
213 {},199 {},
214};200};
215 201
@@ -409,6 +395,8 @@ extern const struct bench bench_bloom_false_positive; · 193 unmodified lines
409extern const struct bench bench_hashmap_without_bloom;395extern const struct bench bench_hashmap_without_bloom;
410extern const struct bench bench_hashmap_with_bloom;396extern const struct bench bench_hashmap_with_bloom;
411extern const struct bench bench_bpf_loop;397extern const struct bench bench_bpf_loop;
398extern const struct bench bench_strncmp_no_helper;
399extern const struct bench bench_strncmp_helper;
412 400
413static const struct bench *benchs[] = {401static const struct bench *benchs[] = {
414 &bench_count_global,402 &bench_count_global,
@@ -441,6 +429,8 @@ static const struct bench *benchs[] = { · 26 unmodified lines
441 &bench_hashmap_without_bloom,429 &bench_hashmap_without_bloom,
442 &bench_hashmap_with_bloom,430 &bench_hashmap_with_bloom,
443 &bench_bpf_loop,431 &bench_bpf_loop,
432 &bench_strncmp_no_helper,
433 &bench_strncmp_helper,
444};434};
445 435
446static void setup_benchmark()436static void setup_benchmark()
tools/testing/selftests/bpf/bench.h+5−4
@@ -38,8 +38,8 @@ struct bench_res { · 37 unmodified lines
38 38
39struct bench {39struct bench {
40 const char *name;40 const char *name;
41 void (*validate)();41 void (*validate)(void);
42 void (*setup)();42 void (*setup)(void);
43 void *(*producer_thread)(void *ctx);43 void *(*producer_thread)(void *ctx);
44 void *(*consumer_thread)(void *ctx);44 void *(*consumer_thread)(void *ctx);
45 void (*measure)(struct bench_res* res);45 void (*measure)(struct bench_res* res);
@@ -54,7 +54,7 @@ struct counter { · 8 unmodified lines
54extern struct env env;54extern struct env env;
55extern const struct bench *bench;55extern const struct bench *bench;
56 56
57void setup_libbpf();57void setup_libbpf(void);
58void hits_drops_report_progress(int iter, struct bench_res *res, long delta_ns);58void hits_drops_report_progress(int iter, struct bench_res *res, long delta_ns);
59void hits_drops_report_final(struct bench_res res[], int res_cnt);59void hits_drops_report_final(struct bench_res res[], int res_cnt);
60void false_hits_report_progress(int iter, struct bench_res *res, long delta_ns);60void false_hits_report_progress(int iter, struct bench_res *res, long delta_ns);
@@ -62,7 +62,8 @@ void false_hits_report_final(struct bench_res res[], int res_cnt); · 1 unmodified line
62void ops_report_progress(int iter, struct bench_res *res, long delta_ns);62void ops_report_progress(int iter, struct bench_res *res, long delta_ns);
63void ops_report_final(struct bench_res res[], int res_cnt);63void ops_report_final(struct bench_res res[], int res_cnt);
64 64
65static inline __u64 get_time_ns() {65static inline __u64 get_time_ns(void)
66{
66 struct timespec t;67 struct timespec t;
67 68
68 clock_gettime(CLOCK_MONOTONIC, &t);69 clock_gettime(CLOCK_MONOTONIC, &t);
tools/testing/selftests/bpf/benchs/bench_count.c+1−1
@@ -36,7 +36,7 @@ static struct count_local_ctx { · 35 unmodified lines
36 struct counter *hits;36 struct counter *hits;
37} count_local_ctx;37} count_local_ctx;
38 38
39static void count_local_setup()39static void count_local_setup(void)
40{40{
41 struct count_local_ctx *ctx = &count_local_ctx;41 struct count_local_ctx *ctx = &count_local_ctx;
42 42
tools/testing/selftests/bpf/benchs/bench_rename.c+8−8
@@ -11,7 +11,7 @@ static struct ctx { · 10 unmodified lines
11 int fd;11 int fd;
12} ctx;12} ctx;
13 13
14static void validate()14static void validate(void)
15{15{
16 if (env.producer_cnt != 1) {16 if (env.producer_cnt != 1) {
17 fprintf(stderr, "benchmark doesn't support multi-producer!\n");17 fprintf(stderr, "benchmark doesn't support multi-producer!\n");
@@ -43,7 +43,7 @@ static void measure(struct bench_res *res) · 25 unmodified lines
43 res->hits = atomic_swap(&ctx.hits.value, 0);43 res->hits = atomic_swap(&ctx.hits.value, 0);
44}44}
45 45
46static void setup_ctx()46static void setup_ctx(void)
47{47{
48 setup_libbpf();48 setup_libbpf();
49 49
@@ -71,36 +71,36 @@ static void attach_bpf(struct bpf_program *prog) · 21 unmodified lines
71 }71 }
72}72}
73 73
74static void setup_base()74static void setup_base(void)
75{75{
76 setup_ctx();76 setup_ctx();
77}77}
78 78
79static void setup_kprobe()79static void setup_kprobe(void)
80{80{
81 setup_ctx();81 setup_ctx();
82 attach_bpf(ctx.skel->progs.prog1);82 attach_bpf(ctx.skel->progs.prog1);
83}83}
84 84
85static void setup_kretprobe()85static void setup_kretprobe(void)
86{86{
87 setup_ctx();87 setup_ctx();
88 attach_bpf(ctx.skel->progs.prog2);88 attach_bpf(ctx.skel->progs.prog2);
89}89}
90 90
91static void setup_rawtp()91static void setup_rawtp(void)
92{92{
93 setup_ctx();93 setup_ctx();
94 attach_bpf(ctx.skel->progs.prog3);94 attach_bpf(ctx.skel->progs.prog3);
95}95}
96 96
97static void setup_fentry()97static void setup_fentry(void)
98{98{
99 setup_ctx();99 setup_ctx();
100 attach_bpf(ctx.skel->progs.prog4);100 attach_bpf(ctx.skel->progs.prog4);
101}101}
102 102
103static void setup_fexit()103static void setup_fexit(void)
104{104{
105 setup_ctx();105 setup_ctx();
106 attach_bpf(ctx.skel->progs.prog5);106 attach_bpf(ctx.skel->progs.prog5);
tools/testing/selftests/bpf/benchs/bench_ringbufs.c+7−7
@@ -88,12 +88,12 @@ const struct argp bench_ringbufs_argp = { · 87 unmodified lines
88 88
89static struct counter buf_hits;89static struct counter buf_hits;
90 90
91static inline void bufs_trigger_batch()91static inline void bufs_trigger_batch(void)
92{92{
93 (void)syscall(__NR_getpgid);93 (void)syscall(__NR_getpgid);
94}94}
95 95
96static void bufs_validate()96static void bufs_validate(void)
97{97{
98 if (env.consumer_cnt != 1) {98 if (env.consumer_cnt != 1) {
99 fprintf(stderr, "rb-libbpf benchmark doesn't support multi-consumer!\n");99 fprintf(stderr, "rb-libbpf benchmark doesn't support multi-consumer!\n");
@@ -132,7 +132,7 @@ static void ringbuf_libbpf_measure(struct bench_res *res) · 32 unmodified lines
132 res->drops = atomic_swap(&ctx->skel->bss->dropped, 0);132 res->drops = atomic_swap(&ctx->skel->bss->dropped, 0);
133}133}
134 134
135static struct ringbuf_bench *ringbuf_setup_skeleton()135static struct ringbuf_bench *ringbuf_setup_skeleton(void)
136{136{
137 struct ringbuf_bench *skel;137 struct ringbuf_bench *skel;
138 138
@@ -167,7 +167,7 @@ static int buf_process_sample(void *ctx, void *data, size_t len) · 28 unmodified lines
167 return 0;167 return 0;
168}168}
169 169
170static void ringbuf_libbpf_setup()170static void ringbuf_libbpf_setup(void)
171{171{
172 struct ringbuf_libbpf_ctx *ctx = &ringbuf_libbpf_ctx;172 struct ringbuf_libbpf_ctx *ctx = &ringbuf_libbpf_ctx;
173 struct bpf_link *link;173 struct bpf_link *link;
@@ -223,7 +223,7 @@ static void ringbuf_custom_measure(struct bench_res *res) · 49 unmodified lines
223 res->drops = atomic_swap(&ctx->skel->bss->dropped, 0);223 res->drops = atomic_swap(&ctx->skel->bss->dropped, 0);
224}224}
225 225
226static void ringbuf_custom_setup()226static void ringbuf_custom_setup(void)
227{227{
228 struct ringbuf_custom_ctx *ctx = &ringbuf_custom_ctx;228 struct ringbuf_custom_ctx *ctx = &ringbuf_custom_ctx;
229 const size_t page_size = getpagesize();229 const size_t page_size = getpagesize();
@@ -352,7 +352,7 @@ static void perfbuf_measure(struct bench_res *res) · 122 unmodified lines
352 res->drops = atomic_swap(&ctx->skel->bss->dropped, 0);352 res->drops = atomic_swap(&ctx->skel->bss->dropped, 0);
353}353}
354 354
355static struct perfbuf_bench *perfbuf_setup_skeleton()355static struct perfbuf_bench *perfbuf_setup_skeleton(void)
356{356{
357 struct perfbuf_bench *skel;357 struct perfbuf_bench *skel;
358 358
@@ -390,7 +390,7 @@ perfbuf_process_sample_raw(void *input_ctx, int cpu, · 31 unmodified lines
390 return LIBBPF_PERF_EVENT_CONT;390 return LIBBPF_PERF_EVENT_CONT;
391}391}
392 392
393static void perfbuf_libbpf_setup()393static void perfbuf_libbpf_setup(void)
394{394{
395 struct perfbuf_libbpf_ctx *ctx = &perfbuf_libbpf_ctx;395 struct perfbuf_libbpf_ctx *ctx = &perfbuf_libbpf_ctx;
396 struct perf_event_attr attr;396 struct perf_event_attr attr;
tools/testing/selftests/bpf/benchs/bench_strncmp.c+161−0
@@ -0,0 +1,161 @@
1// SPDX-License-Identifier: GPL-2.0
2/* Copyright (C) 2021. Huawei Technologies Co., Ltd */
3#include <argp.h>
4#include "bench.h"
5#include "strncmp_bench.skel.h"
6
7static struct strncmp_ctx {
8 struct strncmp_bench *skel;
9} ctx;
10
11static struct strncmp_args {
12 u32 cmp_str_len;
13} args = {
14 .cmp_str_len = 32,
15};
16
17enum {
18 ARG_CMP_STR_LEN = 5000,
19};
20
21static const struct argp_option opts[] = {
22 { "cmp-str-len", ARG_CMP_STR_LEN, "CMP_STR_LEN", 0,
23 "Set the length of compared string" },
24 {},
25};
26
27static error_t strncmp_parse_arg(int key, char *arg, struct argp_state *state)
28{
29 switch (key) {
30 case ARG_CMP_STR_LEN:
31 args.cmp_str_len = strtoul(arg, NULL, 10);
32 if (!args.cmp_str_len ||
33 args.cmp_str_len >= sizeof(ctx.skel->bss->str)) {
34 fprintf(stderr, "Invalid cmp str len (limit %zu)\n",
35 sizeof(ctx.skel->bss->str));
36 argp_usage(state);
37 }
38 break;
39 default:
40 return ARGP_ERR_UNKNOWN;
41 }
42
43 return 0;
44}
45
46const struct argp bench_strncmp_argp = {
47 .options = opts,
48 .parser = strncmp_parse_arg,
49};
50
51static void strncmp_validate(void)
52{
53 if (env.consumer_cnt != 1) {
54 fprintf(stderr, "strncmp benchmark doesn't support multi-consumer!\n");
55 exit(1);
56 }
57}
58
59static void strncmp_setup(void)
60{
61 int err;
62 char *target;
63 size_t i, sz;
64
65 sz = sizeof(ctx.skel->rodata->target);
66 if (!sz || sz < sizeof(ctx.skel->bss->str)) {
67 fprintf(stderr, "invalid string size (target %zu, src %zu)\n",
68 sz, sizeof(ctx.skel->bss->str));
69 exit(1);
70 }
71
72 setup_libbpf();
73
74 ctx.skel = strncmp_bench__open();
75 if (!ctx.skel) {
76 fprintf(stderr, "failed to open skeleton\n");
77 exit(1);
78 }
79
80 srandom(time(NULL));
81 target = ctx.skel->rodata->target;
82 for (i = 0; i < sz - 1; i++)
83 target[i] = '1' + random() % 9;
84 target[sz - 1] = '\0';
85
86 ctx.skel->rodata->cmp_str_len = args.cmp_str_len;
87
88 memcpy(ctx.skel->bss->str, target, args.cmp_str_len);
89 ctx.skel->bss->str[args.cmp_str_len] = '\0';
90 /* Make bss->str < rodata->target */
91 ctx.skel->bss->str[args.cmp_str_len - 1] -= 1;
92
93 err = strncmp_bench__load(ctx.skel);
94 if (err) {
95 fprintf(stderr, "failed to load skeleton\n");
96 strncmp_bench__destroy(ctx.skel);
97 exit(1);
98 }
99}
100
101static void strncmp_attach_prog(struct bpf_program *prog)
102{
103 struct bpf_link *link;
104
105 link = bpf_program__attach(prog);
106 if (!link) {
107 fprintf(stderr, "failed to attach program!\n");
108 exit(1);
109 }
110}
111
112static void strncmp_no_helper_setup(void)
113{
114 strncmp_setup();
115 strncmp_attach_prog(ctx.skel->progs.strncmp_no_helper);
116}
117
118static void strncmp_helper_setup(void)
119{
120 strncmp_setup();
121 strncmp_attach_prog(ctx.skel->progs.strncmp_helper);
122}
123
124static void *strncmp_producer(void *ctx)
125{
126 while (true)
127 (void)syscall(__NR_getpgid);
128 return NULL;
129}
130
131static void *strncmp_consumer(void *ctx)
132{
133 return NULL;
134}
135
136static void strncmp_measure(struct bench_res *res)
137{
138 res->hits = atomic_swap(&ctx.skel->bss->hits, 0);
139}
140
141const struct bench bench_strncmp_no_helper = {
142 .name = "strncmp-no-helper",
143 .validate = strncmp_validate,
144 .setup = strncmp_no_helper_setup,
145 .producer_thread = strncmp_producer,
146 .consumer_thread = strncmp_consumer,
147 .measure = strncmp_measure,
148 .report_progress = hits_drops_report_progress,
149 .report_final = hits_drops_report_final,
150};
151
152const struct bench bench_strncmp_helper = {
153 .name = "strncmp-helper",
154 .validate = strncmp_validate,
155 .setup = strncmp_helper_setup,
156 .producer_thread = strncmp_producer,
157 .consumer_thread = strncmp_consumer,
158 .measure = strncmp_measure,
159 .report_progress = hits_drops_report_progress,
160 .report_final = hits_drops_report_final,
161};
tools/testing/selftests/bpf/benchs/bench_trigger.c+12−12
@@ -11,7 +11,7 @@ static struct trigger_ctx { · 10 unmodified lines
11 11
12static struct counter base_hits;12static struct counter base_hits;
13 13
14static void trigger_validate()14static void trigger_validate(void)
15{15{
16 if (env.consumer_cnt != 1) {16 if (env.consumer_cnt != 1) {
17 fprintf(stderr, "benchmark doesn't support multi-consumer!\n");17 fprintf(stderr, "benchmark doesn't support multi-consumer!\n");
@@ -45,7 +45,7 @@ static void trigger_measure(struct bench_res *res) · 27 unmodified lines
45 res->hits = atomic_swap(&ctx.skel->bss->hits, 0);45 res->hits = atomic_swap(&ctx.skel->bss->hits, 0);
46}46}
47 47
48static void setup_ctx()48static void setup_ctx(void)
49{49{
50 setup_libbpf();50 setup_libbpf();
51 51
@@ -67,37 +67,37 @@ static void attach_bpf(struct bpf_program *prog) · 15 unmodified lines
67 }67 }
68}68}
69 69
70static void trigger_tp_setup()70static void trigger_tp_setup(void)
71{71{
72 setup_ctx();72 setup_ctx();
73 attach_bpf(ctx.skel->progs.bench_trigger_tp);73 attach_bpf(ctx.skel->progs.bench_trigger_tp);
74}74}
75 75
76static void trigger_rawtp_setup()76static void trigger_rawtp_setup(void)
77{77{
78 setup_ctx();78 setup_ctx();
79 attach_bpf(ctx.skel->progs.bench_trigger_raw_tp);79 attach_bpf(ctx.skel->progs.bench_trigger_raw_tp);
80}80}
81 81
82static void trigger_kprobe_setup()82static void trigger_kprobe_setup(void)
83{83{
84 setup_ctx();84 setup_ctx();
85 attach_bpf(ctx.skel->progs.bench_trigger_kprobe);85 attach_bpf(ctx.skel->progs.bench_trigger_kprobe);
86}86}
87 87
88static void trigger_fentry_setup()88static void trigger_fentry_setup(void)
89{89{
90 setup_ctx();90 setup_ctx();
91 attach_bpf(ctx.skel->progs.bench_trigger_fentry);91 attach_bpf(ctx.skel->progs.bench_trigger_fentry);
92}92}
93 93
94static void trigger_fentry_sleep_setup()94static void trigger_fentry_sleep_setup(void)
95{95{
96 setup_ctx();96 setup_ctx();
97 attach_bpf(ctx.skel->progs.bench_trigger_fentry_sleep);97 attach_bpf(ctx.skel->progs.bench_trigger_fentry_sleep);
98}98}
99 99
100static void trigger_fmodret_setup()100static void trigger_fmodret_setup(void)
101{101{
102 setup_ctx();102 setup_ctx();
103 attach_bpf(ctx.skel->progs.bench_trigger_fmodret);103 attach_bpf(ctx.skel->progs.bench_trigger_fmodret);
@@ -183,22 +183,22 @@ static void usetup(bool use_retprobe, bool use_nop) · 79 unmodified lines
183 ctx.skel->links.bench_trigger_uprobe = link;183 ctx.skel->links.bench_trigger_uprobe = link;
184}184}
185 185
186static void uprobe_setup_with_nop()186static void uprobe_setup_with_nop(void)
187{187{
188 usetup(false, true);188 usetup(false, true);
189}189}
190 190
191static void uretprobe_setup_with_nop()191static void uretprobe_setup_with_nop(void)
192{192{
193 usetup(true, true);193 usetup(true, true);
194}194}
195 195
196static void uprobe_setup_without_nop()196static void uprobe_setup_without_nop(void)
197{197{
198 usetup(false, false);198 usetup(false, false);
199}199}
200 200
201static void uretprobe_setup_without_nop()201static void uretprobe_setup_without_nop(void)
202{202{
203 usetup(true, false);203 usetup(true, false);
204}204}
tools/testing/selftests/bpf/benchs/run_bench_strncmp.sh+12−0
@@ -0,0 +1,12 @@
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4source ./benchs/run_common.sh
5
6set -eufo pipefail
7
8for s in 1 8 64 512 2048 4095; do
9 for b in no-helper helper; do
10 summarize ${b}-${s} "$($RUN_BENCH --cmp-str-len=$s strncmp-${b})"
11 done
12done
tools/testing/selftests/bpf/config+2−0
@@ -38,7 +38,9 @@ CONFIG_IPV6_SIT=m · 37 unmodified lines
38CONFIG_BPF_JIT=y38CONFIG_BPF_JIT=y
39CONFIG_BPF_LSM=y39CONFIG_BPF_LSM=y
40CONFIG_SECURITY=y40CONFIG_SECURITY=y
41CONFIG_RC_CORE=y
41CONFIG_LIRC=y42CONFIG_LIRC=y
43CONFIG_BPF_LIRC_MODE2=y
42CONFIG_IMA=y44CONFIG_IMA=y
43CONFIG_SECURITYFS=y45CONFIG_SECURITYFS=y
44CONFIG_IMA_WRITE_POLICY=y46CONFIG_IMA_WRITE_POLICY=y
tools/testing/selftests/bpf/prog_tests/align.c+103−88
@@ -39,13 +39,13 @@ static struct bpf_align_test tests[] = { · 38 unmodified lines
39 },39 },
40 .prog_type = BPF_PROG_TYPE_SCHED_CLS,40 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
41 .matches = {41 .matches = {
42 {1, "R1=ctx(id=0,off=0,imm=0)"},42 {0, "R1=ctx(id=0,off=0,imm=0)"},
43 {1, "R10=fp0"},43 {0, "R10=fp0"},
44 {1, "R3_w=inv2"},44 {0, "R3_w=inv2"},
45 {2, "R3_w=inv4"},45 {1, "R3_w=inv4"},
46 {3, "R3_w=inv8"},46 {2, "R3_w=inv8"},
47 {4, "R3_w=inv16"},47 {3, "R3_w=inv16"},
48 {5, "R3_w=inv32"},48 {4, "R3_w=inv32"},
49 },49 },
50 },50 },
51 {51 {
@@ -67,19 +67,19 @@ static struct bpf_align_test tests[] = { · 15 unmodified lines
67 },67 },
68 .prog_type = BPF_PROG_TYPE_SCHED_CLS,68 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
69 .matches = {69 .matches = {
70 {1, "R1=ctx(id=0,off=0,imm=0)"},70 {0, "R1=ctx(id=0,off=0,imm=0)"},
71 {1, "R10=fp0"},71 {0, "R10=fp0"},
72 {1, "R3_w=inv1"},72 {0, "R3_w=inv1"},
73 {2, "R3_w=inv2"},73 {1, "R3_w=inv2"},
74 {3, "R3_w=inv4"},74 {2, "R3_w=inv4"},
75 {4, "R3_w=inv8"},75 {3, "R3_w=inv8"},
76 {5, "R3_w=inv16"},76 {4, "R3_w=inv16"},
77 {6, "R3_w=inv1"},77 {5, "R3_w=inv1"},
78 {7, "R4_w=inv32"},78 {6, "R4_w=inv32"},
79 {8, "R4_w=inv16"},79 {7, "R4_w=inv16"},
80 {9, "R4_w=inv8"},80 {8, "R4_w=inv8"},
81 {10, "R4_w=inv4"},81 {9, "R4_w=inv4"},
82 {11, "R4_w=inv2"},82 {10, "R4_w=inv2"},
83 },83 },
84 },84 },
85 {85 {
@@ -96,14 +96,14 @@ static struct bpf_align_test tests[] = { · 10 unmodified lines
96 },96 },
97 .prog_type = BPF_PROG_TYPE_SCHED_CLS,97 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
98 .matches = {98 .matches = {
99 {1, "R1=ctx(id=0,off=0,imm=0)"},99 {0, "R1=ctx(id=0,off=0,imm=0)"},
100 {1, "R10=fp0"},100 {0, "R10=fp0"},
101 {1, "R3_w=inv4"},101 {0, "R3_w=inv4"},
102 {2, "R3_w=inv8"},102 {1, "R3_w=inv8"},
103 {3, "R3_w=inv10"},103 {2, "R3_w=inv10"},
104 {4, "R4_w=inv8"},104 {3, "R4_w=inv8"},
105 {5, "R4_w=inv12"},105 {4, "R4_w=inv12"},
106 {6, "R4_w=inv14"},106 {5, "R4_w=inv14"},
107 },107 },
108 },108 },
109 {109 {
@@ -118,12 +118,12 @@ static struct bpf_align_test tests[] = { · 8 unmodified lines
118 },118 },
119 .prog_type = BPF_PROG_TYPE_SCHED_CLS,119 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
120 .matches = {120 .matches = {
121 {1, "R1=ctx(id=0,off=0,imm=0)"},121 {0, "R1=ctx(id=0,off=0,imm=0)"},
122 {1, "R10=fp0"},122 {0, "R10=fp0"},
123 {0, "R3_w=inv7"},
123 {1, "R3_w=inv7"},124 {1, "R3_w=inv7"},
124 {2, "R3_w=inv7"},125 {2, "R3_w=inv14"},
125 {3, "R3_w=inv14"},126 {3, "R3_w=inv56"},
126 {4, "R3_w=inv56"},
127 },127 },
128 },128 },
129 129
@@ -161,19 +161,19 @@ static struct bpf_align_test tests[] = { · 31 unmodified lines
161 },161 },
162 .prog_type = BPF_PROG_TYPE_SCHED_CLS,162 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
163 .matches = {163 .matches = {
164 {7, "R0_w=pkt(id=0,off=8,r=8,imm=0)"},164 {6, "R0_w=pkt(id=0,off=8,r=8,imm=0)"},
165 {7, "R3_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},165 {6, "R3_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},
166 {8, "R3_w=inv(id=0,umax_value=510,var_off=(0x0; 0x1fe))"},166 {7, "R3_w=inv(id=0,umax_value=510,var_off=(0x0; 0x1fe))"},
167 {9, "R3_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},167 {8, "R3_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
168 {10, "R3_w=inv(id=0,umax_value=2040,var_off=(0x0; 0x7f8))"},168 {9, "R3_w=inv(id=0,umax_value=2040,var_off=(0x0; 0x7f8))"},
169 {11, "R3_w=inv(id=0,umax_value=4080,var_off=(0x0; 0xff0))"},169 {10, "R3_w=inv(id=0,umax_value=4080,var_off=(0x0; 0xff0))"},
170 {18, "R3=pkt_end(id=0,off=0,imm=0)"},170 {12, "R3_w=pkt_end(id=0,off=0,imm=0)"},
171 {18, "R4_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},171 {17, "R4_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},
172 {19, "R4_w=inv(id=0,umax_value=8160,var_off=(0x0; 0x1fe0))"},172 {18, "R4_w=inv(id=0,umax_value=8160,var_off=(0x0; 0x1fe0))"},
173 {20, "R4_w=inv(id=0,umax_value=4080,var_off=(0x0; 0xff0))"},173 {19, "R4_w=inv(id=0,umax_value=4080,var_off=(0x0; 0xff0))"},
174 {21, "R4_w=inv(id=0,umax_value=2040,var_off=(0x0; 0x7f8))"},174 {20, "R4_w=inv(id=0,umax_value=2040,var_off=(0x0; 0x7f8))"},
175 {22, "R4_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},175 {21, "R4_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
176 {23, "R4_w=inv(id=0,umax_value=510,var_off=(0x0; 0x1fe))"},176 {22, "R4_w=inv(id=0,umax_value=510,var_off=(0x0; 0x1fe))"},
177 },177 },
178 },178 },
179 {179 {
@@ -194,16 +194,16 @@ static struct bpf_align_test tests[] = { · 14 unmodified lines
194 },194 },
195 .prog_type = BPF_PROG_TYPE_SCHED_CLS,195 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
196 .matches = {196 .matches = {
197 {7, "R3_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},197 {6, "R3_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},
198 {8, "R4_w=inv(id=1,umax_value=255,var_off=(0x0; 0xff))"},198 {7, "R4_w=inv(id=1,umax_value=255,var_off=(0x0; 0xff))"},
199 {9, "R4_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},199 {8, "R4_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},
200 {10, "R4_w=inv(id=1,umax_value=255,var_off=(0x0; 0xff))"},200 {9, "R4_w=inv(id=1,umax_value=255,var_off=(0x0; 0xff))"},
201 {11, "R4_w=inv(id=0,umax_value=510,var_off=(0x0; 0x1fe))"},201 {10, "R4_w=inv(id=0,umax_value=510,var_off=(0x0; 0x1fe))"},
202 {12, "R4_w=inv(id=1,umax_value=255,var_off=(0x0; 0xff))"},202 {11, "R4_w=inv(id=1,umax_value=255,var_off=(0x0; 0xff))"},
203 {13, "R4_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},203 {12, "R4_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
204 {14, "R4_w=inv(id=1,umax_value=255,var_off=(0x0; 0xff))"},204 {13, "R4_w=inv(id=1,umax_value=255,var_off=(0x0; 0xff))"},
205 {15, "R4_w=inv(id=0,umax_value=2040,var_off=(0x0; 0x7f8))"},205 {14, "R4_w=inv(id=0,umax_value=2040,var_off=(0x0; 0x7f8))"},
206 {16, "R4_w=inv(id=0,umax_value=4080,var_off=(0x0; 0xff0))"},206 {15, "R4_w=inv(id=0,umax_value=4080,var_off=(0x0; 0xff0))"},
207 },207 },
208 },208 },
209 {209 {
@@ -234,14 +234,14 @@ static struct bpf_align_test tests[] = { · 24 unmodified lines
234 },234 },
235 .prog_type = BPF_PROG_TYPE_SCHED_CLS,235 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
236 .matches = {236 .matches = {
237 {4, "R5_w=pkt(id=0,off=0,r=0,imm=0)"},237 {2, "R5_w=pkt(id=0,off=0,r=0,imm=0)"},
238 {5, "R5_w=pkt(id=0,off=14,r=0,imm=0)"},238 {4, "R5_w=pkt(id=0,off=14,r=0,imm=0)"},
239 {6, "R4_w=pkt(id=0,off=14,r=0,imm=0)"},239 {5, "R4_w=pkt(id=0,off=14,r=0,imm=0)"},
240 {10, "R2=pkt(id=0,off=0,r=18,imm=0)"},240 {9, "R2=pkt(id=0,off=0,r=18,imm=0)"},
241 {10, "R5=pkt(id=0,off=14,r=18,imm=0)"},241 {10, "R5=pkt(id=0,off=14,r=18,imm=0)"},
242 {10, "R4_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},242 {10, "R4_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},
243 {13, "R4_w=inv(id=0,umax_value=65535,var_off=(0x0; 0xffff))"},
243 {14, "R4_w=inv(id=0,umax_value=65535,var_off=(0x0; 0xffff))"},244 {14, "R4_w=inv(id=0,umax_value=65535,var_off=(0x0; 0xffff))"},
244 {15, "R4_w=inv(id=0,umax_value=65535,var_off=(0x0; 0xffff))"},
245 },245 },
246 },246 },
247 {247 {
@@ -296,8 +296,8 @@ static struct bpf_align_test tests[] = { · 48 unmodified lines
296 /* Calculated offset in R6 has unknown value, but known296 /* Calculated offset in R6 has unknown value, but known
297 * alignment of 4.297 * alignment of 4.
298 */298 */
299 {8, "R2_w=pkt(id=0,off=0,r=8,imm=0)"},299 {6, "R2_w=pkt(id=0,off=0,r=8,imm=0)"},
300 {8, "R6_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},300 {7, "R6_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
301 /* Offset is added to packet pointer R5, resulting in301 /* Offset is added to packet pointer R5, resulting in
302 * known fixed offset, and variable offset from R6.302 * known fixed offset, and variable offset from R6.
303 */303 */
@@ -313,11 +313,11 @@ static struct bpf_align_test tests[] = { · 9 unmodified lines
313 /* Variable offset is added to R5 packet pointer,313 /* Variable offset is added to R5 packet pointer,
314 * resulting in auxiliary alignment of 4.314 * resulting in auxiliary alignment of 4.
315 */315 */
316 {18, "R5_w=pkt(id=2,off=0,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"},316 {17, "R5_w=pkt(id=2,off=0,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
317 /* Constant offset is added to R5, resulting in317 /* Constant offset is added to R5, resulting in
318 * reg->off of 14.318 * reg->off of 14.
319 */319 */
320 {19, "R5_w=pkt(id=2,off=14,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"},320 {18, "R5_w=pkt(id=2,off=14,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
321 /* At the time the word size load is performed from R5,321 /* At the time the word size load is performed from R5,
322 * its total fixed offset is NET_IP_ALIGN + reg->off322 * its total fixed offset is NET_IP_ALIGN + reg->off
323 * (14) which is 16. Then the variable offset is 4-byte323 * (14) which is 16. Then the variable offset is 4-byte
@@ -329,18 +329,18 @@ static struct bpf_align_test tests[] = { · 5 unmodified lines
329 /* Constant offset is added to R5 packet pointer,329 /* Constant offset is added to R5 packet pointer,
330 * resulting in reg->off value of 14.330 * resulting in reg->off value of 14.
331 */331 */
332 {26, "R5_w=pkt(id=0,off=14,r=8"},332 {25, "R5_w=pkt(id=0,off=14,r=8"},
333 /* Variable offset is added to R5, resulting in a333 /* Variable offset is added to R5, resulting in a
334 * variable offset of (4n).334 * variable offset of (4n).
335 */335 */
336 {27, "R5_w=pkt(id=3,off=14,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"},336 {26, "R5_w=pkt(id=3,off=14,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
337 /* Constant is added to R5 again, setting reg->off to 18. */337 /* Constant is added to R5 again, setting reg->off to 18. */
338 {28, "R5_w=pkt(id=3,off=18,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"},338 {27, "R5_w=pkt(id=3,off=18,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
339 /* And once more we add a variable; resulting var_off339 /* And once more we add a variable; resulting var_off
340 * is still (4n), fixed offset is not changed.340 * is still (4n), fixed offset is not changed.
341 * Also, we create a new reg->id.341 * Also, we create a new reg->id.
342 */342 */
343 {29, "R5_w=pkt(id=4,off=18,r=0,umax_value=2040,var_off=(0x0; 0x7fc)"},343 {28, "R5_w=pkt(id=4,off=18,r=0,umax_value=2040,var_off=(0x0; 0x7fc)"},
344 /* At the time the word size load is performed from R5,344 /* At the time the word size load is performed from R5,
345 * its total fixed offset is NET_IP_ALIGN + reg->off (18)345 * its total fixed offset is NET_IP_ALIGN + reg->off (18)
346 * which is 20. Then the variable offset is (4n), so346 * which is 20. Then the variable offset is (4n), so
@@ -386,13 +386,13 @@ static struct bpf_align_test tests[] = { · 39 unmodified lines
386 /* Calculated offset in R6 has unknown value, but known386 /* Calculated offset in R6 has unknown value, but known
387 * alignment of 4.387 * alignment of 4.
388 */388 */
389 {8, "R2_w=pkt(id=0,off=0,r=8,imm=0)"},389 {6, "R2_w=pkt(id=0,off=0,r=8,imm=0)"},
390 {8, "R6_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},390 {7, "R6_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
391 /* Adding 14 makes R6 be (4n+2) */391 /* Adding 14 makes R6 be (4n+2) */
392 {9, "R6_w=inv(id=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc))"},392 {8, "R6_w=inv(id=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc))"},
393 /* Packet pointer has (4n+2) offset */393 /* Packet pointer has (4n+2) offset */
394 {11, "R5_w=pkt(id=1,off=0,r=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc)"},394 {11, "R5_w=pkt(id=1,off=0,r=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc)"},
395 {13, "R4=pkt(id=1,off=4,r=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc)"},395 {12, "R4=pkt(id=1,off=4,r=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc)"},
396 /* At the time the word size load is performed from R5,396 /* At the time the word size load is performed from R5,
397 * its total fixed offset is NET_IP_ALIGN + reg->off (0)397 * its total fixed offset is NET_IP_ALIGN + reg->off (0)
398 * which is 2. Then the variable offset is (4n+2), so398 * which is 2. Then the variable offset is (4n+2), so
@@ -403,12 +403,12 @@ static struct bpf_align_test tests[] = { · 4 unmodified lines
403 /* Newly read value in R6 was shifted left by 2, so has403 /* Newly read value in R6 was shifted left by 2, so has
404 * known alignment of 4.404 * known alignment of 4.
405 */405 */
406 {18, "R6_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},406 {17, "R6_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
407 /* Added (4n) to packet pointer's (4n+2) var_off, giving407 /* Added (4n) to packet pointer's (4n+2) var_off, giving
408 * another (4n+2).408 * another (4n+2).
409 */409 */
410 {19, "R5_w=pkt(id=2,off=0,r=0,umin_value=14,umax_value=2054,var_off=(0x2; 0xffc)"},410 {19, "R5_w=pkt(id=2,off=0,r=0,umin_value=14,umax_value=2054,var_off=(0x2; 0xffc)"},
411 {21, "R4=pkt(id=2,off=4,r=0,umin_value=14,umax_value=2054,var_off=(0x2; 0xffc)"},411 {20, "R4=pkt(id=2,off=4,r=0,umin_value=14,umax_value=2054,var_off=(0x2; 0xffc)"},
412 /* At the time the word size load is performed from R5,412 /* At the time the word size load is performed from R5,
413 * its total fixed offset is NET_IP_ALIGN + reg->off (0)413 * its total fixed offset is NET_IP_ALIGN + reg->off (0)
414 * which is 2. Then the variable offset is (4n+2), so414 * which is 2. Then the variable offset is (4n+2), so
@@ -448,18 +448,18 @@ static struct bpf_align_test tests[] = { · 33 unmodified lines
448 .prog_type = BPF_PROG_TYPE_SCHED_CLS,448 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
449 .result = REJECT,449 .result = REJECT,
450 .matches = {450 .matches = {
451 {4, "R5_w=pkt_end(id=0,off=0,imm=0)"},451 {3, "R5_w=pkt_end(id=0,off=0,imm=0)"},
452 /* (ptr - ptr) << 2 == unknown, (4n) */452 /* (ptr - ptr) << 2 == unknown, (4n) */
453 {6, "R5_w=inv(id=0,smax_value=9223372036854775804,umax_value=18446744073709551612,var_off=(0x0; 0xfffffffffffffffc)"},453 {5, "R5_w=inv(id=0,smax_value=9223372036854775804,umax_value=18446744073709551612,var_off=(0x0; 0xfffffffffffffffc)"},
454 /* (4n) + 14 == (4n+2). We blow our bounds, because454 /* (4n) + 14 == (4n+2). We blow our bounds, because
455 * the add could overflow.455 * the add could overflow.
456 */456 */
457 {7, "R5_w=inv(id=0,smin_value=-9223372036854775806,smax_value=9223372036854775806,umin_value=2,umax_value=18446744073709551614,var_off=(0x2; 0xfffffffffffffffc)"},457 {6, "R5_w=inv(id=0,smin_value=-9223372036854775806,smax_value=9223372036854775806,umin_value=2,umax_value=18446744073709551614,var_off=(0x2; 0xfffffffffffffffc)"},
458 /* Checked s>=0 */458 /* Checked s>=0 */
459 {9, "R5=inv(id=0,umin_value=2,umax_value=9223372036854775806,var_off=(0x2; 0x7ffffffffffffffc)"},459 {9, "R5=inv(id=0,umin_value=2,umax_value=9223372036854775806,var_off=(0x2; 0x7ffffffffffffffc)"},
460 /* packet pointer + nonnegative (4n+2) */460 /* packet pointer + nonnegative (4n+2) */
461 {11, "R6_w=pkt(id=1,off=0,r=0,umin_value=2,umax_value=9223372036854775806,var_off=(0x2; 0x7ffffffffffffffc)"},461 {11, "R6_w=pkt(id=1,off=0,r=0,umin_value=2,umax_value=9223372036854775806,var_off=(0x2; 0x7ffffffffffffffc)"},
462 {13, "R4_w=pkt(id=1,off=4,r=0,umin_value=2,umax_value=9223372036854775806,var_off=(0x2; 0x7ffffffffffffffc)"},462 {12, "R4_w=pkt(id=1,off=4,r=0,umin_value=2,umax_value=9223372036854775806,var_off=(0x2; 0x7ffffffffffffffc)"},
463 /* NET_IP_ALIGN + (4n+2) == (4n), alignment is fine.463 /* NET_IP_ALIGN + (4n+2) == (4n), alignment is fine.
464 * We checked the bounds, but it might have been able464 * We checked the bounds, but it might have been able
465 * to overflow if the packet pointer started in the465 * to overflow if the packet pointer started in the
@@ -502,14 +502,14 @@ static struct bpf_align_test tests[] = { · 36 unmodified lines
502 /* Calculated offset in R6 has unknown value, but known502 /* Calculated offset in R6 has unknown value, but known
503 * alignment of 4.503 * alignment of 4.
504 */504 */
505 {7, "R2_w=pkt(id=0,off=0,r=8,imm=0)"},505 {6, "R2_w=pkt(id=0,off=0,r=8,imm=0)"},
506 {9, "R6_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},506 {8, "R6_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
507 /* Adding 14 makes R6 be (4n+2) */507 /* Adding 14 makes R6 be (4n+2) */
508 {10, "R6_w=inv(id=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc))"},508 {9, "R6_w=inv(id=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc))"},
509 /* New unknown value in R7 is (4n) */509 /* New unknown value in R7 is (4n) */
510 {11, "R7_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},510 {10, "R7_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
511 /* Subtracting it from R6 blows our unsigned bounds */511 /* Subtracting it from R6 blows our unsigned bounds */
512 {12, "R6=inv(id=0,smin_value=-1006,smax_value=1034,umin_value=2,umax_value=18446744073709551614,var_off=(0x2; 0xfffffffffffffffc)"},512 {11, "R6=inv(id=0,smin_value=-1006,smax_value=1034,umin_value=2,umax_value=18446744073709551614,var_off=(0x2; 0xfffffffffffffffc)"},
513 /* Checked s>= 0 */513 /* Checked s>= 0 */
514 {14, "R6=inv(id=0,umin_value=2,umax_value=1034,var_off=(0x2; 0x7fc))"},514 {14, "R6=inv(id=0,umin_value=2,umax_value=1034,var_off=(0x2; 0x7fc))"},
515 /* At the time the word size load is performed from R5,515 /* At the time the word size load is performed from R5,
@@ -556,14 +556,14 @@ static struct bpf_align_test tests[] = { · 40 unmodified lines
556 /* Calculated offset in R6 has unknown value, but known556 /* Calculated offset in R6 has unknown value, but known
557 * alignment of 4.557 * alignment of 4.
558 */558 */
559 {7, "R2_w=pkt(id=0,off=0,r=8,imm=0)"},559 {6, "R2_w=pkt(id=0,off=0,r=8,imm=0)"},
560 {10, "R6_w=inv(id=0,umax_value=60,var_off=(0x0; 0x3c))"},560 {9, "R6_w=inv(id=0,umax_value=60,var_off=(0x0; 0x3c))"},
561 /* Adding 14 makes R6 be (4n+2) */561 /* Adding 14 makes R6 be (4n+2) */
562 {11, "R6_w=inv(id=0,umin_value=14,umax_value=74,var_off=(0x2; 0x7c))"},562 {10, "R6_w=inv(id=0,umin_value=14,umax_value=74,var_off=(0x2; 0x7c))"},
563 /* Subtracting from packet pointer overflows ubounds */563 /* Subtracting from packet pointer overflows ubounds */
564 {13, "R5_w=pkt(id=2,off=0,r=8,umin_value=18446744073709551542,umax_value=18446744073709551602,var_off=(0xffffffffffffff82; 0x7c)"},564 {13, "R5_w=pkt(id=2,off=0,r=8,umin_value=18446744073709551542,umax_value=18446744073709551602,var_off=(0xffffffffffffff82; 0x7c)"},
565 /* New unknown value in R7 is (4n), >= 76 */565 /* New unknown value in R7 is (4n), >= 76 */
566 {15, "R7_w=inv(id=0,umin_value=76,umax_value=1096,var_off=(0x0; 0x7fc))"},566 {14, "R7_w=inv(id=0,umin_value=76,umax_value=1096,var_off=(0x0; 0x7fc))"},
567 /* Adding it to packet pointer gives nice bounds again */567 /* Adding it to packet pointer gives nice bounds again */
568 {16, "R5_w=pkt(id=3,off=0,r=0,umin_value=2,umax_value=1082,var_off=(0x2; 0xfffffffc)"},568 {16, "R5_w=pkt(id=3,off=0,r=0,umin_value=2,umax_value=1082,var_off=(0x2; 0xfffffffc)"},
569 /* At the time the word size load is performed from R5,569 /* At the time the word size load is performed from R5,
@@ -625,12 +625,15 @@ static int do_test_single(struct bpf_align_test *test) · 55 unmodified lines
625 line_ptr = strtok(bpf_vlog_copy, "\n");625 line_ptr = strtok(bpf_vlog_copy, "\n");
626 for (i = 0; i < MAX_MATCHES; i++) {626 for (i = 0; i < MAX_MATCHES; i++) {
627 struct bpf_reg_match m = test->matches[i];627 struct bpf_reg_match m = test->matches[i];
628 int tmp;
628 629
629 if (!m.match)630 if (!m.match)
630 break;631 break;
631 while (line_ptr) {632 while (line_ptr) {
632 cur_line = -1;633 cur_line = -1;
633 sscanf(line_ptr, "%u: ", &cur_line);634 sscanf(line_ptr, "%u: ", &cur_line);
635 if (cur_line == -1)
636 sscanf(line_ptr, "from %u to %u: ", &tmp, &cur_line);
634 if (cur_line == m.line)637 if (cur_line == m.line)
635 break;638 break;
636 line_ptr = strtok(NULL, "\n");639 line_ptr = strtok(NULL, "\n");
@@ -642,7 +645,19 @@ static int do_test_single(struct bpf_align_test *test) · 5 unmodified lines
642 printf("%s", bpf_vlog);645 printf("%s", bpf_vlog);
643 break;646 break;
644 }647 }
648 /* Check the next line as well in case the previous line
649 * did not have a corresponding bpf insn. Example:
650 * func#0 @0
651 * 0: R1=ctx(id=0,off=0,imm=0) R10=fp0
652 * 0: (b7) r3 = 2 ; R3_w=inv2
653 */
645 if (!strstr(line_ptr, m.match)) {654 if (!strstr(line_ptr, m.match)) {
655 cur_line = -1;
656 line_ptr = strtok(NULL, "\n");
657 sscanf(line_ptr, "%u: ", &cur_line);
658 }
659 if (cur_line != m.line || !line_ptr ||
660 !strstr(line_ptr, m.match)) {
646 printf("Failed to find match %u: %s\n",661 printf("Failed to find match %u: %s\n",
647 m.line, m.match);662 m.line, m.match);
648 ret = 1;663 ret = 1;
tools/testing/selftests/bpf/prog_tests/bpf_obj_id.c+2−2
@@ -65,8 +65,8 @@ void serial_test_bpf_obj_id(void) · 64 unmodified lines
65 if (CHECK_FAIL(err))65 if (CHECK_FAIL(err))
66 goto done;66 goto done;
67 67
68 prog = bpf_object__find_program_by_title(objs[i],68 prog = bpf_object__find_program_by_name(objs[i],
69 "raw_tp/sys_enter");69 "test_obj_id");
70 if (CHECK_FAIL(!prog))70 if (CHECK_FAIL(!prog))
71 goto done;71 goto done;
72 links[i] = bpf_program__attach(prog);72 links[i] = bpf_program__attach(prog);
tools/testing/selftests/bpf/prog_tests/bpf_tcp_ca.c+3−4
@@ -217,7 +217,7 @@ static bool found; · 216 unmodified lines
217static int libbpf_debug_print(enum libbpf_print_level level,217static int libbpf_debug_print(enum libbpf_print_level level,
218 const char *format, va_list args)218 const char *format, va_list args)
219{219{
220 const char *log_buf;220 const char *prog_name, *log_buf;
221 221
222 if (level != LIBBPF_WARN ||222 if (level != LIBBPF_WARN ||
223 !strstr(format, "-- BEGIN PROG LOAD LOG --")) {223 !strstr(format, "-- BEGIN PROG LOAD LOG --")) {
@@ -225,15 +225,14 @@ static int libbpf_debug_print(enum libbpf_print_level level, · 1 unmodified line
225 return 0;225 return 0;
226 }226 }
227 227
228 /* skip prog_name */228 prog_name = va_arg(args, char *);
229 va_arg(args, char *);
230 log_buf = va_arg(args, char *);229 log_buf = va_arg(args, char *);
231 if (!log_buf)230 if (!log_buf)
232 goto out;231 goto out;
233 if (err_str && strstr(log_buf, err_str) != NULL)232 if (err_str && strstr(log_buf, err_str) != NULL)
234 found = true;233 found = true;
235out:234out:
236 printf(format, log_buf);235 printf(format, prog_name, log_buf);
237 return 0;236 return 0;
238}237}
239 238
tools/testing/selftests/bpf/prog_tests/btf.c+0−1
@@ -22,7 +22,6 @@ · 21 unmodified lines
22#include <bpf/libbpf.h>22#include <bpf/libbpf.h>
23#include <bpf/btf.h>23#include <bpf/btf.h>
24 24
25#include "bpf_rlimit.h"
26#include "bpf_util.h"25#include "bpf_util.h"
27#include "../test_btf.h"26#include "../test_btf.h"
28#include "test_progs.h"27#include "test_progs.h"
tools/testing/selftests/bpf/prog_tests/connect_force_port.c+9−9
@@ -67,9 +67,9 @@ static int run_test(int cgroup_fd, int server_fd, int family, int type) · 66 unmodified lines
67 goto close_bpf_object;67 goto close_bpf_object;
68 }68 }
69 69
70 prog = bpf_object__find_program_by_title(obj, v4 ?70 prog = bpf_object__find_program_by_name(obj, v4 ?
71 "cgroup/connect4" :71 "connect4" :
72 "cgroup/connect6");72 "connect6");
73 if (CHECK(!prog, "find_prog", "connect prog not found\n")) {73 if (CHECK(!prog, "find_prog", "connect prog not found\n")) {
74 err = -EIO;74 err = -EIO;
75 goto close_bpf_object;75 goto close_bpf_object;
@@ -83,9 +83,9 @@ static int run_test(int cgroup_fd, int server_fd, int family, int type) · 7 unmodified lines
83 goto close_bpf_object;83 goto close_bpf_object;
84 }84 }
85 85
86 prog = bpf_object__find_program_by_title(obj, v4 ?86 prog = bpf_object__find_program_by_name(obj, v4 ?
87 "cgroup/getpeername4" :87 "getpeername4" :
88 "cgroup/getpeername6");88 "getpeername6");
89 if (CHECK(!prog, "find_prog", "getpeername prog not found\n")) {89 if (CHECK(!prog, "find_prog", "getpeername prog not found\n")) {
90 err = -EIO;90 err = -EIO;
91 goto close_bpf_object;91 goto close_bpf_object;
@@ -99,9 +99,9 @@ static int run_test(int cgroup_fd, int server_fd, int family, int type) · 7 unmodified lines
99 goto close_bpf_object;99 goto close_bpf_object;
100 }100 }
101 101
102 prog = bpf_object__find_program_by_title(obj, v4 ?102 prog = bpf_object__find_program_by_name(obj, v4 ?
103 "cgroup/getsockname4" :103 "getsockname4" :
104 "cgroup/getsockname6");104 "getsockname6");
105 if (CHECK(!prog, "find_prog", "getsockname prog not found\n")) {105 if (CHECK(!prog, "find_prog", "getsockname prog not found\n")) {
106 err = -EIO;106 err = -EIO;
107 goto close_bpf_object;107 goto close_bpf_object;
tools/testing/selftests/bpf/prog_tests/core_reloc.c+53−26
@@ -10,7 +10,7 @@ static int duration = 0; · 9 unmodified lines
10 10
11#define STRUCT_TO_CHAR_PTR(struct_name) (const char *)&(struct struct_name)11#define STRUCT_TO_CHAR_PTR(struct_name) (const char *)&(struct struct_name)
12 12
13#define MODULES_CASE(name, sec_name, tp_name) { \13#define MODULES_CASE(name, pg_name, tp_name) { \
14 .case_name = name, \14 .case_name = name, \
15 .bpf_obj_file = "test_core_reloc_module.o", \15 .bpf_obj_file = "test_core_reloc_module.o", \
16 .btf_src_file = NULL, /* find in kernel module BTFs */ \16 .btf_src_file = NULL, /* find in kernel module BTFs */ \
@@ -28,7 +28,7 @@ static int duration = 0; · 11 unmodified lines
28 .comm_len = sizeof("test_progs"), \28 .comm_len = sizeof("test_progs"), \
29 }, \29 }, \
30 .output_len = sizeof(struct core_reloc_module_output), \30 .output_len = sizeof(struct core_reloc_module_output), \
31 .prog_sec_name = sec_name, \31 .prog_name = pg_name, \
32 .raw_tp_name = tp_name, \32 .raw_tp_name = tp_name, \
33 .trigger = __trigger_module_test_read, \33 .trigger = __trigger_module_test_read, \
34 .needs_testmod = true, \34 .needs_testmod = true, \
@@ -43,7 +43,9 @@ static int duration = 0; · 8 unmodified lines
43#define FLAVORS_CASE_COMMON(name) \43#define FLAVORS_CASE_COMMON(name) \
44 .case_name = #name, \44 .case_name = #name, \
45 .bpf_obj_file = "test_core_reloc_flavors.o", \45 .bpf_obj_file = "test_core_reloc_flavors.o", \
46 .btf_src_file = "btf__core_reloc_" #name ".o" \46 .btf_src_file = "btf__core_reloc_" #name ".o", \
47 .raw_tp_name = "sys_enter", \
48 .prog_name = "test_core_flavors" \
47 49
48#define FLAVORS_CASE(name) { \50#define FLAVORS_CASE(name) { \
49 FLAVORS_CASE_COMMON(name), \51 FLAVORS_CASE_COMMON(name), \
@@ -66,7 +68,9 @@ static int duration = 0; · 16 unmodified lines
66#define NESTING_CASE_COMMON(name) \68#define NESTING_CASE_COMMON(name) \
67 .case_name = #name, \69 .case_name = #name, \
68 .bpf_obj_file = "test_core_reloc_nesting.o", \70 .bpf_obj_file = "test_core_reloc_nesting.o", \
69 .btf_src_file = "btf__core_reloc_" #name ".o"71 .btf_src_file = "btf__core_reloc_" #name ".o", \
72 .raw_tp_name = "sys_enter", \
73 .prog_name = "test_core_nesting" \
70 74
71#define NESTING_CASE(name) { \75#define NESTING_CASE(name) { \
72 NESTING_CASE_COMMON(name), \76 NESTING_CASE_COMMON(name), \
@@ -91,7 +95,9 @@ static int duration = 0; · 18 unmodified lines
91#define ARRAYS_CASE_COMMON(name) \95#define ARRAYS_CASE_COMMON(name) \
92 .case_name = #name, \96 .case_name = #name, \
93 .bpf_obj_file = "test_core_reloc_arrays.o", \97 .bpf_obj_file = "test_core_reloc_arrays.o", \
94 .btf_src_file = "btf__core_reloc_" #name ".o"98 .btf_src_file = "btf__core_reloc_" #name ".o", \
99 .raw_tp_name = "sys_enter", \
100 .prog_name = "test_core_arrays" \
95 101
96#define ARRAYS_CASE(name) { \102#define ARRAYS_CASE(name) { \
97 ARRAYS_CASE_COMMON(name), \103 ARRAYS_CASE_COMMON(name), \
@@ -123,7 +129,9 @@ static int duration = 0; · 25 unmodified lines
123#define PRIMITIVES_CASE_COMMON(name) \129#define PRIMITIVES_CASE_COMMON(name) \
124 .case_name = #name, \130 .case_name = #name, \
125 .bpf_obj_file = "test_core_reloc_primitives.o", \131 .bpf_obj_file = "test_core_reloc_primitives.o", \
126 .btf_src_file = "btf__core_reloc_" #name ".o"132 .btf_src_file = "btf__core_reloc_" #name ".o", \
133 .raw_tp_name = "sys_enter", \
134 .prog_name = "test_core_primitives" \
127 135
128#define PRIMITIVES_CASE(name) { \136#define PRIMITIVES_CASE(name) { \
129 PRIMITIVES_CASE_COMMON(name), \137 PRIMITIVES_CASE_COMMON(name), \
@@ -158,6 +166,8 @@ static int duration = 0; · 28 unmodified lines
158 .e = 5, .f = 6, .g = 7, .h = 8, \166 .e = 5, .f = 6, .g = 7, .h = 8, \
159 }, \167 }, \
160 .output_len = sizeof(struct core_reloc_mods_output), \168 .output_len = sizeof(struct core_reloc_mods_output), \
169 .raw_tp_name = "sys_enter", \
170 .prog_name = "test_core_mods", \
161}171}
162 172
163#define PTR_AS_ARR_CASE(name) { \173#define PTR_AS_ARR_CASE(name) { \
@@ -174,6 +184,8 @@ static int duration = 0; · 10 unmodified lines
174 .a = 3, \184 .a = 3, \
175 }, \185 }, \
176 .output_len = sizeof(struct core_reloc_ptr_as_arr), \186 .output_len = sizeof(struct core_reloc_ptr_as_arr), \
187 .raw_tp_name = "sys_enter", \
188 .prog_name = "test_core_ptr_as_arr", \
177}189}
178 190
179#define INTS_DATA(struct_name) STRUCT_TO_CHAR_PTR(struct_name) { \191#define INTS_DATA(struct_name) STRUCT_TO_CHAR_PTR(struct_name) { \
@@ -190,7 +202,9 @@ static int duration = 0; · 10 unmodified lines
190#define INTS_CASE_COMMON(name) \202#define INTS_CASE_COMMON(name) \
191 .case_name = #name, \203 .case_name = #name, \
192 .bpf_obj_file = "test_core_reloc_ints.o", \204 .bpf_obj_file = "test_core_reloc_ints.o", \
193 .btf_src_file = "btf__core_reloc_" #name ".o"205 .btf_src_file = "btf__core_reloc_" #name ".o", \
206 .raw_tp_name = "sys_enter", \
207 .prog_name = "test_core_ints"
194 208
195#define INTS_CASE(name) { \209#define INTS_CASE(name) { \
196 INTS_CASE_COMMON(name), \210 INTS_CASE_COMMON(name), \
@@ -208,7 +222,9 @@ static int duration = 0; · 11 unmodified lines
208#define FIELD_EXISTS_CASE_COMMON(name) \222#define FIELD_EXISTS_CASE_COMMON(name) \
209 .case_name = #name, \223 .case_name = #name, \
210 .bpf_obj_file = "test_core_reloc_existence.o", \224 .bpf_obj_file = "test_core_reloc_existence.o", \
211 .btf_src_file = "btf__core_reloc_" #name ".o" \225 .btf_src_file = "btf__core_reloc_" #name ".o", \
226 .raw_tp_name = "sys_enter", \
227 .prog_name = "test_core_existence"
212 228
213#define BITFIELDS_CASE_COMMON(objfile, test_name_prefix, name) \229#define BITFIELDS_CASE_COMMON(objfile, test_name_prefix, name) \
214 .case_name = test_name_prefix#name, \230 .case_name = test_name_prefix#name, \
@@ -223,6 +239,8 @@ static int duration = 0; · 8 unmodified lines
223 .output = STRUCT_TO_CHAR_PTR(core_reloc_bitfields_output) \239 .output = STRUCT_TO_CHAR_PTR(core_reloc_bitfields_output) \
224 __VA_ARGS__, \240 __VA_ARGS__, \
225 .output_len = sizeof(struct core_reloc_bitfields_output), \241 .output_len = sizeof(struct core_reloc_bitfields_output), \
242 .raw_tp_name = "sys_enter", \
243 .prog_name = "test_core_bitfields", \
226}, { \244}, { \
227 BITFIELDS_CASE_COMMON("test_core_reloc_bitfields_direct.o", \245 BITFIELDS_CASE_COMMON("test_core_reloc_bitfields_direct.o", \
228 "direct:", name), \246 "direct:", name), \
@@ -231,7 +249,7 @@ static int duration = 0; · 2 unmodified lines
231 .output = STRUCT_TO_CHAR_PTR(core_reloc_bitfields_output) \249 .output = STRUCT_TO_CHAR_PTR(core_reloc_bitfields_output) \
232 __VA_ARGS__, \250 __VA_ARGS__, \
233 .output_len = sizeof(struct core_reloc_bitfields_output), \251 .output_len = sizeof(struct core_reloc_bitfields_output), \
234 .prog_sec_name = "tp_btf/sys_enter", \252 .prog_name = "test_core_bitfields_direct", \
235}253}
236 254
237 255
@@ -239,17 +257,21 @@ static int duration = 0; · 1 unmodified line
239 BITFIELDS_CASE_COMMON("test_core_reloc_bitfields_probed.o", \257 BITFIELDS_CASE_COMMON("test_core_reloc_bitfields_probed.o", \
240 "probed:", name), \258 "probed:", name), \
241 .fails = true, \259 .fails = true, \
260 .raw_tp_name = "sys_enter", \
261 .prog_name = "test_core_bitfields", \
242}, { \262}, { \
243 BITFIELDS_CASE_COMMON("test_core_reloc_bitfields_direct.o", \263 BITFIELDS_CASE_COMMON("test_core_reloc_bitfields_direct.o", \
244 "direct:", name), \264 "direct:", name), \
245 .prog_sec_name = "tp_btf/sys_enter", \
246 .fails = true, \265 .fails = true, \
266 .prog_name = "test_core_bitfields_direct", \
247}267}
248 268
249#define SIZE_CASE_COMMON(name) \269#define SIZE_CASE_COMMON(name) \
250 .case_name = #name, \270 .case_name = #name, \
251 .bpf_obj_file = "test_core_reloc_size.o", \271 .bpf_obj_file = "test_core_reloc_size.o", \
252 .btf_src_file = "btf__core_reloc_" #name ".o"272 .btf_src_file = "btf__core_reloc_" #name ".o", \
273 .raw_tp_name = "sys_enter", \
274 .prog_name = "test_core_size"
253 275
254#define SIZE_OUTPUT_DATA(type) \276#define SIZE_OUTPUT_DATA(type) \
255 STRUCT_TO_CHAR_PTR(core_reloc_size_output) { \277 STRUCT_TO_CHAR_PTR(core_reloc_size_output) { \
@@ -277,8 +299,10 @@ static int duration = 0; · 21 unmodified lines
277 299
278#define TYPE_BASED_CASE_COMMON(name) \300#define TYPE_BASED_CASE_COMMON(name) \
279 .case_name = #name, \301 .case_name = #name, \
280 .bpf_obj_file = "test_core_reloc_type_based.o", \302 .bpf_obj_file = "test_core_reloc_type_based.o", \
281 .btf_src_file = "btf__core_reloc_" #name ".o" \303 .btf_src_file = "btf__core_reloc_" #name ".o", \
304 .raw_tp_name = "sys_enter", \
305 .prog_name = "test_core_type_based"
282 306
283#define TYPE_BASED_CASE(name, ...) { \307#define TYPE_BASED_CASE(name, ...) { \
284 TYPE_BASED_CASE_COMMON(name), \308 TYPE_BASED_CASE_COMMON(name), \
@@ -295,7 +319,9 @@ static int duration = 0; · 10 unmodified lines
295#define TYPE_ID_CASE_COMMON(name) \319#define TYPE_ID_CASE_COMMON(name) \
296 .case_name = #name, \320 .case_name = #name, \
297 .bpf_obj_file = "test_core_reloc_type_id.o", \321 .bpf_obj_file = "test_core_reloc_type_id.o", \
298 .btf_src_file = "btf__core_reloc_" #name ".o" \322 .btf_src_file = "btf__core_reloc_" #name ".o", \
323 .raw_tp_name = "sys_enter", \
324 .prog_name = "test_core_type_id"
299 325
300#define TYPE_ID_CASE(name, setup_fn) { \326#define TYPE_ID_CASE(name, setup_fn) { \
301 TYPE_ID_CASE_COMMON(name), \327 TYPE_ID_CASE_COMMON(name), \
@@ -312,7 +338,9 @@ static int duration = 0; · 10 unmodified lines
312#define ENUMVAL_CASE_COMMON(name) \338#define ENUMVAL_CASE_COMMON(name) \
313 .case_name = #name, \339 .case_name = #name, \
314 .bpf_obj_file = "test_core_reloc_enumval.o", \340 .bpf_obj_file = "test_core_reloc_enumval.o", \
315 .btf_src_file = "btf__core_reloc_" #name ".o" \341 .btf_src_file = "btf__core_reloc_" #name ".o", \
342 .raw_tp_name = "sys_enter", \
343 .prog_name = "test_core_enumval"
316 344
317#define ENUMVAL_CASE(name, ...) { \345#define ENUMVAL_CASE(name, ...) { \
318 ENUMVAL_CASE_COMMON(name), \346 ENUMVAL_CASE_COMMON(name), \
@@ -342,7 +370,7 @@ struct core_reloc_test_case { · 23 unmodified lines
342 bool fails;370 bool fails;
343 bool needs_testmod;371 bool needs_testmod;
344 bool relaxed_core_relocs;372 bool relaxed_core_relocs;
345 const char *prog_sec_name;373 const char *prog_name;
346 const char *raw_tp_name;374 const char *raw_tp_name;
347 setup_test_fn setup;375 setup_test_fn setup;
348 trigger_test_fn trigger;376 trigger_test_fn trigger;
@@ -497,11 +525,13 @@ static struct core_reloc_test_case test_cases[] = { · 148 unmodified lines
497 .comm_len = sizeof("test_progs"),525 .comm_len = sizeof("test_progs"),
498 },526 },
499 .output_len = sizeof(struct core_reloc_kernel_output),527 .output_len = sizeof(struct core_reloc_kernel_output),
528 .raw_tp_name = "sys_enter",
529 .prog_name = "test_core_kernel",
500 },530 },
501 531
502 /* validate we can find kernel module BTF types for relocs/attach */532 /* validate we can find kernel module BTF types for relocs/attach */
503 MODULES_CASE("module_probed", "raw_tp/bpf_testmod_test_read", "bpf_testmod_test_read"),533 MODULES_CASE("module_probed", "test_core_module_probed", "bpf_testmod_test_read"),
504 MODULES_CASE("module_direct", "tp_btf/bpf_testmod_test_read", NULL),534 MODULES_CASE("module_direct", "test_core_module_direct", NULL),
505 535
506 /* validate BPF program can use multiple flavors to match against536 /* validate BPF program can use multiple flavors to match against
507 * single target BTF type537 * single target BTF type
@@ -580,6 +610,8 @@ static struct core_reloc_test_case test_cases[] = { · 72 unmodified lines
580 .c = 0, /* BUG in clang, should be 3 */610 .c = 0, /* BUG in clang, should be 3 */
581 },611 },
582 .output_len = sizeof(struct core_reloc_misc_output),612 .output_len = sizeof(struct core_reloc_misc_output),
613 .raw_tp_name = "sys_enter",
614 .prog_name = "test_core_misc",
583 },615 },
584 616
585 /* validate field existence checks */617 /* validate field existence checks */
@@ -848,14 +880,9 @@ void test_core_reloc(void) · 262 unmodified lines
848 if (!ASSERT_OK_PTR(obj, "obj_open"))880 if (!ASSERT_OK_PTR(obj, "obj_open"))
849 goto cleanup;881 goto cleanup;
850 882
851 probe_name = "raw_tracepoint/sys_enter";883 probe_name = test_case->prog_name;
852 tp_name = "sys_enter";884 tp_name = test_case->raw_tp_name; /* NULL for tp_btf */
853 if (test_case->prog_sec_name) {885 prog = bpf_object__find_program_by_name(obj, probe_name);
854 probe_name = test_case->prog_sec_name;
855 tp_name = test_case->raw_tp_name; /* NULL for tp_btf */
856 }
857
858 prog = bpf_object__find_program_by_title(obj, probe_name);
859 if (CHECK(!prog, "find_probe",886 if (CHECK(!prog, "find_probe",
860 "prog '%s' not found\n", probe_name))887 "prog '%s' not found\n", probe_name))
861 goto cleanup;888 goto cleanup;
tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c+13−4
@@ -101,6 +101,8 @@ static void test_fexit_bpf2bpf_common(const char *obj_file, · 100 unmodified lines
101 101
102 for (i = 0; i < prog_cnt; i++) {102 for (i = 0; i < prog_cnt; i++) {
103 struct bpf_link_info link_info;103 struct bpf_link_info link_info;
104 struct bpf_program *pos;
105 const char *pos_sec_name;
104 char *tgt_name;106 char *tgt_name;
105 __s32 btf_id;107 __s32 btf_id;
106 108
@@ -109,7 +111,14 @@ static void test_fexit_bpf2bpf_common(const char *obj_file, · 2 unmodified lines
109 goto close_prog;111 goto close_prog;
110 btf_id = btf__find_by_name_kind(btf, tgt_name + 1, BTF_KIND_FUNC);112 btf_id = btf__find_by_name_kind(btf, tgt_name + 1, BTF_KIND_FUNC);
111 113
112 prog[i] = bpf_object__find_program_by_title(obj, prog_name[i]);114 prog[i] = NULL;
115 bpf_object__for_each_program(pos, obj) {
116 pos_sec_name = bpf_program__section_name(pos);
117 if (pos_sec_name && !strcmp(pos_sec_name, prog_name[i])) {
118 prog[i] = pos;
119 break;
120 }
121 }
113 if (!ASSERT_OK_PTR(prog[i], prog_name[i]))122 if (!ASSERT_OK_PTR(prog[i], prog_name[i]))
114 goto close_prog;123 goto close_prog;
115 124
@@ -211,8 +220,8 @@ static void test_func_replace_verify(void) · 95 unmodified lines
211 220
212static int test_second_attach(struct bpf_object *obj)221static int test_second_attach(struct bpf_object *obj)
213{222{
214 const char *prog_name = "freplace/get_constant";223 const char *prog_name = "security_new_get_constant";
215 const char *tgt_name = prog_name + 9; /* cut off freplace/ */224 const char *tgt_name = "get_constant";
216 const char *tgt_obj_file = "./test_pkt_access.o";225 const char *tgt_obj_file = "./test_pkt_access.o";
217 struct bpf_program *prog = NULL;226 struct bpf_program *prog = NULL;
218 struct bpf_object *tgt_obj;227 struct bpf_object *tgt_obj;
@@ -220,7 +229,7 @@ static int test_second_attach(struct bpf_object *obj) · 1 unmodified line
220 struct bpf_link *link;229 struct bpf_link *link;
221 int err = 0, tgt_fd;230 int err = 0, tgt_fd;
222 231
223 prog = bpf_object__find_program_by_title(obj, prog_name);232 prog = bpf_object__find_program_by_name(obj, prog_name);
224 if (CHECK(!prog, "find_prog", "prog %s not found\n", prog_name))233 if (CHECK(!prog, "find_prog", "prog %s not found\n", prog_name))
225 return -ENOENT;234 return -ENOENT;
226 235
tools/testing/selftests/bpf/prog_tests/get_func_args_test.c+44−0
@@ -0,0 +1,44 @@
1// SPDX-License-Identifier: GPL-2.0
2#include <test_progs.h>
3#include "get_func_args_test.skel.h"
4
5void test_get_func_args_test(void)
6{
7 struct get_func_args_test *skel = NULL;
8 __u32 duration = 0, retval;
9 int err, prog_fd;
10
11 skel = get_func_args_test__open_and_load();
12 if (!ASSERT_OK_PTR(skel, "get_func_args_test__open_and_load"))
13 return;
14
15 err = get_func_args_test__attach(skel);
16 if (!ASSERT_OK(err, "get_func_args_test__attach"))
17 goto cleanup;
18
19 /* This runs bpf_fentry_test* functions and triggers
20 * fentry/fexit programs.
21 */
22 prog_fd = bpf_program__fd(skel->progs.test1);
23 err = bpf_prog_test_run(prog_fd, 1, NULL, 0,
24 NULL, NULL, &retval, &duration);
25 ASSERT_OK(err, "test_run");
26 ASSERT_EQ(retval, 0, "test_run");
27
28 /* This runs bpf_modify_return_test function and triggers
29 * fmod_ret_test and fexit_test programs.
30 */
31 prog_fd = bpf_program__fd(skel->progs.fmod_ret_test);
32 err = bpf_prog_test_run(prog_fd, 1, NULL, 0,
33 NULL, NULL, &retval, &duration);
34 ASSERT_OK(err, "test_run");
35 ASSERT_EQ(retval, 1234, "test_run");
36
37 ASSERT_EQ(skel->bss->test1_result, 1, "test1_result");
38 ASSERT_EQ(skel->bss->test2_result, 1, "test2_result");
39 ASSERT_EQ(skel->bss->test3_result, 1, "test3_result");
40 ASSERT_EQ(skel->bss->test4_result, 1, "test4_result");
41
42cleanup:
43 get_func_args_test__destroy(skel);
44}
tools/testing/selftests/bpf/prog_tests/get_stack_raw_tp.c+2−2
@@ -89,7 +89,7 @@ void test_get_stack_raw_tp(void) · 88 unmodified lines
89{89{
90 const char *file = "./test_get_stack_rawtp.o";90 const char *file = "./test_get_stack_rawtp.o";
91 const char *file_err = "./test_get_stack_rawtp_err.o";91 const char *file_err = "./test_get_stack_rawtp_err.o";
92 const char *prog_name = "raw_tracepoint/sys_enter";92 const char *prog_name = "bpf_prog1";
93 int i, err, prog_fd, exp_cnt = MAX_CNT_RAWTP;93 int i, err, prog_fd, exp_cnt = MAX_CNT_RAWTP;
94 struct perf_buffer *pb = NULL;94 struct perf_buffer *pb = NULL;
95 struct bpf_link *link = NULL;95 struct bpf_link *link = NULL;
@@ -107,7 +107,7 @@ void test_get_stack_raw_tp(void) · 11 unmodified lines
107 if (CHECK(err, "prog_load raw tp", "err %d errno %d\n", err, errno))107 if (CHECK(err, "prog_load raw tp", "err %d errno %d\n", err, errno))
108 return;108 return;
109 109
110 prog = bpf_object__find_program_by_title(obj, prog_name);110 prog = bpf_object__find_program_by_name(obj, prog_name);
111 if (CHECK(!prog, "find_probe", "prog '%s' not found\n", prog_name))111 if (CHECK(!prog, "find_probe", "prog '%s' not found\n", prog_name))
112 goto close_prog;112 goto close_prog;
113 113
tools/testing/selftests/bpf/prog_tests/ksyms_btf.c+14−0
@@ -8,6 +8,7 @@ · 7 unmodified lines
8#include "test_ksyms_btf_null_check.skel.h"8#include "test_ksyms_btf_null_check.skel.h"
9#include "test_ksyms_weak.skel.h"9#include "test_ksyms_weak.skel.h"
10#include "test_ksyms_weak.lskel.h"10#include "test_ksyms_weak.lskel.h"
11#include "test_ksyms_btf_write_check.skel.h"
11 12
12static int duration;13static int duration;
13 14
@@ -137,6 +138,16 @@ cleanup: · 123 unmodified lines
137 test_ksyms_weak_lskel__destroy(skel);138 test_ksyms_weak_lskel__destroy(skel);
138}139}
139 140
141static void test_write_check(void)
142{
143 struct test_ksyms_btf_write_check *skel;
144
145 skel = test_ksyms_btf_write_check__open_and_load();
146 ASSERT_ERR_PTR(skel, "unexpected load of a prog writing to ksym memory\n");
147
148 test_ksyms_btf_write_check__destroy(skel);
149}
150
140void test_ksyms_btf(void)151void test_ksyms_btf(void)
141{152{
142 int percpu_datasec;153 int percpu_datasec;
@@ -167,4 +178,7 @@ void test_ksyms_btf(void) · 24 unmodified lines
167 178
168 if (test__start_subtest("weak_ksyms_lskel"))179 if (test__start_subtest("weak_ksyms_lskel"))
169 test_weak_syms_lskel();180 test_weak_syms_lskel();
181
182 if (test__start_subtest("write_check"))
183 test_write_check();
170}184}
tools/testing/selftests/bpf/prog_tests/libbpf_probes.c+124−0
@@ -0,0 +1,124 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/* Copyright (c) 2021 Facebook */
3
4#include <test_progs.h>
5#include <bpf/btf.h>
6
7void test_libbpf_probe_prog_types(void)
8{
9 struct btf *btf;
10 const struct btf_type *t;
11 const struct btf_enum *e;
12 int i, n, id;
13
14 btf = btf__parse("/sys/kernel/btf/vmlinux", NULL);
15 if (!ASSERT_OK_PTR(btf, "btf_parse"))
16 return;
17
18 /* find enum bpf_prog_type and enumerate each value */
19 id = btf__find_by_name_kind(btf, "bpf_prog_type", BTF_KIND_ENUM);
20 if (!ASSERT_GT(id, 0, "bpf_prog_type_id"))
21 goto cleanup;
22 t = btf__type_by_id(btf, id);
23 if (!ASSERT_OK_PTR(t, "bpf_prog_type_enum"))
24 goto cleanup;
25
26 for (e = btf_enum(t), i = 0, n = btf_vlen(t); i < n; e++, i++) {
27 const char *prog_type_name = btf__str_by_offset(btf, e->name_off);
28 enum bpf_prog_type prog_type = (enum bpf_prog_type)e->val;
29 int res;
30
31 if (prog_type == BPF_PROG_TYPE_UNSPEC)
32 continue;
33
34 if (!test__start_subtest(prog_type_name))
35 continue;
36
37 res = libbpf_probe_bpf_prog_type(prog_type, NULL);
38 ASSERT_EQ(res, 1, prog_type_name);
39 }
40
41cleanup:
42 btf__free(btf);
43}
44
45void test_libbpf_probe_map_types(void)
46{
47 struct btf *btf;
48 const struct btf_type *t;
49 const struct btf_enum *e;
50 int i, n, id;
51
52 btf = btf__parse("/sys/kernel/btf/vmlinux", NULL);
53 if (!ASSERT_OK_PTR(btf, "btf_parse"))
54 return;
55
56 /* find enum bpf_map_type and enumerate each value */
57 id = btf__find_by_name_kind(btf, "bpf_map_type", BTF_KIND_ENUM);
58 if (!ASSERT_GT(id, 0, "bpf_map_type_id"))
59 goto cleanup;
60 t = btf__type_by_id(btf, id);
61 if (!ASSERT_OK_PTR(t, "bpf_map_type_enum"))
62 goto cleanup;
63
64 for (e = btf_enum(t), i = 0, n = btf_vlen(t); i < n; e++, i++) {
65 const char *map_type_name = btf__str_by_offset(btf, e->name_off);
66 enum bpf_map_type map_type = (enum bpf_map_type)e->val;
67 int res;
68
69 if (map_type == BPF_MAP_TYPE_UNSPEC)
70 continue;
71
72 if (!test__start_subtest(map_type_name))
73 continue;
74
75 res = libbpf_probe_bpf_map_type(map_type, NULL);
76 ASSERT_EQ(res, 1, map_type_name);
77 }
78
79cleanup:
80 btf__free(btf);
81}
82
83void test_libbpf_probe_helpers(void)
84{
85#define CASE(prog, helper, supp) { \
86 .prog_type_name = "BPF_PROG_TYPE_" # prog, \
87 .helper_name = "bpf_" # helper, \
88 .prog_type = BPF_PROG_TYPE_ ## prog, \
89 .helper_id = BPF_FUNC_ ## helper, \
90 .supported = supp, \
91}
92 const struct case_def {
93 const char *prog_type_name;
94 const char *helper_name;
95 enum bpf_prog_type prog_type;
96 enum bpf_func_id helper_id;
97 bool supported;
98 } cases[] = {
99 CASE(KPROBE, unspec, false),
100 CASE(KPROBE, map_lookup_elem, true),
101 CASE(KPROBE, loop, true),
102
103 CASE(KPROBE, ktime_get_coarse_ns, false),
104 CASE(SOCKET_FILTER, ktime_get_coarse_ns, true),
105
106 CASE(KPROBE, sys_bpf, false),
107 CASE(SYSCALL, sys_bpf, true),
108 };
109 size_t case_cnt = ARRAY_SIZE(cases), i;
110 char buf[128];
111
112 for (i = 0; i < case_cnt; i++) {
113 const struct case_def *d = &cases[i];
114 int res;
115
116 snprintf(buf, sizeof(buf), "%s+%s", d->prog_type_name, d->helper_name);
117
118 if (!test__start_subtest(buf))
119 continue;
120
121 res = libbpf_probe_bpf_helper(d->prog_type, d->helper_id, NULL);
122 ASSERT_EQ(res, d->supported, buf);
123 }
124}
tools/testing/selftests/bpf/prog_tests/select_reuseport.c+0−1
@@ -18,7 +18,6 @@ · 17 unmodified lines
18#include <netinet/in.h>18#include <netinet/in.h>
19#include <bpf/bpf.h>19#include <bpf/bpf.h>
20#include <bpf/libbpf.h>20#include <bpf/libbpf.h>
21#include "bpf_rlimit.h"
22#include "bpf_util.h"21#include "bpf_util.h"
23 22
24#include "test_progs.h"23#include "test_progs.h"
tools/testing/selftests/bpf/prog_tests/sk_lookup.c+0−1
@@ -30,7 +30,6 @@ · 29 unmodified lines
30#include <bpf/bpf.h>30#include <bpf/bpf.h>
31 31
32#include "test_progs.h"32#include "test_progs.h"
33#include "bpf_rlimit.h"
34#include "bpf_util.h"33#include "bpf_util.h"
35#include "cgroup_helpers.h"34#include "cgroup_helpers.h"
36#include "network_helpers.h"35#include "network_helpers.h"
tools/testing/selftests/bpf/prog_tests/sock_fields.c+0−1
@@ -15,7 +15,6 @@ · 14 unmodified lines
15#include "network_helpers.h"15#include "network_helpers.h"
16#include "cgroup_helpers.h"16#include "cgroup_helpers.h"
17#include "test_progs.h"17#include "test_progs.h"
18#include "bpf_rlimit.h"
19#include "test_sock_fields.skel.h"18#include "test_sock_fields.skel.h"
20 19
21enum bpf_linum_array_idx {20enum bpf_linum_array_idx {
tools/testing/selftests/bpf/prog_tests/sockopt_inherit.c+8−7
@@ -136,7 +136,8 @@ static int start_server(void) · 135 unmodified lines
136 return fd;136 return fd;
137}137}
138 138
139static int prog_attach(struct bpf_object *obj, int cgroup_fd, const char *title)139static int prog_attach(struct bpf_object *obj, int cgroup_fd, const char *title,
140 const char *prog_name)
140{141{
141 enum bpf_attach_type attach_type;142 enum bpf_attach_type attach_type;
142 enum bpf_prog_type prog_type;143 enum bpf_prog_type prog_type;
@@ -145,20 +146,20 @@ static int prog_attach(struct bpf_object *obj, int cgroup_fd, const char *title) · 2 unmodified lines
145 146
146 err = libbpf_prog_type_by_name(title, &prog_type, &attach_type);147 err = libbpf_prog_type_by_name(title, &prog_type, &attach_type);
147 if (err) {148 if (err) {
148 log_err("Failed to deduct types for %s BPF program", title);149 log_err("Failed to deduct types for %s BPF program", prog_name);
149 return -1;150 return -1;
150 }151 }
151 152
152 prog = bpf_object__find_program_by_title(obj, title);153 prog = bpf_object__find_program_by_name(obj, prog_name);
153 if (!prog) {154 if (!prog) {
154 log_err("Failed to find %s BPF program", title);155 log_err("Failed to find %s BPF program", prog_name);
155 return -1;156 return -1;
156 }157 }
157 158
158 err = bpf_prog_attach(bpf_program__fd(prog), cgroup_fd,159 err = bpf_prog_attach(bpf_program__fd(prog), cgroup_fd,
159 attach_type, 0);160 attach_type, 0);
160 if (err) {161 if (err) {
161 log_err("Failed to attach %s BPF program", title);162 log_err("Failed to attach %s BPF program", prog_name);
162 return -1;163 return -1;
163 }164 }
164 165
@@ -181,11 +182,11 @@ static void run_test(int cgroup_fd) · 16 unmodified lines
181 if (!ASSERT_OK(err, "obj_load"))182 if (!ASSERT_OK(err, "obj_load"))
182 goto close_bpf_object;183 goto close_bpf_object;
183 184
184 err = prog_attach(obj, cgroup_fd, "cgroup/getsockopt");185 err = prog_attach(obj, cgroup_fd, "cgroup/getsockopt", "_getsockopt");
185 if (CHECK_FAIL(err))186 if (CHECK_FAIL(err))
186 goto close_bpf_object;187 goto close_bpf_object;
187 188
188 err = prog_attach(obj, cgroup_fd, "cgroup/setsockopt");189 err = prog_attach(obj, cgroup_fd, "cgroup/setsockopt", "_setsockopt");
189 if (CHECK_FAIL(err))190 if (CHECK_FAIL(err))
190 goto close_bpf_object;191 goto close_bpf_object;
191 192
tools/testing/selftests/bpf/prog_tests/stacktrace_map.c+2−2
@@ -4,7 +4,7 @@ · 3 unmodified lines
4void test_stacktrace_map(void)4void test_stacktrace_map(void)
5{5{
6 int control_map_fd, stackid_hmap_fd, stackmap_fd, stack_amap_fd;6 int control_map_fd, stackid_hmap_fd, stackmap_fd, stack_amap_fd;
7 const char *prog_name = "tracepoint/sched/sched_switch";7 const char *prog_name = "oncpu";
8 int err, prog_fd, stack_trace_len;8 int err, prog_fd, stack_trace_len;
9 const char *file = "./test_stacktrace_map.o";9 const char *file = "./test_stacktrace_map.o";
10 __u32 key, val, duration = 0;10 __u32 key, val, duration = 0;
@@ -16,7 +16,7 @@ void test_stacktrace_map(void) · 5 unmodified lines
16 if (CHECK(err, "prog_load", "err %d errno %d\n", err, errno))16 if (CHECK(err, "prog_load", "err %d errno %d\n", err, errno))
17 return;17 return;
18 18
19 prog = bpf_object__find_program_by_title(obj, prog_name);19 prog = bpf_object__find_program_by_name(obj, prog_name);
20 if (CHECK(!prog, "find_prog", "prog '%s' not found\n", prog_name))20 if (CHECK(!prog, "find_prog", "prog '%s' not found\n", prog_name))
21 goto close_prog;21 goto close_prog;
22 22
tools/testing/selftests/bpf/prog_tests/stacktrace_map_raw_tp.c+2−2
@@ -3,7 +3,7 @@ · 2 unmodified lines
3 3
4void test_stacktrace_map_raw_tp(void)4void test_stacktrace_map_raw_tp(void)
5{5{
6 const char *prog_name = "tracepoint/sched/sched_switch";6 const char *prog_name = "oncpu";
7 int control_map_fd, stackid_hmap_fd, stackmap_fd;7 int control_map_fd, stackid_hmap_fd, stackmap_fd;
8 const char *file = "./test_stacktrace_map.o";8 const char *file = "./test_stacktrace_map.o";
9 __u32 key, val, duration = 0;9 __u32 key, val, duration = 0;
@@ -16,7 +16,7 @@ void test_stacktrace_map_raw_tp(void) · 6 unmodified lines
16 if (CHECK(err, "prog_load raw tp", "err %d errno %d\n", err, errno))16 if (CHECK(err, "prog_load raw tp", "err %d errno %d\n", err, errno))
17 return;17 return;
18 18
19 prog = bpf_object__find_program_by_title(obj, prog_name);19 prog = bpf_object__find_program_by_name(obj, prog_name);
20 if (CHECK(!prog, "find_prog", "prog '%s' not found\n", prog_name))20 if (CHECK(!prog, "find_prog", "prog '%s' not found\n", prog_name))
21 goto close_prog;21 goto close_prog;
22 22
tools/testing/selftests/bpf/prog_tests/test_local_storage.c+6−14
@@ -28,10 +28,6 @@ static unsigned int duration; · 27 unmodified lines
28struct storage {28struct storage {
29 void *inode;29 void *inode;
30 unsigned int value;30 unsigned int value;
31 /* Lock ensures that spin locked versions of local stoage operations
32 * also work, most operations in this tests are still single threaded
33 */
34 struct bpf_spin_lock lock;
35};31};
36 32
37/* Fork and exec the provided rm binary and return the exit code of the33/* Fork and exec the provided rm binary and return the exit code of the
@@ -66,27 +62,24 @@ static int run_self_unlink(int *monitored_pid, const char *rm_path) · 28 unmodified lines
66 62
67static bool check_syscall_operations(int map_fd, int obj_fd)63static bool check_syscall_operations(int map_fd, int obj_fd)
68{64{
69 struct storage val = { .value = TEST_STORAGE_VALUE, .lock = { 0 } },65 struct storage val = { .value = TEST_STORAGE_VALUE },
70 lookup_val = { .value = 0, .lock = { 0 } };66 lookup_val = { .value = 0 };
71 int err;67 int err;
72 68
73 /* Looking up an existing element should fail initially */69 /* Looking up an existing element should fail initially */
74 err = bpf_map_lookup_elem_flags(map_fd, &obj_fd, &lookup_val,70 err = bpf_map_lookup_elem_flags(map_fd, &obj_fd, &lookup_val, 0);
75 BPF_F_LOCK);
76 if (CHECK(!err || errno != ENOENT, "bpf_map_lookup_elem",71 if (CHECK(!err || errno != ENOENT, "bpf_map_lookup_elem",
77 "err:%d errno:%d\n", err, errno))72 "err:%d errno:%d\n", err, errno))
78 return false;73 return false;
79 74
80 /* Create a new element */75 /* Create a new element */
81 err = bpf_map_update_elem(map_fd, &obj_fd, &val,76 err = bpf_map_update_elem(map_fd, &obj_fd, &val, BPF_NOEXIST);
82 BPF_NOEXIST | BPF_F_LOCK);
83 if (CHECK(err < 0, "bpf_map_update_elem", "err:%d errno:%d\n", err,77 if (CHECK(err < 0, "bpf_map_update_elem", "err:%d errno:%d\n", err,
84 errno))78 errno))
85 return false;79 return false;
86 80
87 /* Lookup the newly created element */81 /* Lookup the newly created element */
88 err = bpf_map_lookup_elem_flags(map_fd, &obj_fd, &lookup_val,82 err = bpf_map_lookup_elem_flags(map_fd, &obj_fd, &lookup_val, 0);
89 BPF_F_LOCK);
90 if (CHECK(err < 0, "bpf_map_lookup_elem", "err:%d errno:%d", err,83 if (CHECK(err < 0, "bpf_map_lookup_elem", "err:%d errno:%d", err,
91 errno))84 errno))
92 return false;85 return false;
@@ -102,8 +95,7 @@ static bool check_syscall_operations(int map_fd, int obj_fd) · 9 unmodified lines
102 return false;95 return false;
103 96
104 /* The lookup should fail, now that the element has been deleted */97 /* The lookup should fail, now that the element has been deleted */
105 err = bpf_map_lookup_elem_flags(map_fd, &obj_fd, &lookup_val,98 err = bpf_map_lookup_elem_flags(map_fd, &obj_fd, &lookup_val, 0);
106 BPF_F_LOCK);
107 if (CHECK(!err || errno != ENOENT, "bpf_map_lookup_elem",99 if (CHECK(!err || errno != ENOENT, "bpf_map_lookup_elem",
108 "err:%d errno:%d\n", err, errno))100 "err:%d errno:%d\n", err, errno))
109 return false;101 return false;
tools/testing/selftests/bpf/prog_tests/test_overhead.c+10−10
@@ -56,11 +56,11 @@ static void setaffinity(void) · 55 unmodified lines
56 56
57void test_test_overhead(void)57void test_test_overhead(void)
58{58{
59 const char *kprobe_name = "kprobe/__set_task_comm";59 const char *kprobe_name = "prog1";
60 const char *kretprobe_name = "kretprobe/__set_task_comm";60 const char *kretprobe_name = "prog2";
61 const char *raw_tp_name = "raw_tp/task_rename";61 const char *raw_tp_name = "prog3";
62 const char *fentry_name = "fentry/__set_task_comm";62 const char *fentry_name = "prog4";
63 const char *fexit_name = "fexit/__set_task_comm";63 const char *fexit_name = "prog5";
64 const char *kprobe_func = "__set_task_comm";64 const char *kprobe_func = "__set_task_comm";
65 struct bpf_program *kprobe_prog, *kretprobe_prog, *raw_tp_prog;65 struct bpf_program *kprobe_prog, *kretprobe_prog, *raw_tp_prog;
66 struct bpf_program *fentry_prog, *fexit_prog;66 struct bpf_program *fentry_prog, *fexit_prog;
@@ -76,23 +76,23 @@ void test_test_overhead(void) · 9 unmodified lines
76 if (!ASSERT_OK_PTR(obj, "obj_open_file"))76 if (!ASSERT_OK_PTR(obj, "obj_open_file"))
77 return;77 return;
78 78
79 kprobe_prog = bpf_object__find_program_by_title(obj, kprobe_name);79 kprobe_prog = bpf_object__find_program_by_name(obj, kprobe_name);
80 if (CHECK(!kprobe_prog, "find_probe",80 if (CHECK(!kprobe_prog, "find_probe",
81 "prog '%s' not found\n", kprobe_name))81 "prog '%s' not found\n", kprobe_name))
82 goto cleanup;82 goto cleanup;
83 kretprobe_prog = bpf_object__find_program_by_title(obj, kretprobe_name);83 kretprobe_prog = bpf_object__find_program_by_name(obj, kretprobe_name);
84 if (CHECK(!kretprobe_prog, "find_probe",84 if (CHECK(!kretprobe_prog, "find_probe",
85 "prog '%s' not found\n", kretprobe_name))85 "prog '%s' not found\n", kretprobe_name))
86 goto cleanup;86 goto cleanup;
87 raw_tp_prog = bpf_object__find_program_by_title(obj, raw_tp_name);87 raw_tp_prog = bpf_object__find_program_by_name(obj, raw_tp_name);
88 if (CHECK(!raw_tp_prog, "find_probe",88 if (CHECK(!raw_tp_prog, "find_probe",
89 "prog '%s' not found\n", raw_tp_name))89 "prog '%s' not found\n", raw_tp_name))
90 goto cleanup;90 goto cleanup;
91 fentry_prog = bpf_object__find_program_by_title(obj, fentry_name);91 fentry_prog = bpf_object__find_program_by_name(obj, fentry_name);
92 if (CHECK(!fentry_prog, "find_probe",92 if (CHECK(!fentry_prog, "find_probe",
93 "prog '%s' not found\n", fentry_name))93 "prog '%s' not found\n", fentry_name))
94 goto cleanup;94 goto cleanup;
95 fexit_prog = bpf_object__find_program_by_title(obj, fexit_name);95 fexit_prog = bpf_object__find_program_by_name(obj, fexit_name);
96 if (CHECK(!fexit_prog, "find_probe",96 if (CHECK(!fexit_prog, "find_probe",
97 "prog '%s' not found\n", fexit_name))97 "prog '%s' not found\n", fexit_name))
98 goto cleanup;98 goto cleanup;
tools/testing/selftests/bpf/prog_tests/test_strncmp.c+167−0
@@ -0,0 +1,167 @@
1// SPDX-License-Identifier: GPL-2.0
2/* Copyright (C) 2021. Huawei Technologies Co., Ltd */
3#include <test_progs.h>
4#include "strncmp_test.skel.h"
5
6static int trigger_strncmp(const struct strncmp_test *skel)
7{
8 int cmp;
9
10 usleep(1);
11
12 cmp = skel->bss->cmp_ret;
13 if (cmp > 0)
14 return 1;
15 if (cmp < 0)
16 return -1;
17 return 0;
18}
19
20/*
21 * Compare str and target after making str[i] != target[i].
22 * When exp is -1, make str[i] < target[i] and delta = -1.
23 */
24static void strncmp_full_str_cmp(struct strncmp_test *skel, const char *name,
25 int exp)
26{
27 size_t nr = sizeof(skel->bss->str);
28 char *str = skel->bss->str;
29 int delta = exp;
30 int got;
31 size_t i;
32
33 memcpy(str, skel->rodata->target, nr);
34 for (i = 0; i < nr - 1; i++) {
35 str[i] += delta;
36
37 got = trigger_strncmp(skel);
38 ASSERT_EQ(got, exp, name);
39
40 str[i] -= delta;
41 }
42}
43
44static void test_strncmp_ret(void)
45{
46 struct strncmp_test *skel;
47 struct bpf_program *prog;
48 int err, got;
49
50 skel = strncmp_test__open();
51 if (!ASSERT_OK_PTR(skel, "strncmp_test open"))
52 return;
53
54 bpf_object__for_each_program(prog, skel->obj)
55 bpf_program__set_autoload(prog, false);
56
57 bpf_program__set_autoload(skel->progs.do_strncmp, true);
58
59 err = strncmp_test__load(skel);
60 if (!ASSERT_EQ(err, 0, "strncmp_test load"))
61 goto out;
62
63 err = strncmp_test__attach(skel);
64 if (!ASSERT_EQ(err, 0, "strncmp_test attach"))
65 goto out;
66
67 skel->bss->target_pid = getpid();
68
69 /* Empty str */
70 skel->bss->str[0] = '\0';
71 got = trigger_strncmp(skel);
72 ASSERT_EQ(got, -1, "strncmp: empty str");
73
74 /* Same string */
75 memcpy(skel->bss->str, skel->rodata->target, sizeof(skel->bss->str));
76 got = trigger_strncmp(skel);
77 ASSERT_EQ(got, 0, "strncmp: same str");
78
79 /* Not-null-termainted string */
80 memcpy(skel->bss->str, skel->rodata->target, sizeof(skel->bss->str));
81 skel->bss->str[sizeof(skel->bss->str) - 1] = 'A';
82 got = trigger_strncmp(skel);
83 ASSERT_EQ(got, 1, "strncmp: not-null-term str");
84
85 strncmp_full_str_cmp(skel, "strncmp: less than", -1);
86 strncmp_full_str_cmp(skel, "strncmp: greater than", 1);
87out:
88 strncmp_test__destroy(skel);
89}
90
91static void test_strncmp_bad_not_const_str_size(void)
92{
93 struct strncmp_test *skel;
94 struct bpf_program *prog;
95 int err;
96
97 skel = strncmp_test__open();
98 if (!ASSERT_OK_PTR(skel, "strncmp_test open"))
99 return;
100
101 bpf_object__for_each_program(prog, skel->obj)
102 bpf_program__set_autoload(prog, false);
103
104 bpf_program__set_autoload(skel->progs.strncmp_bad_not_const_str_size,
105 true);
106
107 err = strncmp_test__load(skel);
108 ASSERT_ERR(err, "strncmp_test load bad_not_const_str_size");
109
110 strncmp_test__destroy(skel);
111}
112
113static void test_strncmp_bad_writable_target(void)
114{
115 struct strncmp_test *skel;
116 struct bpf_program *prog;
117 int err;
118
119 skel = strncmp_test__open();
120 if (!ASSERT_OK_PTR(skel, "strncmp_test open"))
121 return;
122
123 bpf_object__for_each_program(prog, skel->obj)
124 bpf_program__set_autoload(prog, false);
125
126 bpf_program__set_autoload(skel->progs.strncmp_bad_writable_target,
127 true);
128
129 err = strncmp_test__load(skel);
130 ASSERT_ERR(err, "strncmp_test load bad_writable_target");
131
132 strncmp_test__destroy(skel);
133}
134
135static void test_strncmp_bad_not_null_term_target(void)
136{
137 struct strncmp_test *skel;
138 struct bpf_program *prog;
139 int err;
140
141 skel = strncmp_test__open();
142 if (!ASSERT_OK_PTR(skel, "strncmp_test open"))
143 return;
144
145 bpf_object__for_each_program(prog, skel->obj)
146 bpf_program__set_autoload(prog, false);
147
148 bpf_program__set_autoload(skel->progs.strncmp_bad_not_null_term_target,
149 true);
150
151 err = strncmp_test__load(skel);
152 ASSERT_ERR(err, "strncmp_test load bad_not_null_term_target");
153
154 strncmp_test__destroy(skel);
155}
156
157void test_test_strncmp(void)
158{
159 if (test__start_subtest("strncmp_ret"))
160 test_strncmp_ret();
161 if (test__start_subtest("strncmp_bad_not_const_str_size"))
162 test_strncmp_bad_not_const_str_size();
163 if (test__start_subtest("strncmp_bad_writable_target"))
164 test_strncmp_bad_writable_target();
165 if (test__start_subtest("strncmp_bad_not_null_term_target"))
166 test_strncmp_bad_not_null_term_target();
167}
tools/testing/selftests/bpf/prog_tests/trampoline_count.c+3−3
@@ -35,7 +35,7 @@ static struct bpf_link *load(struct bpf_object *obj, const char *name) · 34 unmodified lines
35 struct bpf_program *prog;35 struct bpf_program *prog;
36 int duration = 0;36 int duration = 0;
37 37
38 prog = bpf_object__find_program_by_title(obj, name);38 prog = bpf_object__find_program_by_name(obj, name);
39 if (CHECK(!prog, "find_probe", "prog '%s' not found\n", name))39 if (CHECK(!prog, "find_probe", "prog '%s' not found\n", name))
40 return ERR_PTR(-EINVAL);40 return ERR_PTR(-EINVAL);
41 return bpf_program__attach_trace(prog);41 return bpf_program__attach_trace(prog);
@@ -44,8 +44,8 @@ static struct bpf_link *load(struct bpf_object *obj, const char *name) · 2 unmodified lines
44/* TODO: use different target function to run in concurrent mode */44/* TODO: use different target function to run in concurrent mode */
45void serial_test_trampoline_count(void)45void serial_test_trampoline_count(void)
46{46{
47 const char *fentry_name = "fentry/__set_task_comm";47 const char *fentry_name = "prog1";
48 const char *fexit_name = "fexit/__set_task_comm";48 const char *fexit_name = "prog2";
49 const char *object = "test_trampoline_count.o";49 const char *object = "test_trampoline_count.o";
50 struct inst inst[MAX_TRAMP_PROGS] = {};50 struct inst inst[MAX_TRAMP_PROGS] = {};
51 int err, i = 0, duration = 0;51 int err, i = 0, duration = 0;
tools/testing/selftests/bpf/progs/get_func_args_test.c+123−0
@@ -0,0 +1,123 @@
1// SPDX-License-Identifier: GPL-2.0
2#include <linux/bpf.h>
3#include <bpf/bpf_helpers.h>
4#include <bpf/bpf_tracing.h>
5#include <errno.h>
6
7char _license[] SEC("license") = "GPL";
8
9__u64 test1_result = 0;
10SEC("fentry/bpf_fentry_test1")
11int BPF_PROG(test1)
12{
13 __u64 cnt = bpf_get_func_arg_cnt(ctx);
14 __u64 a = 0, z = 0, ret = 0;
15 __s64 err;
16
17 test1_result = cnt == 1;
18
19 /* valid arguments */
20 err = bpf_get_func_arg(ctx, 0, &a);
21
22 /* We need to cast access to traced function argument values with
23 * proper type cast, because trampoline uses type specific instruction
24 * to save it, like for 'int a' with 32-bit mov like:
25 *
26 * mov %edi,-0x8(%rbp)
27 *
28 * so the upper 4 bytes are not zeroed.
29 */
30 test1_result &= err == 0 && ((int) a == 1);
31
32 /* not valid argument */
33 err = bpf_get_func_arg(ctx, 1, &z);
34 test1_result &= err == -EINVAL;
35
36 /* return value fails in fentry */
37 err = bpf_get_func_ret(ctx, &ret);
38 test1_result &= err == -EOPNOTSUPP;
39 return 0;
40}
41
42__u64 test2_result = 0;
43SEC("fexit/bpf_fentry_test2")
44int BPF_PROG(test2)
45{
46 __u64 cnt = bpf_get_func_arg_cnt(ctx);
47 __u64 a = 0, b = 0, z = 0, ret = 0;
48 __s64 err;
49
50 test2_result = cnt == 2;
51
52 /* valid arguments */
53 err = bpf_get_func_arg(ctx, 0, &a);
54 test2_result &= err == 0 && (int) a == 2;
55
56 err = bpf_get_func_arg(ctx, 1, &b);
57 test2_result &= err == 0 && b == 3;
58
59 /* not valid argument */
60 err = bpf_get_func_arg(ctx, 2, &z);
61 test2_result &= err == -EINVAL;
62
63 /* return value */
64 err = bpf_get_func_ret(ctx, &ret);
65 test2_result &= err == 0 && ret == 5;
66 return 0;
67}
68
69__u64 test3_result = 0;
70SEC("fmod_ret/bpf_modify_return_test")
71int BPF_PROG(fmod_ret_test, int _a, int *_b, int _ret)
72{
73 __u64 cnt = bpf_get_func_arg_cnt(ctx);
74 __u64 a = 0, b = 0, z = 0, ret = 0;
75 __s64 err;
76
77 test3_result = cnt == 2;
78
79 /* valid arguments */
80 err = bpf_get_func_arg(ctx, 0, &a);
81 test3_result &= err == 0 && ((int) a == 1);
82
83 err = bpf_get_func_arg(ctx, 1, &b);
84 test3_result &= err == 0 && ((int *) b == _b);
85
86 /* not valid argument */
87 err = bpf_get_func_arg(ctx, 2, &z);
88 test3_result &= err == -EINVAL;
89
90 /* return value */
91 err = bpf_get_func_ret(ctx, &ret);
92 test3_result &= err == 0 && ret == 0;
93
94 /* change return value, it's checked in fexit_test program */
95 return 1234;
96}
97
98__u64 test4_result = 0;
99SEC("fexit/bpf_modify_return_test")
100int BPF_PROG(fexit_test, int _a, int *_b, int _ret)
101{
102 __u64 cnt = bpf_get_func_arg_cnt(ctx);
103 __u64 a = 0, b = 0, z = 0, ret = 0;
104 __s64 err;
105
106 test4_result = cnt == 2;
107
108 /* valid arguments */
109 err = bpf_get_func_arg(ctx, 0, &a);
110 test4_result &= err == 0 && ((int) a == 1);
111
112 err = bpf_get_func_arg(ctx, 1, &b);
113 test4_result &= err == 0 && ((int *) b == _b);
114
115 /* not valid argument */
116 err = bpf_get_func_arg(ctx, 2, &z);
117 test4_result &= err == -EINVAL;
118
119 /* return value */
120 err = bpf_get_func_ret(ctx, &ret);
121 test4_result &= err == 0 && ret == 1234;
122 return 0;
123}
tools/testing/selftests/bpf/progs/local_storage.c+5−19
@@ -20,7 +20,6 @@ int sk_storage_result = -1; · 19 unmodified lines
20struct local_storage {20struct local_storage {
21 struct inode *exec_inode;21 struct inode *exec_inode;
22 __u32 value;22 __u32 value;
23 struct bpf_spin_lock lock;
24};23};
25 24
26struct {25struct {
@@ -58,9 +57,7 @@ int BPF_PROG(unlink_hook, struct inode *dir, struct dentry *victim) · 31 unmodified lines
58 bpf_get_current_task_btf(), 0, 0);57 bpf_get_current_task_btf(), 0, 0);
59 if (storage) {58 if (storage) {
60 /* Don't let an executable delete itself */59 /* Don't let an executable delete itself */
61 bpf_spin_lock(&storage->lock);
62 is_self_unlink = storage->exec_inode == victim->d_inode;60 is_self_unlink = storage->exec_inode == victim->d_inode;
63 bpf_spin_unlock(&storage->lock);
64 if (is_self_unlink)61 if (is_self_unlink)
65 return -EPERM;62 return -EPERM;
66 }63 }
@@ -68,7 +65,7 @@ int BPF_PROG(unlink_hook, struct inode *dir, struct dentry *victim) · 1 unmodified line
68 return 0;65 return 0;
69}66}
70 67
71SEC("lsm/inode_rename")68SEC("lsm.s/inode_rename")
72int BPF_PROG(inode_rename, struct inode *old_dir, struct dentry *old_dentry,69int BPF_PROG(inode_rename, struct inode *old_dir, struct dentry *old_dentry,
73 struct inode *new_dir, struct dentry *new_dentry,70 struct inode *new_dir, struct dentry *new_dentry,
74 unsigned int flags)71 unsigned int flags)
@@ -89,10 +86,8 @@ int BPF_PROG(inode_rename, struct inode *old_dir, struct dentry *old_dentry, · 14 unmodified lines
89 if (!storage)86 if (!storage)
90 return 0;87 return 0;
91 88
92 bpf_spin_lock(&storage->lock);
93 if (storage->value != DUMMY_STORAGE_VALUE)89 if (storage->value != DUMMY_STORAGE_VALUE)
94 inode_storage_result = -1;90 inode_storage_result = -1;
95 bpf_spin_unlock(&storage->lock);
96 91
97 err = bpf_inode_storage_delete(&inode_storage_map, old_dentry->d_inode);92 err = bpf_inode_storage_delete(&inode_storage_map, old_dentry->d_inode);
98 if (!err)93 if (!err)
@@ -101,7 +96,7 @@ int BPF_PROG(inode_rename, struct inode *old_dir, struct dentry *old_dentry, · 2 unmodified lines
101 return 0;96 return 0;
102}97}
103 98
104SEC("lsm/socket_bind")99SEC("lsm.s/socket_bind")
105int BPF_PROG(socket_bind, struct socket *sock, struct sockaddr *address,100int BPF_PROG(socket_bind, struct socket *sock, struct sockaddr *address,
106 int addrlen)101 int addrlen)
107{102{
@@ -117,10 +112,8 @@ int BPF_PROG(socket_bind, struct socket *sock, struct sockaddr *address, · 9 unmodified lines
117 if (!storage)112 if (!storage)
118 return 0;113 return 0;
119 114
120 bpf_spin_lock(&storage->lock);
121 if (storage->value != DUMMY_STORAGE_VALUE)115 if (storage->value != DUMMY_STORAGE_VALUE)
122 sk_storage_result = -1;116 sk_storage_result = -1;
123 bpf_spin_unlock(&storage->lock);
124 117
125 err = bpf_sk_storage_delete(&sk_storage_map, sock->sk);118 err = bpf_sk_storage_delete(&sk_storage_map, sock->sk);
126 if (!err)119 if (!err)
@@ -129,7 +122,7 @@ int BPF_PROG(socket_bind, struct socket *sock, struct sockaddr *address, · 2 unmodified lines
129 return 0;122 return 0;
130}123}
131 124
132SEC("lsm/socket_post_create")125SEC("lsm.s/socket_post_create")
133int BPF_PROG(socket_post_create, struct socket *sock, int family, int type,126int BPF_PROG(socket_post_create, struct socket *sock, int family, int type,
134 int protocol, int kern)127 int protocol, int kern)
135{128{
@@ -144,9 +137,7 @@ int BPF_PROG(socket_post_create, struct socket *sock, int family, int type, · 8 unmodified lines
144 if (!storage)137 if (!storage)
145 return 0;138 return 0;
146 139
147 bpf_spin_lock(&storage->lock);
148 storage->value = DUMMY_STORAGE_VALUE;140 storage->value = DUMMY_STORAGE_VALUE;
149 bpf_spin_unlock(&storage->lock);
150 141
151 return 0;142 return 0;
152}143}
@@ -154,7 +145,7 @@ int BPF_PROG(socket_post_create, struct socket *sock, int family, int type, · 1 unmodified line
154/* This uses the local storage to remember the inode of the binary that a145/* This uses the local storage to remember the inode of the binary that a
155 * process was originally executing.146 * process was originally executing.
156 */147 */
157SEC("lsm/bprm_committed_creds")148SEC("lsm.s/bprm_committed_creds")
158void BPF_PROG(exec, struct linux_binprm *bprm)149void BPF_PROG(exec, struct linux_binprm *bprm)
159{150{
160 __u32 pid = bpf_get_current_pid_tgid() >> 32;151 __u32 pid = bpf_get_current_pid_tgid() >> 32;
@@ -166,18 +157,13 @@ void BPF_PROG(exec, struct linux_binprm *bprm) · 5 unmodified lines
166 storage = bpf_task_storage_get(&task_storage_map,157 storage = bpf_task_storage_get(&task_storage_map,
167 bpf_get_current_task_btf(), 0,158 bpf_get_current_task_btf(), 0,
168 BPF_LOCAL_STORAGE_GET_F_CREATE);159 BPF_LOCAL_STORAGE_GET_F_CREATE);
169 if (storage) {160 if (storage)
170 bpf_spin_lock(&storage->lock);
171 storage->exec_inode = bprm->file->f_inode;161 storage->exec_inode = bprm->file->f_inode;
172 bpf_spin_unlock(&storage->lock);
173 }
174 162
175 storage = bpf_inode_storage_get(&inode_storage_map, bprm->file->f_inode,163 storage = bpf_inode_storage_get(&inode_storage_map, bprm->file->f_inode,
176 0, BPF_LOCAL_STORAGE_GET_F_CREATE);164 0, BPF_LOCAL_STORAGE_GET_F_CREATE);
177 if (!storage)165 if (!storage)
178 return;166 return;
179 167
180 bpf_spin_lock(&storage->lock);
181 storage->value = DUMMY_STORAGE_VALUE;168 storage->value = DUMMY_STORAGE_VALUE;
182 bpf_spin_unlock(&storage->lock);
183}169}
tools/testing/selftests/bpf/progs/strncmp_bench.c+50−0
@@ -0,0 +1,50 @@
1// SPDX-License-Identifier: GPL-2.0
2/* Copyright (C) 2021. Huawei Technologies Co., Ltd */
3#include <linux/types.h>
4#include <linux/bpf.h>
5#include <bpf/bpf_helpers.h>
6#include <bpf/bpf_tracing.h>
7
8#define STRNCMP_STR_SZ 4096
9
10/* Will be updated by benchmark before program loading */
11const volatile unsigned int cmp_str_len = 1;
12const char target[STRNCMP_STR_SZ];
13
14long hits = 0;
15char str[STRNCMP_STR_SZ];
16
17char _license[] SEC("license") = "GPL";
18
19static __always_inline int local_strncmp(const char *s1, unsigned int sz,
20 const char *s2)
21{
22 int ret = 0;
23 unsigned int i;
24
25 for (i = 0; i < sz; i++) {
26 /* E.g. 0xff > 0x31 */
27 ret = (unsigned char)s1[i] - (unsigned char)s2[i];
28 if (ret || !s1[i])
29 break;
30 }
31
32 return ret;
33}
34
35SEC("tp/syscalls/sys_enter_getpgid")
36int strncmp_no_helper(void *ctx)
37{
38 if (local_strncmp(str, cmp_str_len + 1, target) < 0)
39 __sync_add_and_fetch(&hits, 1);
40 return 0;
41}
42
43SEC("tp/syscalls/sys_enter_getpgid")
44int strncmp_helper(void *ctx)
45{
46 if (bpf_strncmp(str, cmp_str_len + 1, target) < 0)
47 __sync_add_and_fetch(&hits, 1);
48 return 0;
49}
50
tools/testing/selftests/bpf/progs/strncmp_test.c+54−0
@@ -0,0 +1,54 @@
1// SPDX-License-Identifier: GPL-2.0
2/* Copyright (C) 2021. Huawei Technologies Co., Ltd */
3#include <stdbool.h>
4#include <linux/types.h>
5#include <linux/bpf.h>
6#include <bpf/bpf_helpers.h>
7#include <bpf/bpf_tracing.h>
8
9#define STRNCMP_STR_SZ 8
10
11const char target[STRNCMP_STR_SZ] = "EEEEEEE";
12char str[STRNCMP_STR_SZ];
13int cmp_ret = 0;
14int target_pid = 0;
15
16const char no_str_target[STRNCMP_STR_SZ] = "12345678";
17char writable_target[STRNCMP_STR_SZ];
18unsigned int no_const_str_size = STRNCMP_STR_SZ;
19
20char _license[] SEC("license") = "GPL";
21
22SEC("tp/syscalls/sys_enter_nanosleep")
23int do_strncmp(void *ctx)
24{
25 if ((bpf_get_current_pid_tgid() >> 32) != target_pid)
26 return 0;
27
28 cmp_ret = bpf_strncmp(str, STRNCMP_STR_SZ, target);
29 return 0;
30}
31
32SEC("tp/syscalls/sys_enter_nanosleep")
33int strncmp_bad_not_const_str_size(void *ctx)
34{
35 /* The value of string size is not const, so will fail */
36 cmp_ret = bpf_strncmp(str, no_const_str_size, target);
37 return 0;
38}
39
40SEC("tp/syscalls/sys_enter_nanosleep")
41int strncmp_bad_writable_target(void *ctx)
42{
43 /* Compared target is not read-only, so will fail */
44 cmp_ret = bpf_strncmp(str, STRNCMP_STR_SZ, writable_target);
45 return 0;
46}
47
48SEC("tp/syscalls/sys_enter_nanosleep")
49int strncmp_bad_not_null_term_target(void *ctx)
50{
51 /* Compared target is not null-terminated, so will fail */
52 cmp_ret = bpf_strncmp(str, STRNCMP_STR_SZ, no_str_target);
53 return 0;
54}
tools/testing/selftests/bpf/progs/test_ksyms_btf_write_check.c+29−0
@@ -0,0 +1,29 @@
1// SPDX-License-Identifier: GPL-2.0
2/* Copyright (c) 2021 Google */
3
4#include "vmlinux.h"
5
6#include <bpf/bpf_helpers.h>
7
8extern const int bpf_prog_active __ksym; /* int type global var. */
9
10SEC("raw_tp/sys_enter")
11int handler(const void *ctx)
12{
13 int *active;
14 __u32 cpu;
15
16 cpu = bpf_get_smp_processor_id();
17 active = (int *)bpf_per_cpu_ptr(&bpf_prog_active, cpu);
18 if (active) {
19 /* Kernel memory obtained from bpf_{per,this}_cpu_ptr
20 * is read-only, should _not_ pass verification.
21 */
22 /* WRITE_ONCE */
23 *(volatile int *)active = -1;
24 }
25
26 return 0;
27}
28
29char _license[] SEC("license") = "GPL";
tools/testing/selftests/bpf/test_cpp.cpp+8−1
@@ -7,9 +7,15 @@ · 6 unmodified lines
7 7
8/* do nothing, just make sure we can link successfully */8/* do nothing, just make sure we can link successfully */
9 9
10static void dump_printf(void *ctx, const char *fmt, va_list args)
11{
12}
13
10int main(int argc, char *argv[])14int main(int argc, char *argv[])
11{15{
16 struct btf_dump_opts opts = { };
12 struct test_core_extern *skel;17 struct test_core_extern *skel;
18 struct btf *btf;
13 19
14 /* libbpf.h */20 /* libbpf.h */
15 libbpf_set_print(NULL);21 libbpf_set_print(NULL);
@@ -18,7 +24,8 @@ int main(int argc, char *argv[]) · 2 unmodified lines
18 bpf_prog_get_fd_by_id(0);24 bpf_prog_get_fd_by_id(0);
19 25
20 /* btf.h */26 /* btf.h */
21 btf__new(NULL, 0);27 btf = btf__new(NULL, 0);
28 btf_dump__new(btf, dump_printf, nullptr, &opts);
22 29
23 /* BPF skeleton */30 /* BPF skeleton */
24 skel = test_core_extern__open_and_load();31 skel = test_core_extern__open_and_load();
tools/testing/selftests/bpf/test_maps.c+0−1
@@ -23,7 +23,6 @@ · 22 unmodified lines
23#include <bpf/libbpf.h>23#include <bpf/libbpf.h>
24 24
25#include "bpf_util.h"25#include "bpf_util.h"
26#include "bpf_rlimit.h"
27#include "test_maps.h"26#include "test_maps.h"
28#include "testing_helpers.h"27#include "testing_helpers.h"
29 28
tools/testing/selftests/bpf/test_progs.c+0−2
@@ -4,7 +4,6 @@ · 3 unmodified lines
4#define _GNU_SOURCE4#define _GNU_SOURCE
5#include "test_progs.h"5#include "test_progs.h"
6#include "cgroup_helpers.h"6#include "cgroup_helpers.h"
7#include "bpf_rlimit.h"
8#include <argp.h>7#include <argp.h>
9#include <pthread.h>8#include <pthread.h>
10#include <sched.h>9#include <sched.h>
@@ -1342,7 +1341,6 @@ int main(int argc, char **argv) · 1331 unmodified lines
1342 1341
1343 /* Use libbpf 1.0 API mode */1342 /* Use libbpf 1.0 API mode */
1344 libbpf_set_strict_mode(LIBBPF_STRICT_ALL);1343 libbpf_set_strict_mode(LIBBPF_STRICT_ALL);
1345
1346 libbpf_set_print(libbpf_print_fn);1344 libbpf_set_print(libbpf_print_fn);
1347 1345
1348 srand(time(NULL));1346 srand(time(NULL));
tools/testing/selftests/bpf/test_verifier.c+8−10
@@ -41,7 +41,6 @@ · 40 unmodified lines
41# define CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS 141# define CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS 1
42# endif42# endif
43#endif43#endif
44#include "bpf_rlimit.h"
45#include "bpf_rand.h"44#include "bpf_rand.h"
46#include "bpf_util.h"45#include "bpf_util.h"
47#include "test_btf.h"46#include "test_btf.h"
@@ -701,22 +700,18 @@ static int create_sk_storage_map(void) · 653 unmodified lines
701 700
702static int create_map_timer(void)701static int create_map_timer(void)
703{702{
704 struct bpf_create_map_attr attr = {703 LIBBPF_OPTS(bpf_map_create_opts, opts,
705 .name = "test_map",
706 .map_type = BPF_MAP_TYPE_ARRAY,
707 .key_size = 4,
708 .value_size = 16,
709 .max_entries = 1,
710 .btf_key_type_id = 1,704 .btf_key_type_id = 1,
711 .btf_value_type_id = 5,705 .btf_value_type_id = 5,
712 };706 );
713 int fd, btf_fd;707 int fd, btf_fd;
714 708
715 btf_fd = load_btf();709 btf_fd = load_btf();
716 if (btf_fd < 0)710 if (btf_fd < 0)
717 return -1;711 return -1;
718 attr.btf_fd = btf_fd;712
719 fd = bpf_create_map_xattr(&attr);713 opts.btf_fd = btf_fd;
714 fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, "test_map", 4, 16, 1, &opts);
720 if (fd < 0)715 if (fd < 0)
721 printf("Failed to create map with timer\n");716 printf("Failed to create map with timer\n");
722 return fd;717 return fd;
@@ -1399,6 +1394,9 @@ int main(int argc, char **argv) · 676 unmodified lines
1399 return EXIT_FAILURE;1394 return EXIT_FAILURE;
1400 }1395 }
1401 1396
1397 /* Use libbpf 1.0 API mode */
1398 libbpf_set_strict_mode(LIBBPF_STRICT_ALL);
1399
1402 bpf_semi_rand_init();1400 bpf_semi_rand_init();
1403 return do_test(unpriv, from, to);1401 return do_test(unpriv, from, to);
1404}1402}
tools/testing/selftests/bpf/verifier/btf_ctx_access.c+12−0
@@ -0,0 +1,12 @@
1{
2 "btf_ctx_access accept",
3 .insns = {
4 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 8), /* load 2nd argument value (int pointer) */
5 BPF_MOV64_IMM(BPF_REG_0, 0),
6 BPF_EXIT_INSN(),
7 },
8 .result = ACCEPT,
9 .prog_type = BPF_PROG_TYPE_TRACING,
10 .expected_attach_type = BPF_TRACE_FENTRY,
11 .kfunc = "bpf_modify_return_test",
12},
tools/testing/selftests/bpf/vmtest.sh+1−1
@@ -32,7 +32,7 @@ ROOTFS_IMAGE="root.img" · 31 unmodified lines
32OUTPUT_DIR="$HOME/.bpf_selftests"32OUTPUT_DIR="$HOME/.bpf_selftests"
33KCONFIG_URL="https://raw.githubusercontent.com/libbpf/libbpf/master/travis-ci/vmtest/configs/config-latest.${ARCH}"33KCONFIG_URL="https://raw.githubusercontent.com/libbpf/libbpf/master/travis-ci/vmtest/configs/config-latest.${ARCH}"
34KCONFIG_API_URL="https://api.github.com/repos/libbpf/libbpf/contents/travis-ci/vmtest/configs/config-latest.${ARCH}"34KCONFIG_API_URL="https://api.github.com/repos/libbpf/libbpf/contents/travis-ci/vmtest/configs/config-latest.${ARCH}"
35INDEX_URL="https://raw.githubusercontent.com/libbpf/libbpf/master/travis-ci/vmtest/configs/INDEX"35INDEX_URL="https://raw.githubusercontent.com/libbpf/ci/master/INDEX"
36NUM_COMPILE_JOBS="$(nproc)"36NUM_COMPILE_JOBS="$(nproc)"
37LOG_FILE_BASE="$(date +"bpf_selftests.%Y-%m-%d_%H-%M-%S")"37LOG_FILE_BASE="$(date +"bpf_selftests.%Y-%m-%d_%H-%M-%S")"
38LOG_FILE="${LOG_FILE_BASE}.log"38LOG_FILE="${LOG_FILE_BASE}.log"