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
5757 $(LIBBPF_BOOTSTRAP): $(wildcard $(BPF_DIR)/*.[ch] $(BPF_DIR)/Makefile) | $(LIBBPF_BOOTSTRAP_OUTPUT)
5858 $(Q)$(MAKE) -C $(BPF_DIR) OUTPUT=$(LIBBPF_BOOTSTRAP_OUTPUT) \
5959 DESTDIR=$(LIBBPF_BOOTSTRAP_DESTDIR) prefix= \
60− ARCH= CC=$(HOSTCC) LD=$(HOSTLD) $@ install_headers
60+ ARCH= CROSS_COMPILE= CC=$(HOSTCC) LD=$(HOSTLD) $@ install_headers
6161
6262 $(LIBBPF_BOOTSTRAP_INTERNAL_HDRS): $(LIBBPF_BOOTSTRAP_HDRS_DIR)/%.h: $(BPF_DIR)/%.h | $(LIBBPF_BOOTSTRAP_HDRS_DIR)
6363 $(call QUIET_INSTALL, $@)
@@ -152,6 +152,9 @@ CFLAGS += -DHAVE_LIBBFD_SUPPORT · 88 unmodified lines
152152 SRCS += $(BFD_SRCS)
153153 endif
154154
155+HOST_CFLAGS = $(subst -I$(LIBBPF_INCLUDE),-I$(LIBBPF_BOOTSTRAP_INCLUDE),\
156+ $(subst $(CLANG_CROSS_FLAGS),,$(CFLAGS)))
157+
155158 BPFTOOL_BOOTSTRAP := $(BOOTSTRAP_OUTPUT)bpftool
156159
157160 BOOTSTRAP_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
202205 CFLAGS += $(if $(BUILD_BPF_SKELS),,-DBPFTOOL_WITHOUT_SKELETONS)
203206
204207 $(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 $@
206209
207210 $(OUTPUT)disasm.o: $(srctree)/kernel/bpf/disasm.c
208211 $(QUIET_CC)$(CC) $(CFLAGS) -c -MMD $< -o $@
@@ -213,15 +216,13 @@ ifneq ($(feature-zlib), 1) · 4 unmodified lines
213216 endif
214217
215218 $(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 $@
217220
218221 $(OUTPUT)bpftool: $(OBJS) $(LIBBPF)
219222 $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) -o $@
220223
221224 $(BOOTSTRAP_OUTPUT)%.o: %.c $(LIBBPF_BOOTSTRAP_INTERNAL_HDRS) | $(BOOTSTRAP_OUTPUT)
222− $(QUIET_CC)$(HOSTCC) \
223− $(subst -I$(LIBBPF_INCLUDE),-I$(LIBBPF_BOOTSTRAP_INCLUDE),$(CFLAGS)) \
224− -c -MMD $< -o $@
225+ $(QUIET_CC)$(HOSTCC) $(HOST_CFLAGS) -c -MMD $< -o $@
225226
226227 $(OUTPUT)%.o: %.c
227228 $(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
642642 printf("\n");
643643 }
644644
645−static void
646−probe_large_insn_limit(const char *define_prefix, __u32 ifindex)
645+/*
646+ * Probe for availability of kernel commit (5.3):
647+ *
648+ * c04c0d2b968a ("bpf: increase complexity limit and maximum program size")
649+ */
650+static void probe_large_insn_limit(const char *define_prefix, __u32 ifindex)
647651 {
652+ LIBBPF_OPTS(bpf_prog_load_opts, opts,
653+ .prog_ifindex = ifindex,
654+ );
655+ struct bpf_insn insns[BPF_MAXINSNS + 1];
648656 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);
649670
650− res = bpf_probe_large_insn_limit(ifindex);
651671 print_bool_feature("have_large_insn_limit",
652672 "Large program size limit",
653673 "LARGE_INSN_LIMIT",
tools/bpf/bpftool/main.c+2−0
@@ -408,6 +408,8 @@ int main(int argc, char **argv) · 407 unmodified lines
408408 bool version_requested = false;
409409 int opt, ret;
410410
411+ setlinebuf(stdout);
412+
411413 last_do_help = do_help;
412414 pretty_output = false;
413415 json_output = false;
tools/bpf/resolve_btfids/Makefile+1−0
@@ -19,6 +19,7 @@ CC = $(HOSTCC) · 18 unmodified lines
1919 LD = $(HOSTLD)
2020 ARCH = $(HOSTARCH)
2121 RM ?= rm
22+CROSS_COMPILE =
2223
2324 OUTPUT ?= $(srctree)/tools/bpf/resolve_btfids/
2425
tools/bpf/runqslower/Makefile+2−2
@@ -12,7 +12,7 @@ BPFOBJ := $(BPFOBJ_OUTPUT)libbpf.a · 11 unmodified lines
1212 BPF_DESTDIR := $(BPFOBJ_OUTPUT)
1313 BPF_INCLUDE := $(BPF_DESTDIR)/include
1414 INCLUDES := -I$(OUTPUT) -I$(BPF_INCLUDE) -I$(abspath ../../include/uapi)
15−CFLAGS := -g -Wall
15+CFLAGS := -g -Wall $(CLANG_CROSS_FLAGS)
1616
1717 # Try to detect best kernel BTF source
1818 KERNEL_REL := $(shell uname -r)
@@ -88,4 +88,4 @@ $(BPFOBJ): $(wildcard $(LIBBPF_SRC)/*.[ch] $(LIBBPF_SRC)/Makefile) | $(BPFOBJ_OU · 69 unmodified lines
8888
8989 $(DEFAULT_BPFTOOL): $(BPFOBJ) | $(BPFTOOL_OUTPUT)
9090 $(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
49834983 * Return
49844984 * The number of loops performed, **-EINVAL** for invalid **flags**,
49854985 * **-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.
49865021 */
49875022 #define __BPF_FUNC_MAPPER(FN) \
49885023 FN(unspec), \
@@ -5167,6 +5202,10 @@ union bpf_attr { · 178 unmodified lines
51675202 FN(kallsyms_lookup_name), \
51685203 FN(find_vma), \
51695204 FN(loop), \
5205+ FN(strncmp), \
5206+ FN(get_func_arg), \
5207+ FN(get_func_ret), \
5208+ FN(get_func_arg_cnt), \
51705209 /* */
51715210
51725211 /* 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
9090 override CFLAGS += $(INCLUDES)
9191 override CFLAGS += -fvisibility=hidden
9292 override CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
93+override CFLAGS += $(CLANG_CROSS_FLAGS)
9394
9495 # flags specific for shared library
9596 SHLIB_FLAGS := -DSHARED -fPIC
@@ -162,7 +163,7 @@ $(BPF_HELPER_DEFS): $(srctree)/tools/include/uapi/linux/bpf.h · 66 unmodified lines
162163 $(OUTPUT)libbpf.so: $(OUTPUT)libbpf.so.$(LIBBPF_VERSION)
163164
164165 $(OUTPUT)libbpf.so.$(LIBBPF_VERSION): $(BPF_IN_SHARED) $(VERSION_SCRIPT)
165− $(QUIET_LINK)$(CC) $(LDFLAGS) \
166+ $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) \
166167 --shared -Wl,-soname,libbpf.so.$(LIBBPF_MAJOR_VERSION) \
167168 -Wl,--version-script=$(VERSION_SCRIPT) $< -lelf -lz -o $@
168169 @ln -sf $(@F) $(OUTPUT)libbpf.so
tools/lib/bpf/bpf.c+83−2
@@ -28,7 +28,9 @@ · 27 unmodified lines
2828 #include <asm/unistd.h>
2929 #include <errno.h>
3030 #include <linux/bpf.h>
31+#include <linux/filter.h>
3132 #include <limits.h>
33+#include <sys/resource.h>
3234 #include "bpf.h"
3335 #include "libbpf.h"
3436 #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
9496 return fd;
9597 }
9698
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+ */
107+int 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+
133+static bool memlock_bumped;
134+static rlim_t memlock_rlim = RLIM_INFINITY;
135+
136+int 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+
145+int 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+
97170 int bpf_map_create(enum bpf_map_type map_type,
98171 const char *map_name,
99172 __u32 key_size,
@@ -105,6 +178,8 @@ int bpf_map_create(enum bpf_map_type map_type, · 5 unmodified lines
105178 union bpf_attr attr;
106179 int fd;
107180
181+ bump_rlimit_memlock();
182+
108183 memset(&attr, 0, attr_sz);
109184
110185 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
112187
113188 attr.map_type = map_type;
114189 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));
116191 attr.key_size = key_size;
117192 attr.value_size = value_size;
118193 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
251326 union bpf_attr attr;
252327 char *log_buf;
253328
329+ bump_rlimit_memlock();
330+
254331 if (!OPTS_VALID(opts, bpf_prog_load_opts))
255332 return libbpf_err(-EINVAL);
256333
@@ -271,7 +348,7 @@ int bpf_prog_load_v0_6_0(enum bpf_prog_type prog_type, · 14 unmodified lines
271348 attr.kern_version = OPTS_GET(opts, kern_version, 0);
272349
273350 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));
275352 attr.license = ptr_to_u64(license);
276353
277354 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
456533 union bpf_attr attr;
457534 int fd;
458535
536+ bump_rlimit_memlock();
537+
459538 memset(&attr, 0, sizeof(attr));
460539 attr.prog_type = type;
461540 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
10561135 __u32 log_level;
10571136 int fd;
10581137
1138+ bump_rlimit_memlock();
1139+
10591140 memset(&attr, 0, attr_sz);
10601141
10611142 if (!OPTS_VALID(opts, bpf_btf_load_opts))
tools/lib/bpf/bpf.h+2−0
@@ -35,6 +35,8 @@ · 34 unmodified lines
3535 extern "C" {
3636 #endif
3737
38+int libbpf_set_memlock_rlim(size_t memlock_bytes);
39+
3840 struct bpf_map_create_opts {
3941 size_t sz; /* size of this struct for forward/backward compatibility */
4042
tools/lib/bpf/bpf_tracing.h+174−257
@@ -66,277 +66,204 @@ · 65 unmodified lines
6666
6767 #if defined(__KERNEL__) || defined(__VMLINUX_H__)
6868
69−#define PT_REGS_PARM1(x) ((x)->di)
70−#define PT_REGS_PARM2(x) ((x)->si)
71−#define PT_REGS_PARM3(x) ((x)->dx)
72−#define PT_REGS_PARM4(x) ((x)->cx)
73−#define PT_REGS_PARM5(x) ((x)->r8)
74−#define PT_REGS_RET(x) ((x)->sp)
75−#define PT_REGS_FP(x) ((x)->bp)
76−#define PT_REGS_RC(x) ((x)->ax)
77−#define PT_REGS_SP(x) ((x)->sp)
78−#define PT_REGS_IP(x) ((x)->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)
69+#define __PT_PARM1_REG di
70+#define __PT_PARM2_REG si
71+#define __PT_PARM3_REG dx
72+#define __PT_PARM4_REG cx
73+#define __PT_PARM5_REG r8
74+#define __PT_RET_REG sp
75+#define __PT_FP_REG bp
76+#define __PT_RC_REG ax
77+#define __PT_SP_REG sp
78+#define __PT_IP_REG ip
9079
9180 #else
9281
9382 #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
11883
119−#define PT_REGS_PARM1(x) ((x)->rdi)
120−#define PT_REGS_PARM2(x) ((x)->rsi)
121−#define PT_REGS_PARM3(x) ((x)->rdx)
122−#define PT_REGS_PARM4(x) ((x)->rcx)
123−#define PT_REGS_PARM5(x) ((x)->r8)
124−#define PT_REGS_RET(x) ((x)->rsp)
125−#define PT_REGS_FP(x) ((x)->rbp)
126−#define PT_REGS_RC(x) ((x)->rax)
127−#define PT_REGS_SP(x) ((x)->rsp)
128−#define PT_REGS_IP(x) ((x)->rip)
129−
130−#define PT_REGS_PARM1_CORE(x) BPF_CORE_READ((x), rdi)
131−#define PT_REGS_PARM2_CORE(x) BPF_CORE_READ((x), rsi)
132−#define PT_REGS_PARM3_CORE(x) BPF_CORE_READ((x), rdx)
133−#define PT_REGS_PARM4_CORE(x) BPF_CORE_READ((x), rcx)
134−#define PT_REGS_PARM5_CORE(x) BPF_CORE_READ((x), r8)
135−#define PT_REGS_RET_CORE(x) BPF_CORE_READ((x), rsp)
136−#define PT_REGS_FP_CORE(x) BPF_CORE_READ((x), rbp)
137−#define PT_REGS_RC_CORE(x) BPF_CORE_READ((x), rax)
138−#define PT_REGS_SP_CORE(x) BPF_CORE_READ((x), rsp)
139−#define PT_REGS_IP_CORE(x) BPF_CORE_READ((x), rip)
140−
141−#endif
142−#endif
84+#define __PT_PARM1_REG eax
85+#define __PT_PARM2_REG edx
86+#define __PT_PARM3_REG ecx
87+/* i386 kernel is built with -mregparm=3 */
88+#define __PT_PARM4_REG __unsupported__
89+#define __PT_PARM5_REG __unsupported__
90+#define __PT_RET_REG esp
91+#define __PT_FP_REG ebp
92+#define __PT_RC_REG eax
93+#define __PT_SP_REG esp
94+#define __PT_IP_REG eip
95+
96+#else /* __i386__ */
97+
98+#define __PT_PARM1_REG rdi
99+#define __PT_PARM2_REG rsi
100+#define __PT_PARM3_REG rdx
101+#define __PT_PARM4_REG rcx
102+#define __PT_PARM5_REG r8
103+#define __PT_RET_REG rsp
104+#define __PT_FP_REG rbp
105+#define __PT_RC_REG rax
106+#define __PT_SP_REG rsp
107+#define __PT_IP_REG rip
108+
109+#endif /* __i386__ */
110+
111+#endif /* __KERNEL__ || __VMLINUX_H__ */
143112
144113 #elif defined(bpf_target_s390)
145114
146115 /* s390 provides user_pt_regs instead of struct pt_regs to userspace */
147−struct pt_regs;
148−#define PT_REGS_S390 const volatile user_pt_regs
149−#define PT_REGS_PARM1(x) (((PT_REGS_S390 *)(x))->gprs[2])
150−#define PT_REGS_PARM2(x) (((PT_REGS_S390 *)(x))->gprs[3])
151−#define PT_REGS_PARM3(x) (((PT_REGS_S390 *)(x))->gprs[4])
152−#define PT_REGS_PARM4(x) (((PT_REGS_S390 *)(x))->gprs[5])
153−#define PT_REGS_PARM5(x) (((PT_REGS_S390 *)(x))->gprs[6])
154−#define PT_REGS_RET(x) (((PT_REGS_S390 *)(x))->gprs[14])
155−/* Works only with CONFIG_FRAME_POINTER */
156−#define PT_REGS_FP(x) (((PT_REGS_S390 *)(x))->gprs[11])
157−#define PT_REGS_RC(x) (((PT_REGS_S390 *)(x))->gprs[2])
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)
116+#define __PT_REGS_CAST(x) ((const user_pt_regs *)(x))
117+#define __PT_PARM1_REG gprs[2]
118+#define __PT_PARM2_REG gprs[3]
119+#define __PT_PARM3_REG gprs[4]
120+#define __PT_PARM4_REG gprs[5]
121+#define __PT_PARM5_REG gprs[6]
122+#define __PT_RET_REG grps[14]
123+#define __PT_FP_REG gprs[11] /* Works only with CONFIG_FRAME_POINTER */
124+#define __PT_RC_REG gprs[2]
125+#define __PT_SP_REG gprs[15]
126+#define __PT_IP_REG psw.addr
171127
172128 #elif defined(bpf_target_arm)
173129
174−#define PT_REGS_PARM1(x) ((x)->uregs[0])
175−#define PT_REGS_PARM2(x) ((x)->uregs[1])
176−#define PT_REGS_PARM3(x) ((x)->uregs[2])
177−#define PT_REGS_PARM4(x) ((x)->uregs[3])
178−#define PT_REGS_PARM5(x) ((x)->uregs[4])
179−#define PT_REGS_RET(x) ((x)->uregs[14])
180−#define PT_REGS_FP(x) ((x)->uregs[11]) /* Works only with CONFIG_FRAME_POINTER */
181−#define PT_REGS_RC(x) ((x)->uregs[0])
182−#define PT_REGS_SP(x) ((x)->uregs[13])
183−#define PT_REGS_IP(x) ((x)->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])
130+#define __PT_PARM1_REG uregs[0]
131+#define __PT_PARM2_REG uregs[1]
132+#define __PT_PARM3_REG uregs[2]
133+#define __PT_PARM4_REG uregs[3]
134+#define __PT_PARM5_REG uregs[4]
135+#define __PT_RET_REG uregs[14]
136+#define __PT_FP_REG uregs[11] /* Works only with CONFIG_FRAME_POINTER */
137+#define __PT_RC_REG uregs[0]
138+#define __PT_SP_REG uregs[13]
139+#define __PT_IP_REG uregs[12]
195140
196141 #elif defined(bpf_target_arm64)
197142
198143 /* arm64 provides struct user_pt_regs instead of struct pt_regs to userspace */
199−struct pt_regs;
200−#define PT_REGS_ARM64 const volatile struct user_pt_regs
201−#define PT_REGS_PARM1(x) (((PT_REGS_ARM64 *)(x))->regs[0])
202−#define PT_REGS_PARM2(x) (((PT_REGS_ARM64 *)(x))->regs[1])
203−#define PT_REGS_PARM3(x) (((PT_REGS_ARM64 *)(x))->regs[2])
204−#define PT_REGS_PARM4(x) (((PT_REGS_ARM64 *)(x))->regs[3])
205−#define PT_REGS_PARM5(x) (((PT_REGS_ARM64 *)(x))->regs[4])
206−#define PT_REGS_RET(x) (((PT_REGS_ARM64 *)(x))->regs[30])
207−/* Works only with CONFIG_FRAME_POINTER */
208−#define PT_REGS_FP(x) (((PT_REGS_ARM64 *)(x))->regs[29])
209−#define PT_REGS_RC(x) (((PT_REGS_ARM64 *)(x))->regs[0])
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)
144+#define __PT_REGS_CAST(x) ((const struct user_pt_regs *)(x))
145+#define __PT_PARM1_REG regs[0]
146+#define __PT_PARM2_REG regs[1]
147+#define __PT_PARM3_REG regs[2]
148+#define __PT_PARM4_REG regs[3]
149+#define __PT_PARM5_REG regs[4]
150+#define __PT_RET_REG regs[30]
151+#define __PT_FP_REG regs[29] /* Works only with CONFIG_FRAME_POINTER */
152+#define __PT_RC_REG regs[0]
153+#define __PT_SP_REG sp
154+#define __PT_IP_REG pc
223155
224156 #elif defined(bpf_target_mips)
225157
226−#define PT_REGS_PARM1(x) ((x)->regs[4])
227−#define PT_REGS_PARM2(x) ((x)->regs[5])
228−#define PT_REGS_PARM3(x) ((x)->regs[6])
229−#define PT_REGS_PARM4(x) ((x)->regs[7])
230−#define PT_REGS_PARM5(x) ((x)->regs[8])
231−#define PT_REGS_RET(x) ((x)->regs[31])
232−#define PT_REGS_FP(x) ((x)->regs[30]) /* Works only with CONFIG_FRAME_POINTER */
233−#define PT_REGS_RC(x) ((x)->regs[2])
234−#define PT_REGS_SP(x) ((x)->regs[29])
235−#define PT_REGS_IP(x) ((x)->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)
158+#define __PT_PARM1_REG regs[4]
159+#define __PT_PARM2_REG regs[5]
160+#define __PT_PARM3_REG regs[6]
161+#define __PT_PARM4_REG regs[7]
162+#define __PT_PARM5_REG regs[8]
163+#define __PT_RET_REG regs[31]
164+#define __PT_FP_REG regs[30] /* Works only with CONFIG_FRAME_POINTER */
165+#define __PT_RC_REG regs[2]
166+#define __PT_SP_REG regs[29]
167+#define __PT_IP_REG cp0_epc
247168
248169 #elif defined(bpf_target_powerpc)
249170
250−#define PT_REGS_PARM1(x) ((x)->gpr[3])
251−#define PT_REGS_PARM2(x) ((x)->gpr[4])
252−#define PT_REGS_PARM3(x) ((x)->gpr[5])
253−#define PT_REGS_PARM4(x) ((x)->gpr[6])
254−#define PT_REGS_PARM5(x) ((x)->gpr[7])
255−#define PT_REGS_RC(x) ((x)->gpr[3])
256−#define PT_REGS_SP(x) ((x)->sp)
257−#define PT_REGS_IP(x) ((x)->nip)
258−
259−#define PT_REGS_PARM1_CORE(x) BPF_CORE_READ((x), gpr[3])
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)
171+#define __PT_PARM1_REG gpr[3]
172+#define __PT_PARM2_REG gpr[4]
173+#define __PT_PARM3_REG gpr[5]
174+#define __PT_PARM4_REG gpr[6]
175+#define __PT_PARM5_REG gpr[7]
176+#define __PT_RET_REG regs[31]
177+#define __PT_FP_REG __unsupported__
178+#define __PT_RC_REG gpr[3]
179+#define __PT_SP_REG sp
180+#define __PT_IP_REG nip
267181
268182 #elif defined(bpf_target_sparc)
269183
270−#define PT_REGS_PARM1(x) ((x)->u_regs[UREG_I0])
271−#define PT_REGS_PARM2(x) ((x)->u_regs[UREG_I1])
272−#define PT_REGS_PARM3(x) ((x)->u_regs[UREG_I2])
273−#define PT_REGS_PARM4(x) ((x)->u_regs[UREG_I3])
274−#define PT_REGS_PARM5(x) ((x)->u_regs[UREG_I4])
275−#define PT_REGS_RET(x) ((x)->u_regs[UREG_I7])
276−#define PT_REGS_RC(x) ((x)->u_regs[UREG_I0])
277−#define PT_REGS_SP(x) ((x)->u_regs[UREG_FP])
278−
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−
184+#define __PT_PARM1_REG u_regs[UREG_I0]
185+#define __PT_PARM2_REG u_regs[UREG_I1]
186+#define __PT_PARM3_REG u_regs[UREG_I2]
187+#define __PT_PARM4_REG u_regs[UREG_I3]
188+#define __PT_PARM5_REG u_regs[UREG_I4]
189+#define __PT_RET_REG u_regs[UREG_I7]
190+#define __PT_FP_REG __unsupported__
191+#define __PT_RC_REG u_regs[UREG_I0]
192+#define __PT_SP_REG u_regs[UREG_FP]
288193 /* Should this also be a bpf_target check for the sparc case? */
289194 #if defined(__arch64__)
290−#define PT_REGS_IP(x) ((x)->tpc)
291−#define PT_REGS_IP_CORE(x) BPF_CORE_READ((x), tpc)
195+#define __PT_IP_REG tpc
292196 #else
293−#define PT_REGS_IP(x) ((x)->pc)
294−#define PT_REGS_IP_CORE(x) BPF_CORE_READ((x), pc)
197+#define __PT_IP_REG pc
295198 #endif
296199
297200 #elif defined(bpf_target_riscv)
298201
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+
299218 struct 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)
322219
220+/* allow some architecutres to override `struct pt_regs` */
221+#ifndef __PT_REGS_CAST
222+#define __PT_REGS_CAST(x) (x)
323223 #endif
324224
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+
325247 #if defined(bpf_target_powerpc)
248+
326249 #define BPF_KPROBE_READ_RET_IP(ip, ctx) ({ (ip) = (ctx)->link; })
327250 #define BPF_KRETPROBE_READ_RET_IP BPF_KPROBE_READ_RET_IP
251+
328252 #elif defined(bpf_target_sparc)
253+
329254 #define BPF_KPROBE_READ_RET_IP(ip, ctx) ({ (ip) = PT_REGS_RET(ctx); })
330255 #define BPF_KRETPROBE_READ_RET_IP BPF_KPROBE_READ_RET_IP
331−#elif defined(bpf_target_defined)
256+
257+#else
258+
332259 #define BPF_KPROBE_READ_RET_IP(ip, ctx) \
333260 ({ bpf_probe_read_kernel(&(ip), sizeof(ip), (void *)PT_REGS_RET(ctx)); })
334261 #define BPF_KRETPROBE_READ_RET_IP(ip, ctx) \
335− ({ bpf_probe_read_kernel(&(ip), sizeof(ip), \
336− (void *)(PT_REGS_FP(ctx) + sizeof(ip))); })
262+ ({ bpf_probe_read_kernel(&(ip), sizeof(ip), (void *)(PT_REGS_FP(ctx) + sizeof(ip))); })
263+
337264 #endif
338265
339−#if !defined(bpf_target_defined)
266+#else /* defined(bpf_target_defined) */
340267
341268 #define PT_REGS_PARM1(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
342269 #define PT_REGS_PARM2(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
@@ -363,7 +290,7 @@ struct pt_regs; · 20 unmodified lines
363290 #define BPF_KPROBE_READ_RET_IP(ip, ctx) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
364291 #define BPF_KRETPROBE_READ_RET_IP(ip, ctx) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
365292
366−#endif /* !defined(bpf_target_defined) */
293+#endif /* defined(bpf_target_defined) */
367294
368295 #ifndef ___bpf_concat
369296 #define ___bpf_concat(a, b) a ## b
@@ -375,25 +302,23 @@ struct pt_regs; · 5 unmodified lines
375302 #define ___bpf_nth(_, _1, _2, _3, _4, _5, _6, _7, _8, _9, _a, _b, _c, N, ...) N
376303 #endif
377304 #ifndef ___bpf_narg
378−#define ___bpf_narg(...) \
379− ___bpf_nth(_, ##__VA_ARGS__, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
305+#define ___bpf_narg(...) ___bpf_nth(_, ##__VA_ARGS__, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
380306 #endif
381307
382−#define ___bpf_ctx_cast0() ctx
383−#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]
385−#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]
387−#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]
389−#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]
391−#define ___bpf_ctx_cast9(x, args...) ___bpf_ctx_cast8(args), (void *)ctx[8]
308+#define ___bpf_ctx_cast0() ctx
309+#define ___bpf_ctx_cast1(x) ___bpf_ctx_cast0(), (void *)ctx[0]
310+#define ___bpf_ctx_cast2(x, args...) ___bpf_ctx_cast1(args), (void *)ctx[1]
311+#define ___bpf_ctx_cast3(x, args...) ___bpf_ctx_cast2(args), (void *)ctx[2]
312+#define ___bpf_ctx_cast4(x, args...) ___bpf_ctx_cast3(args), (void *)ctx[3]
313+#define ___bpf_ctx_cast5(x, args...) ___bpf_ctx_cast4(args), (void *)ctx[4]
314+#define ___bpf_ctx_cast6(x, args...) ___bpf_ctx_cast5(args), (void *)ctx[5]
315+#define ___bpf_ctx_cast7(x, args...) ___bpf_ctx_cast6(args), (void *)ctx[6]
316+#define ___bpf_ctx_cast8(x, args...) ___bpf_ctx_cast7(args), (void *)ctx[7]
317+#define ___bpf_ctx_cast9(x, args...) ___bpf_ctx_cast8(args), (void *)ctx[8]
392318 #define ___bpf_ctx_cast10(x, args...) ___bpf_ctx_cast9(args), (void *)ctx[9]
393319 #define ___bpf_ctx_cast11(x, args...) ___bpf_ctx_cast10(args), (void *)ctx[10]
394320 #define ___bpf_ctx_cast12(x, args...) ___bpf_ctx_cast11(args), (void *)ctx[11]
395−#define ___bpf_ctx_cast(args...) \
396− ___bpf_apply(___bpf_ctx_cast, ___bpf_narg(args))(args)
321+#define ___bpf_ctx_cast(args...) ___bpf_apply(___bpf_ctx_cast, ___bpf_narg(args))(args)
397322
398323 /*
399324 * 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
426351
427352 struct pt_regs;
428353
429−#define ___bpf_kprobe_args0() ctx
430−#define ___bpf_kprobe_args1(x) \
431− ___bpf_kprobe_args0(), (void *)PT_REGS_PARM1(ctx)
432−#define ___bpf_kprobe_args2(x, args...) \
433− ___bpf_kprobe_args1(args), (void *)PT_REGS_PARM2(ctx)
434−#define ___bpf_kprobe_args3(x, args...) \
435− ___bpf_kprobe_args2(args), (void *)PT_REGS_PARM3(ctx)
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)
354+#define ___bpf_kprobe_args0() ctx
355+#define ___bpf_kprobe_args1(x) ___bpf_kprobe_args0(), (void *)PT_REGS_PARM1(ctx)
356+#define ___bpf_kprobe_args2(x, args...) ___bpf_kprobe_args1(args), (void *)PT_REGS_PARM2(ctx)
357+#define ___bpf_kprobe_args3(x, args...) ___bpf_kprobe_args2(args), (void *)PT_REGS_PARM3(ctx)
358+#define ___bpf_kprobe_args4(x, args...) ___bpf_kprobe_args3(args), (void *)PT_REGS_PARM4(ctx)
359+#define ___bpf_kprobe_args5(x, args...) ___bpf_kprobe_args4(args), (void *)PT_REGS_PARM5(ctx)
360+#define ___bpf_kprobe_args(args...) ___bpf_apply(___bpf_kprobe_args, ___bpf_narg(args))(args)
442361
443362 /*
444363 * 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
464383 static __attribute__((always_inline)) typeof(name(0)) \
465384 ____##name(struct pt_regs *ctx, ##args)
466385
467−#define ___bpf_kretprobe_args0() ctx
468−#define ___bpf_kretprobe_args1(x) \
469− ___bpf_kretprobe_args0(), (void *)PT_REGS_RC(ctx)
470−#define ___bpf_kretprobe_args(args...) \
471− ___bpf_apply(___bpf_kretprobe_args, ___bpf_narg(args))(args)
386+#define ___bpf_kretprobe_args0() ctx
387+#define ___bpf_kretprobe_args1(x) ___bpf_kretprobe_args0(), (void *)PT_REGS_RC(ctx)
388+#define ___bpf_kretprobe_args(args...) ___bpf_apply(___bpf_kretprobe_args, ___bpf_narg(args))(args)
472389
473390 /*
474391 * 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
313313 *
314314 * The rest works just like in case of ___libbpf_override() usage with symbol
315315 * 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.
316320 */
321+#ifndef __cplusplus
317322 #define btf_dump__new(a1, a2, a3, a4) __builtin_choose_expr( \
318323 __builtin_types_compatible_p(typeof(a4), btf_dump_printf_fn_t) || \
319324 __builtin_types_compatible_p(typeof(a4), void(void *, const char *, va_list)), \
320325 btf_dump__new_deprecated((void *)a1, (void *)a2, (void *)a3, (void *)a4), \
321326 btf_dump__new((void *)a1, (void *)a2, (void *)a3, (void *)a4))
327+#endif
322328
323329 LIBBPF_API void btf_dump__free(struct btf_dump *d);
324330
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
23212321 if (!opts->indent_str)
23222322 d->typed_dump->indent_str[0] = '\t';
23232323 else
2324− strncat(d->typed_dump->indent_str, opts->indent_str,
2325− sizeof(d->typed_dump->indent_str) - 1);
2324+ libbpf_strlcpy(d->typed_dump->indent_str, opts->indent_str,
2325+ sizeof(d->typed_dump->indent_str));
23262326
23272327 d->typed_dump->compact = OPTS_GET(opts, compact, false);
23282328 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
371371 {
372372 int i;
373373
374− if (nr_progs != gen->nr_progs || nr_maps != gen->nr_maps) {
375− pr_warn("progs/maps mismatch\n");
374+ if (nr_progs < gen->nr_progs || nr_maps != gen->nr_maps) {
375+ pr_warn("nr_progs %d/%d nr_maps %d/%d mismatch\n",
376+ nr_progs, gen->nr_progs, nr_maps, gen->nr_maps);
376377 gen->error = -EFAULT;
377378 return gen->error;
378379 }
@@ -462,8 +463,7 @@ void bpf_gen__map_create(struct bpf_gen *gen, · 83 unmodified lines
462463 attr.map_flags = map_attr->map_flags;
463464 attr.map_extra = map_attr->map_extra;
464465 if (map_name)
465− memcpy(attr.map_name, map_name,
466− min((unsigned)strlen(map_name), BPF_OBJ_NAME_LEN - 1));
466+ libbpf_strlcpy(attr.map_name, map_name, sizeof(attr.map_name));
467467 attr.numa_node = map_attr->numa_node;
468468 attr.map_ifindex = map_attr->map_ifindex;
469469 attr.max_entries = max_entries;
@@ -969,8 +969,7 @@ void bpf_gen__prog_load(struct bpf_gen *gen, · 499 unmodified lines
969969 core_relos = add_data(gen, gen->core_relos,
970970 attr.core_relo_cnt * attr.core_relo_rec_size);
971971
972− memcpy(attr.prog_name, prog_name,
973− min((unsigned)strlen(prog_name), BPF_OBJ_NAME_LEN - 1));
972+ libbpf_strlcpy(attr.prog_name, prog_name, sizeof(attr.prog_name));
974973 prog_load_attr = add_data(gen, &attr, attr_size);
975974
976975 /* 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
187187 #undef __S
188188 }
189189
190−enum 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−
224−static bool kernel_supports(const struct bpf_object *obj, enum kern_feature_id feat_id);
225−
226190 enum reloc_type {
227191 RELO_LD64,
228192 RELO_CALL,
@@ -831,11 +795,36 @@ bpf_object__add_programs(struct bpf_object *obj, Elf_Data *sec_data, · 602 unmodified lines
831795 return 0;
832796 }
833797
834−static __u32 get_kernel_version(void)
798+__u32 get_kernel_version(void)
835799 {
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";
836811 __u32 major, minor, patch;
837812 struct utsname info;
838813
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+
839828 uname(&info);
840829 if (sscanf(info.release, "%u.%u.%u", &major, &minor, &patch) != 3)
841830 return 0;
@@ -1201,12 +1190,10 @@ static struct bpf_object *bpf_object__new(const char *path, · 359 unmodified lines
12011190
12021191 strcpy(obj->path, path);
12031192 if (obj_name) {
1204− strncpy(obj->name, obj_name, sizeof(obj->name) - 1);
1205− obj->name[sizeof(obj->name) - 1] = 0;
1193+ libbpf_strlcpy(obj->name, obj_name, sizeof(obj->name));
12061194 } else {
12071195 /* Using basename() GNU version which doesn't modify arg. */
1208− strncpy(obj->name, basename((void *)path),
1209− sizeof(obj->name) - 1);
1196+ libbpf_strlcpy(obj->name, basename((void *)path), sizeof(obj->name));
12101197 end = strchr(obj->name, '.');
12111198 if (end)
12121199 *end = 0;
@@ -1358,7 +1345,10 @@ static int bpf_object__check_endianness(struct bpf_object *obj) · 145 unmodified lines
13581345 static int
13591346 bpf_object__init_license(struct bpf_object *obj, void *data, size_t size)
13601347 {
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)));
13621352 pr_debug("license of %s is %s\n", obj->path, obj->license);
13631353 return 0;
13641354 }
@@ -4354,6 +4344,10 @@ bpf_object__probe_loading(struct bpf_object *obj) · 2989 unmodified lines
43544344 if (obj->gen_loader)
43554345 return 0;
43564346
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+
43574351 /* make sure basic loading works */
43584352 ret = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, NULL, "GPL", insns, insn_cnt, NULL);
43594353 if (ret < 0)
@@ -4720,14 +4714,17 @@ static struct kern_feature_desc { · 360 unmodified lines
47204714 [FEAT_BTF_TYPE_TAG] = {
47214715 "BTF_KIND_TYPE_TAG support", probe_kern_btf_type_tag,
47224716 },
4717+ [FEAT_MEMCG_ACCOUNT] = {
4718+ "memcg-based memory accounting", probe_memcg_account,
4719+ },
47234720 };
47244721
4725−static bool kernel_supports(const struct bpf_object *obj, enum kern_feature_id feat_id)
4722+bool kernel_supports(const struct bpf_object *obj, enum kern_feature_id feat_id)
47264723 {
47274724 struct kern_feature_desc *feat = &feature_probes[feat_id];
47284725 int ret;
47294726
4730− if (obj->gen_loader)
4727+ if (obj && obj->gen_loader)
47314728 /* To generate loader program assume the latest kernel
47324729 * to avoid doing extra prog_load, map_create syscalls.
47334730 */
tools/lib/bpf/libbpf.h+73−4
@@ -227,6 +227,7 @@ struct btf; · 226 unmodified lines
227227 LIBBPF_API struct btf *bpf_object__btf(const struct bpf_object *obj);
228228 LIBBPF_API int bpf_object__btf_fd(const struct bpf_object *obj);
229229
230+LIBBPF_DEPRECATED_SINCE(0, 7, "use bpf_object__find_program_by_name() instead")
230231 LIBBPF_API struct bpf_program *
231232 bpf_object__find_program_by_title(const struct bpf_object *obj,
232233 const char *title);
@@ -339,7 +340,31 @@ LIBBPF_DEPRECATED_SINCE(0, 7, "multi-instance bpf_program support is deprecated" · 106 unmodified lines
339340 LIBBPF_API int bpf_program__unpin_instance(struct bpf_program *prog,
340341 const char *path,
341342 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+ */
342354 LIBBPF_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+ */
343368 LIBBPF_API int bpf_program__unpin(struct bpf_program *prog, const char *path);
344369 LIBBPF_API void bpf_program__unload(struct bpf_program *prog);
345370
@@ -1027,13 +1052,57 @@ bpf_prog_linfo__lfind(const struct bpf_prog_linfo *prog_linfo, · 681 unmodified lines
10271052 * user, causing subsequent probes to fail. In this case, the caller may want
10281053 * to adjust that limit with setrlimit().
10291054 */
1030−LIBBPF_API bool bpf_probe_prog_type(enum bpf_prog_type prog_type,
1031− __u32 ifindex);
1055+LIBBPF_DEPRECATED_SINCE(0, 8, "use libbpf_probe_bpf_prog_type() instead")
1056+LIBBPF_API bool bpf_probe_prog_type(enum bpf_prog_type prog_type, __u32 ifindex);
1057+LIBBPF_DEPRECATED_SINCE(0, 8, "use libbpf_probe_bpf_map_type() instead")
10321058 LIBBPF_API bool bpf_probe_map_type(enum bpf_map_type map_type, __u32 ifindex);
1033−LIBBPF_API bool bpf_probe_helper(enum bpf_func_id id,
1034− enum bpf_prog_type prog_type, __u32 ifindex);
1059+LIBBPF_DEPRECATED_SINCE(0, 8, "use libbpf_probe_bpf_helper() instead")
1060+LIBBPF_API bool bpf_probe_helper(enum bpf_func_id id, enum bpf_prog_type prog_type, __u32 ifindex);
1061+LIBBPF_DEPRECATED_SINCE(0, 8, "implement your own or use bpftool for feature detection")
10351062 LIBBPF_API bool bpf_probe_large_insn_limit(__u32 ifindex);
10361063
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+ */
1076+LIBBPF_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+ */
1089+LIBBPF_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+ */
1103+LIBBPF_API int libbpf_probe_bpf_helper(enum bpf_prog_type prog_type,
1104+ enum bpf_func_id helper_id, const void *opts);
1105+
10371106 /*
10381107 * Get bpf_prog_info in continuous memory
10391108 *
tools/lib/bpf/libbpf.map+4−0
@@ -427,4 +427,8 @@ LIBBPF_0.7.0 { · 426 unmodified lines
427427 bpf_program__log_level;
428428 bpf_program__set_log_buf;
429429 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;
430434 };
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
169169 return realloc(ptr, total);
170170 }
171171
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+ */
178+static 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+
172193 struct btf;
173194 struct btf_type;
174195
@@ -272,6 +293,45 @@ static inline bool libbpf_validate_opts(const char *opts, · 97 unmodified lines
272293 (opts)->sz - __off); \
273294 })
274295
296+enum 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+
332+int probe_memcg_account(void);
333+bool kernel_supports(const struct bpf_object *obj, enum kern_feature_id feat_id);
334+int bump_rlimit_memlock(void);
275335
276336 int parse_cpu_mask_str(const char *s, bool **mask, int *mask_sz);
277337 int 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
4545 * (positive) error code.
4646 */
4747 LIBBPF_STRICT_DIRECT_ERRS = 0x02,
48−
4948 /*
5049 * Enforce strict BPF program section (SEC()) names.
5150 * E.g., while prefiously SEC("xdp_whatever") or SEC("perf_event_blah") were
@@ -63,6 +62,17 @@ enum libbpf_strict_mode { · 11 unmodified lines
6362 * Clients can maintain it on their own if it is valuable for them.
6463 */
6564 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,
6676
6777 __LIBBPF_STRICT_LAST,
6878 };
tools/lib/bpf/libbpf_probes.c+185−66
@@ -48,28 +48,20 @@ static int get_vendor_id(int ifindex) · 47 unmodified lines
4848 return strtol(buf, NULL, 0);
4949 }
5050
51−static int get_kernel_version(void)
51+static 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)
5255 {
53− int version, subversion, patchlevel;
54− struct utsname utsn;
55−
56− /* Return 0 on failure, and attempt to probe with empty kversion */
57− if (uname(&utsn))
58− return 0;
59−
60− if (sscanf(utsn.release, "%d.%d.%d",
61− &version, &subversion, &patchlevel) != 3)
62− return 0;
63−
64− return (version << 16) + (subversion << 8) + patchlevel;
65−}
66−
67−static void
68−probe_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;
56+ LIBBPF_OPTS(bpf_prog_load_opts, opts,
57+ .log_buf = log_buf,
58+ .log_size = log_buf_sz,
59+ .log_level = log_buf ? 1 : 0,
60+ .prog_ifindex = ifindex,
61+ );
62+ int fd, err, exp_err = 0;
63+ const char *exp_msg = NULL;
64+ char buf[4096];
7365
7466 switch (prog_type) {
7567 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
8476 case BPF_PROG_TYPE_KPROBE:
8577 opts.kern_version = get_kernel_version();
8678 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;
87111 case BPF_PROG_TYPE_UNSPEC:
88112 case BPF_PROG_TYPE_SOCKET_FILTER:
89113 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
103127 case BPF_PROG_TYPE_RAW_TRACEPOINT:
104128 case BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE:
105129 case BPF_PROG_TYPE_LWT_SEG6LOCAL:
106− case BPF_PROG_TYPE_LIRC_MODE2:
107130 case BPF_PROG_TYPE_SK_REUSEPORT:
108131 case BPF_PROG_TYPE_FLOW_DISSECTOR:
109132 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:
115133 break;
134+ default:
135+ return -EOPNOTSUPP;
116136 }
117137
118− opts.prog_ifindex = ifindex;
119− opts.log_buf = buf;
120− opts.log_size = buf_len;
121−
122− fd = bpf_prog_load(prog_type, NULL, "GPL", insns, insns_cnt, NULL);
138+ fd = bpf_prog_load(prog_type, NULL, "GPL", insns, insns_cnt, &opts);
139+ err = -errno;
123140 if (fd >= 0)
124141 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+
152+int 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);
125166 }
126167
127168 bool 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
131172 BPF_EXIT_INSN()
132173 };
133174
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+
134179 if (ifindex && prog_type == BPF_PROG_TYPE_SCHED_CLS)
135180 /* nfp returns -EINVAL on exit(0) with TC offload */
136181 insns[0].imm = 2;
137182
138183 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);
140185
141186 return errno != EINVAL && errno != EOPNOTSUPP;
142187 }
@@ -197,16 +242,18 @@ static int load_local_storage_btf(void) · 54 unmodified lines
197242 strs, sizeof(strs));
198243 }
199244
200−bool bpf_probe_map_type(enum bpf_map_type map_type, __u32 ifindex)
245+static int probe_map_create(enum bpf_map_type map_type, __u32 ifindex)
201246 {
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;
203249 __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;
205253
206254 key_size = sizeof(__u32);
207255 value_size = sizeof(__u32);
208256 max_entries = 1;
209− map_flags = 0;
210257
211258 switch (map_type) {
212259 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
215262 case BPF_MAP_TYPE_LPM_TRIE:
216263 key_size = sizeof(__u64);
217264 value_size = sizeof(__u64);
218− map_flags = BPF_F_NO_PREALLOC;
265+ opts.map_flags = BPF_F_NO_PREALLOC;
219266 break;
220267 case BPF_MAP_TYPE_CGROUP_STORAGE:
221268 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
234281 btf_value_type_id = 3;
235282 value_size = 8;
236283 max_entries = 0;
237− map_flags = BPF_F_NO_PREALLOC;
284+ opts.map_flags = BPF_F_NO_PREALLOC;
238285 btf_fd = load_local_storage_btf();
239286 if (btf_fd < 0)
240− return false;
287+ return btf_fd;
241288 break;
242289 case BPF_MAP_TYPE_RINGBUF:
243290 key_size = 0;
244291 value_size = 0;
245292 max_entries = 4096;
246293 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;
248303 case BPF_MAP_TYPE_HASH:
249304 case BPF_MAP_TYPE_ARRAY:
250305 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
263318 case BPF_MAP_TYPE_XSKMAP:
264319 case BPF_MAP_TYPE_SOCKHASH:
265320 case BPF_MAP_TYPE_REUSEPORT_SOCKARRAY:
266− case BPF_MAP_TYPE_STRUCT_OPS:
267− default:
268321 break;
322+ case BPF_MAP_TYPE_UNSPEC:
323+ default:
324+ return -EOPNOTSUPP;
269325 }
270326
271327 if (map_type == BPF_MAP_TYPE_ARRAY_OF_MAPS ||
272328 map_type == BPF_MAP_TYPE_HASH_OF_MAPS) {
273− LIBBPF_OPTS(bpf_map_create_opts, opts);
274−
275329 /* TODO: probe for device, once libbpf has a function to create
276330 * map-in-map for offload
277331 */
278332 if (ifindex)
279− return false;
333+ goto cleanup;
280334
281335 fd_inner = bpf_map_create(BPF_MAP_TYPE_HASH, NULL,
282336 sizeof(__u32), sizeof(__u32), 1, NULL);
283337 if (fd_inner < 0)
284− return false;
338+ goto cleanup;
285339
286340 opts.inner_map_fd = fd_inner;
287− fd = bpf_map_create(map_type, NULL, sizeof(__u32), sizeof(__u32), 1, &opts);
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− }
341+ }
300342
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;
302347 }
348+
349+ fd = bpf_map_create(map_type, NULL, key_size, value_size, max_entries, &opts);
350+ err = -errno;
351+
352+cleanup:
303353 if (fd >= 0)
304354 close(fd);
355+ if (fd_inner >= 0)
356+ close(fd_inner);
305357 if (btf_fd >= 0)
306358 close(btf_fd);
307359
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+
366+int 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+
377+bool bpf_probe_map_type(enum bpf_map_type map_type, __u32 ifindex)
378+{
379+ return probe_map_create(map_type, ifindex) == 1;
380+}
381+
382+int 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 */
309429 }
310430
311431 bool 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
318438 char buf[4096] = {};
319439 bool res;
320440
321− probe_load(prog_type, insns, ARRAY_SIZE(insns), buf, sizeof(buf),
322− ifindex);
441+ probe_prog_load(prog_type, insns, ARRAY_SIZE(insns), buf, sizeof(buf), ifindex);
323442 res = !grep(buf, "invalid func ") && !grep(buf, "unknown func ");
324443
325444 if (ifindex) {
@@ -351,8 +470,8 @@ bool bpf_probe_large_insn_limit(__u32 ifindex) · 25 unmodified lines
351470 insns[BPF_MAXINSNS] = BPF_EXIT_INSN();
352471
353472 errno = 0;
354− probe_load(BPF_PROG_TYPE_SCHED_CLS, insns, ARRAY_SIZE(insns), NULL, 0,
355− ifindex);
473+ probe_prog_load(BPF_PROG_TYPE_SCHED_CLS, insns, ARRAY_SIZE(insns), NULL, 0,
474+ ifindex);
356475
357476 return errno != E2BIG && errno != EINVAL;
358477 }
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
709709
710710 static int bpf_core_calc_type_relo(const struct bpf_core_relo *relo,
711711 const struct bpf_core_spec *spec,
712− __u32 *val)
712+ __u32 *val, bool *validate)
713713 {
714714 __s64 sz;
715715
716+ /* by default, always check expected value in bpf_insn */
717+ if (validate)
718+ *validate = true;
719+
716720 /* type-based relos return zero when target type is not found */
717721 if (!spec) {
718722 *val = 0;
@@ -722,6 +726,11 @@ static int bpf_core_calc_type_relo(const struct bpf_core_relo *relo, · 3 unmodified lines
722726 switch (relo->kind) {
723727 case BPF_CORE_TYPE_ID_TARGET:
724728 *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;
725734 break;
726735 case BPF_CORE_TYPE_EXISTS:
727736 *val = 1;
@@ -861,8 +870,8 @@ static int bpf_core_calc_relo(const char *prog_name, · 133 unmodified lines
861870 res->fail_memsz_adjust = true;
862871 }
863872 } else if (core_relo_is_type_based(relo->kind)) {
864− err = bpf_core_calc_type_relo(relo, local_spec, &res->orig_val);
865− err = err ?: bpf_core_calc_type_relo(relo, targ_spec, &res->new_val);
873+ err = bpf_core_calc_type_relo(relo, local_spec, &res->orig_val, &res->validate);
874+ err = err ?: bpf_core_calc_type_relo(relo, targ_spec, &res->new_val, NULL);
866875 } else if (core_relo_is_enumval_based(relo->kind)) {
867876 err = bpf_core_calc_enumval_relo(relo, local_spec, &res->orig_val);
868877 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
12131222
12141223 /* TYPE_ID_LOCAL relo is special and doesn't need candidate search */
12151224 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;
12171228 targ_res.poison = false;
12181229 targ_res.orig_val = local_spec->root_type_id;
12191230 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
12271238 return -EOPNOTSUPP;
12281239 }
12291240
1230−
12311241 for (i = 0, j = 0; i < cands->len; i++) {
12321242 err = bpf_core_spec_match(local_spec, cands->cands[i].btf,
12331243 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
548548 return -errno;
549549
550550 ifr.ifr_data = (void *)&channels;
551− memcpy(ifr.ifr_name, ctx->ifname, IFNAMSIZ - 1);
552− ifr.ifr_name[IFNAMSIZ - 1] = '\0';
551+ libbpf_strlcpy(ifr.ifr_name, ctx->ifname, IFNAMSIZ);
553552 err = ioctl(fd, SIOCETHTOOL, &ifr);
554553 if (err && errno != EOPNOTSUPP) {
555554 ret = -errno;
@@ -768,8 +767,7 @@ static int xsk_create_xsk_struct(int ifindex, struct xsk_socket *xsk) · 212 unmodified lines
768767 }
769768
770769 ctx->ifindex = ifindex;
771− memcpy(ctx->ifname, ifname, IFNAMSIZ -1);
772− ctx->ifname[IFNAMSIZ - 1] = 0;
770+ libbpf_strlcpy(ctx->ifname, ifname, IFNAMSIZ);
773771
774772 xsk->ctx = ctx;
775773 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
951949 ctx->refcount = 1;
952950 ctx->umem = umem;
953951 ctx->queue_id = queue_id;
954− memcpy(ctx->ifname, ifname, IFNAMSIZ - 1);
955− ctx->ifname[IFNAMSIZ - 1] = '\0';
952+ libbpf_strlcpy(ctx->ifname, ifname, IFNAMSIZ);
956953
957954 ctx->fill = fill;
958955 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
32573257
32583258 static struct bpf_program *trace__find_bpf_program_by_title(struct trace *trace, const char *name)
32593259 {
3260+ struct bpf_program *pos, *prog = NULL;
3261+ const char *sec_name;
3262+
32603263 if (trace->bpf_obj == NULL)
32613264 return NULL;
32623265
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;
32643275 }
32653276
32663277 static 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
8787
8888 ifeq ($(CC_NO_CLANG), 1)
8989 EXTRA_WARNINGS += -Wstrict-aliasing=3
90−endif
90+
91+else ifneq ($(CROSS_COMPILE),)
92+CLANG_CROSS_FLAGS := --target=$(notdir $(CROSS_COMPILE:%-=%))
93+GCC_TOOLCHAIN_DIR := $(dir $(shell which $(CROSS_COMPILE)gcc))
94+ifneq ($(GCC_TOOLCHAIN_DIR),)
95+CLANG_CROSS_FLAGS += --prefix=$(GCC_TOOLCHAIN_DIR)$(notdir $(CROSS_COMPILE))
96+CLANG_CROSS_FLAGS += --sysroot=$(shell $(CROSS_COMPILE)gcc -print-sysroot)
97+CLANG_CROSS_FLAGS += --gcc-toolchain=$(realpath $(GCC_TOOLCHAIN_DIR)/..)
98+endif # GCC_TOOLCHAIN_DIR
99+CFLAGS += $(CLANG_CROSS_FLAGS)
100+AFLAGS += $(CLANG_CROSS_FLAGS)
101+endif # CROSS_COMPILE
91102
92103 # Hack to avoid type-punned warnings on old systems such as RHEL5:
93104 # 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
170170
171171 $(OUTPUT)/urandom_read: urandom_read.c
172172 $(call msg,BINARY,,$@)
173− $(Q)$(CC) $(LDFLAGS) $< $(LDLIBS) -Wl,--build-id=sha1 -o $@
173+ $(Q)$(CC) $(CFLAGS) $(LDFLAGS) $< $(LDLIBS) -Wl,--build-id=sha1 -o $@
174174
175175 $(OUTPUT)/bpf_testmod.ko: $(VMLINUX_BTF) $(wildcard bpf_testmod/Makefile bpf_testmod/*.[ch])
176176 $(call msg,MOD,,$@)
@@ -217,7 +217,7 @@ BPFTOOL ?= $(DEFAULT_BPFTOOL) · 40 unmodified lines
217217 $(DEFAULT_BPFTOOL): $(wildcard $(BPFTOOLDIR)/*.[ch] $(BPFTOOLDIR)/Makefile) \
218218 $(HOST_BPFOBJ) | $(HOST_BUILD_DIR)/bpftool
219219 $(Q)$(MAKE) $(submake_extras) -C $(BPFTOOLDIR) \
220− CC=$(HOSTCC) LD=$(HOSTLD) \
220+ ARCH= CROSS_COMPILE= CC=$(HOSTCC) LD=$(HOSTLD) \
221221 EXTRA_CFLAGS='-g -O0' \
222222 OUTPUT=$(HOST_BUILD_DIR)/bpftool/ \
223223 LIBBPF_OUTPUT=$(HOST_BUILD_DIR)/libbpf/ \
@@ -248,7 +248,7 @@ $(HOST_BPFOBJ): $(wildcard $(BPFDIR)/*.[ch] $(BPFDIR)/Makefile) \ · 24 unmodified lines
248248 $(APIDIR)/linux/bpf.h \
249249 | $(HOST_BUILD_DIR)/libbpf
250250 $(Q)$(MAKE) $(submake_extras) -C $(BPFDIR) \
251− EXTRA_CFLAGS='-g -O0' \
251+ EXTRA_CFLAGS='-g -O0' ARCH= CROSS_COMPILE= \
252252 OUTPUT=$(HOST_BUILD_DIR)/libbpf/ CC=$(HOSTCC) LD=$(HOSTLD) \
253253 DESTDIR=$(HOST_SCRATCH_DIR)/ prefix= all install_headers
254254 endif
@@ -537,6 +537,7 @@ $(OUTPUT)/bench_ringbufs.o: $(OUTPUT)/ringbuf_bench.skel.h \ · 282 unmodified lines
537537 $(OUTPUT)/perfbuf_bench.skel.h
538538 $(OUTPUT)/bench_bloom_filter_map.o: $(OUTPUT)/bloom_filter_bench.skel.h
539539 $(OUTPUT)/bench_bpf_loop.o: $(OUTPUT)/bpf_loop_bench.skel.h
540+$(OUTPUT)/bench_strncmp.o: $(OUTPUT)/strncmp_bench.skel.h
540541 $(OUTPUT)/bench.o: bench.h testing_helpers.h $(BPFOBJ)
541542 $(OUTPUT)/bench: LDLIBS += -lm
542543 $(OUTPUT)/bench: $(OUTPUT)/bench.o \
@@ -547,9 +548,10 @@ $(OUTPUT)/bench: $(OUTPUT)/bench.o \ · 4 unmodified lines
547548 $(OUTPUT)/bench_trigger.o \
548549 $(OUTPUT)/bench_ringbufs.o \
549550 $(OUTPUT)/bench_bloom_filter_map.o \
550− $(OUTPUT)/bench_bpf_loop.o
551+ $(OUTPUT)/bench_bpf_loop.o \
552+ $(OUTPUT)/bench_strncmp.o
551553 $(call msg,BINARY,,$@)
552− $(Q)$(CC) $(LDFLAGS) $(filter %.a %.o,$^) $(LDLIBS) -o $@
554+ $(Q)$(CC) $(CFLAGS) $(LDFLAGS) $(filter %.a %.o,$^) $(LDLIBS) -o $@
553555
554556 EXTRA_CLEAN := $(TEST_CUSTOM_PROGS) $(SCRATCH_DIR) $(HOST_SCRATCH_DIR) \
555557 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
2929 return vfprintf(stderr, format, args);
3030 }
3131
32−static int bump_memlock_rlimit(void)
32+void setup_libbpf(void)
3333 {
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−
42−void setup_libbpf()
43−{
44− int err;
45−
4634 libbpf_set_strict_mode(LIBBPF_STRICT_ALL);
4735 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);
5236 }
5337
5438 void 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
205189 extern struct argp bench_ringbufs_argp;
206190 extern struct argp bench_bloom_map_argp;
207191 extern struct argp bench_bpf_loop_argp;
192+extern struct argp bench_strncmp_argp;
208193
209194 static const struct argp_child bench_parsers[] = {
210195 { &bench_ringbufs_argp, 0, "Ring buffers benchmark", 0 },
211196 { &bench_bloom_map_argp, 0, "Bloom filter map benchmark", 0 },
212197 { &bench_bpf_loop_argp, 0, "bpf_loop helper benchmark", 0 },
198+ { &bench_strncmp_argp, 0, "bpf_strncmp helper benchmark", 0 },
213199 {},
214200 };
215201
@@ -409,6 +395,8 @@ extern const struct bench bench_bloom_false_positive; · 193 unmodified lines
409395 extern const struct bench bench_hashmap_without_bloom;
410396 extern const struct bench bench_hashmap_with_bloom;
411397 extern const struct bench bench_bpf_loop;
398+extern const struct bench bench_strncmp_no_helper;
399+extern const struct bench bench_strncmp_helper;
412400
413401 static const struct bench *benchs[] = {
414402 &bench_count_global,
@@ -441,6 +429,8 @@ static const struct bench *benchs[] = { · 26 unmodified lines
441429 &bench_hashmap_without_bloom,
442430 &bench_hashmap_with_bloom,
443431 &bench_bpf_loop,
432+ &bench_strncmp_no_helper,
433+ &bench_strncmp_helper,
444434 };
445435
446436 static void setup_benchmark()
tools/testing/selftests/bpf/bench.h+5−4
@@ -38,8 +38,8 @@ struct bench_res { · 37 unmodified lines
3838
3939 struct bench {
4040 const char *name;
41− void (*validate)();
42− void (*setup)();
41+ void (*validate)(void);
42+ void (*setup)(void);
4343 void *(*producer_thread)(void *ctx);
4444 void *(*consumer_thread)(void *ctx);
4545 void (*measure)(struct bench_res* res);
@@ -54,7 +54,7 @@ struct counter { · 8 unmodified lines
5454 extern struct env env;
5555 extern const struct bench *bench;
5656
57−void setup_libbpf();
57+void setup_libbpf(void);
5858 void hits_drops_report_progress(int iter, struct bench_res *res, long delta_ns);
5959 void hits_drops_report_final(struct bench_res res[], int res_cnt);
6060 void 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
6262 void ops_report_progress(int iter, struct bench_res *res, long delta_ns);
6363 void ops_report_final(struct bench_res res[], int res_cnt);
6464
65−static inline __u64 get_time_ns() {
65+static inline __u64 get_time_ns(void)
66+{
6667 struct timespec t;
6768
6869 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
3636 struct counter *hits;
3737 } count_local_ctx;
3838
39−static void count_local_setup()
39+static void count_local_setup(void)
4040 {
4141 struct count_local_ctx *ctx = &count_local_ctx;
4242
tools/testing/selftests/bpf/benchs/bench_rename.c+8−8
@@ -11,7 +11,7 @@ static struct ctx { · 10 unmodified lines
1111 int fd;
1212 } ctx;
1313
14−static void validate()
14+static void validate(void)
1515 {
1616 if (env.producer_cnt != 1) {
1717 fprintf(stderr, "benchmark doesn't support multi-producer!\n");
@@ -43,7 +43,7 @@ static void measure(struct bench_res *res) · 25 unmodified lines
4343 res->hits = atomic_swap(&ctx.hits.value, 0);
4444 }
4545
46−static void setup_ctx()
46+static void setup_ctx(void)
4747 {
4848 setup_libbpf();
4949
@@ -71,36 +71,36 @@ static void attach_bpf(struct bpf_program *prog) · 21 unmodified lines
7171 }
7272 }
7373
74−static void setup_base()
74+static void setup_base(void)
7575 {
7676 setup_ctx();
7777 }
7878
79−static void setup_kprobe()
79+static void setup_kprobe(void)
8080 {
8181 setup_ctx();
8282 attach_bpf(ctx.skel->progs.prog1);
8383 }
8484
85−static void setup_kretprobe()
85+static void setup_kretprobe(void)
8686 {
8787 setup_ctx();
8888 attach_bpf(ctx.skel->progs.prog2);
8989 }
9090
91−static void setup_rawtp()
91+static void setup_rawtp(void)
9292 {
9393 setup_ctx();
9494 attach_bpf(ctx.skel->progs.prog3);
9595 }
9696
97−static void setup_fentry()
97+static void setup_fentry(void)
9898 {
9999 setup_ctx();
100100 attach_bpf(ctx.skel->progs.prog4);
101101 }
102102
103−static void setup_fexit()
103+static void setup_fexit(void)
104104 {
105105 setup_ctx();
106106 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
8888
8989 static struct counter buf_hits;
9090
91−static inline void bufs_trigger_batch()
91+static inline void bufs_trigger_batch(void)
9292 {
9393 (void)syscall(__NR_getpgid);
9494 }
9595
96−static void bufs_validate()
96+static void bufs_validate(void)
9797 {
9898 if (env.consumer_cnt != 1) {
9999 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
132132 res->drops = atomic_swap(&ctx->skel->bss->dropped, 0);
133133 }
134134
135−static struct ringbuf_bench *ringbuf_setup_skeleton()
135+static struct ringbuf_bench *ringbuf_setup_skeleton(void)
136136 {
137137 struct ringbuf_bench *skel;
138138
@@ -167,7 +167,7 @@ static int buf_process_sample(void *ctx, void *data, size_t len) · 28 unmodified lines
167167 return 0;
168168 }
169169
170−static void ringbuf_libbpf_setup()
170+static void ringbuf_libbpf_setup(void)
171171 {
172172 struct ringbuf_libbpf_ctx *ctx = &ringbuf_libbpf_ctx;
173173 struct bpf_link *link;
@@ -223,7 +223,7 @@ static void ringbuf_custom_measure(struct bench_res *res) · 49 unmodified lines
223223 res->drops = atomic_swap(&ctx->skel->bss->dropped, 0);
224224 }
225225
226−static void ringbuf_custom_setup()
226+static void ringbuf_custom_setup(void)
227227 {
228228 struct ringbuf_custom_ctx *ctx = &ringbuf_custom_ctx;
229229 const size_t page_size = getpagesize();
@@ -352,7 +352,7 @@ static void perfbuf_measure(struct bench_res *res) · 122 unmodified lines
352352 res->drops = atomic_swap(&ctx->skel->bss->dropped, 0);
353353 }
354354
355−static struct perfbuf_bench *perfbuf_setup_skeleton()
355+static struct perfbuf_bench *perfbuf_setup_skeleton(void)
356356 {
357357 struct perfbuf_bench *skel;
358358
@@ -390,7 +390,7 @@ perfbuf_process_sample_raw(void *input_ctx, int cpu, · 31 unmodified lines
390390 return LIBBPF_PERF_EVENT_CONT;
391391 }
392392
393−static void perfbuf_libbpf_setup()
393+static void perfbuf_libbpf_setup(void)
394394 {
395395 struct perfbuf_libbpf_ctx *ctx = &perfbuf_libbpf_ctx;
396396 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+
7+static struct strncmp_ctx {
8+ struct strncmp_bench *skel;
9+} ctx;
10+
11+static struct strncmp_args {
12+ u32 cmp_str_len;
13+} args = {
14+ .cmp_str_len = 32,
15+};
16+
17+enum {
18+ ARG_CMP_STR_LEN = 5000,
19+};
20+
21+static 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+
27+static 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+
46+const struct argp bench_strncmp_argp = {
47+ .options = opts,
48+ .parser = strncmp_parse_arg,
49+};
50+
51+static 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+
59+static 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+
101+static 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+
112+static void strncmp_no_helper_setup(void)
113+{
114+ strncmp_setup();
115+ strncmp_attach_prog(ctx.skel->progs.strncmp_no_helper);
116+}
117+
118+static void strncmp_helper_setup(void)
119+{
120+ strncmp_setup();
121+ strncmp_attach_prog(ctx.skel->progs.strncmp_helper);
122+}
123+
124+static void *strncmp_producer(void *ctx)
125+{
126+ while (true)
127+ (void)syscall(__NR_getpgid);
128+ return NULL;
129+}
130+
131+static void *strncmp_consumer(void *ctx)
132+{
133+ return NULL;
134+}
135+
136+static void strncmp_measure(struct bench_res *res)
137+{
138+ res->hits = atomic_swap(&ctx.skel->bss->hits, 0);
139+}
140+
141+const 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+
152+const 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
1111
1212 static struct counter base_hits;
1313
14−static void trigger_validate()
14+static void trigger_validate(void)
1515 {
1616 if (env.consumer_cnt != 1) {
1717 fprintf(stderr, "benchmark doesn't support multi-consumer!\n");
@@ -45,7 +45,7 @@ static void trigger_measure(struct bench_res *res) · 27 unmodified lines
4545 res->hits = atomic_swap(&ctx.skel->bss->hits, 0);
4646 }
4747
48−static void setup_ctx()
48+static void setup_ctx(void)
4949 {
5050 setup_libbpf();
5151
@@ -67,37 +67,37 @@ static void attach_bpf(struct bpf_program *prog) · 15 unmodified lines
6767 }
6868 }
6969
70−static void trigger_tp_setup()
70+static void trigger_tp_setup(void)
7171 {
7272 setup_ctx();
7373 attach_bpf(ctx.skel->progs.bench_trigger_tp);
7474 }
7575
76−static void trigger_rawtp_setup()
76+static void trigger_rawtp_setup(void)
7777 {
7878 setup_ctx();
7979 attach_bpf(ctx.skel->progs.bench_trigger_raw_tp);
8080 }
8181
82−static void trigger_kprobe_setup()
82+static void trigger_kprobe_setup(void)
8383 {
8484 setup_ctx();
8585 attach_bpf(ctx.skel->progs.bench_trigger_kprobe);
8686 }
8787
88−static void trigger_fentry_setup()
88+static void trigger_fentry_setup(void)
8989 {
9090 setup_ctx();
9191 attach_bpf(ctx.skel->progs.bench_trigger_fentry);
9292 }
9393
94−static void trigger_fentry_sleep_setup()
94+static void trigger_fentry_sleep_setup(void)
9595 {
9696 setup_ctx();
9797 attach_bpf(ctx.skel->progs.bench_trigger_fentry_sleep);
9898 }
9999
100−static void trigger_fmodret_setup()
100+static void trigger_fmodret_setup(void)
101101 {
102102 setup_ctx();
103103 attach_bpf(ctx.skel->progs.bench_trigger_fmodret);
@@ -183,22 +183,22 @@ static void usetup(bool use_retprobe, bool use_nop) · 79 unmodified lines
183183 ctx.skel->links.bench_trigger_uprobe = link;
184184 }
185185
186−static void uprobe_setup_with_nop()
186+static void uprobe_setup_with_nop(void)
187187 {
188188 usetup(false, true);
189189 }
190190
191−static void uretprobe_setup_with_nop()
191+static void uretprobe_setup_with_nop(void)
192192 {
193193 usetup(true, true);
194194 }
195195
196−static void uprobe_setup_without_nop()
196+static void uprobe_setup_without_nop(void)
197197 {
198198 usetup(false, false);
199199 }
200200
201−static void uretprobe_setup_without_nop()
201+static void uretprobe_setup_without_nop(void)
202202 {
203203 usetup(true, false);
204204 }
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+
4+source ./benchs/run_common.sh
5+
6+set -eufo pipefail
7+
8+for 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
12+done
tools/testing/selftests/bpf/config+2−0
@@ -38,7 +38,9 @@ CONFIG_IPV6_SIT=m · 37 unmodified lines
3838 CONFIG_BPF_JIT=y
3939 CONFIG_BPF_LSM=y
4040 CONFIG_SECURITY=y
41+CONFIG_RC_CORE=y
4142 CONFIG_LIRC=y
43+CONFIG_BPF_LIRC_MODE2=y
4244 CONFIG_IMA=y
4345 CONFIG_SECURITYFS=y
4446 CONFIG_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
3939 },
4040 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
4141 .matches = {
42− {1, "R1=ctx(id=0,off=0,imm=0)"},
43− {1, "R10=fp0"},
44− {1, "R3_w=inv2"},
45− {2, "R3_w=inv4"},
46− {3, "R3_w=inv8"},
47− {4, "R3_w=inv16"},
48− {5, "R3_w=inv32"},
42+ {0, "R1=ctx(id=0,off=0,imm=0)"},
43+ {0, "R10=fp0"},
44+ {0, "R3_w=inv2"},
45+ {1, "R3_w=inv4"},
46+ {2, "R3_w=inv8"},
47+ {3, "R3_w=inv16"},
48+ {4, "R3_w=inv32"},
4949 },
5050 },
5151 {
@@ -67,19 +67,19 @@ static struct bpf_align_test tests[] = { · 15 unmodified lines
6767 },
6868 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
6969 .matches = {
70− {1, "R1=ctx(id=0,off=0,imm=0)"},
71− {1, "R10=fp0"},
72− {1, "R3_w=inv1"},
73− {2, "R3_w=inv2"},
74− {3, "R3_w=inv4"},
75− {4, "R3_w=inv8"},
76− {5, "R3_w=inv16"},
77− {6, "R3_w=inv1"},
78− {7, "R4_w=inv32"},
79− {8, "R4_w=inv16"},
80− {9, "R4_w=inv8"},
81− {10, "R4_w=inv4"},
82− {11, "R4_w=inv2"},
70+ {0, "R1=ctx(id=0,off=0,imm=0)"},
71+ {0, "R10=fp0"},
72+ {0, "R3_w=inv1"},
73+ {1, "R3_w=inv2"},
74+ {2, "R3_w=inv4"},
75+ {3, "R3_w=inv8"},
76+ {4, "R3_w=inv16"},
77+ {5, "R3_w=inv1"},
78+ {6, "R4_w=inv32"},
79+ {7, "R4_w=inv16"},
80+ {8, "R4_w=inv8"},
81+ {9, "R4_w=inv4"},
82+ {10, "R4_w=inv2"},
8383 },
8484 },
8585 {
@@ -96,14 +96,14 @@ static struct bpf_align_test tests[] = { · 10 unmodified lines
9696 },
9797 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
9898 .matches = {
99− {1, "R1=ctx(id=0,off=0,imm=0)"},
100− {1, "R10=fp0"},
101− {1, "R3_w=inv4"},
102− {2, "R3_w=inv8"},
103− {3, "R3_w=inv10"},
104− {4, "R4_w=inv8"},
105− {5, "R4_w=inv12"},
106− {6, "R4_w=inv14"},
99+ {0, "R1=ctx(id=0,off=0,imm=0)"},
100+ {0, "R10=fp0"},
101+ {0, "R3_w=inv4"},
102+ {1, "R3_w=inv8"},
103+ {2, "R3_w=inv10"},
104+ {3, "R4_w=inv8"},
105+ {4, "R4_w=inv12"},
106+ {5, "R4_w=inv14"},
107107 },
108108 },
109109 {
@@ -118,12 +118,12 @@ static struct bpf_align_test tests[] = { · 8 unmodified lines
118118 },
119119 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
120120 .matches = {
121− {1, "R1=ctx(id=0,off=0,imm=0)"},
122− {1, "R10=fp0"},
121+ {0, "R1=ctx(id=0,off=0,imm=0)"},
122+ {0, "R10=fp0"},
123+ {0, "R3_w=inv7"},
123124 {1, "R3_w=inv7"},
124− {2, "R3_w=inv7"},
125− {3, "R3_w=inv14"},
126− {4, "R3_w=inv56"},
125+ {2, "R3_w=inv14"},
126+ {3, "R3_w=inv56"},
127127 },
128128 },
129129
@@ -161,19 +161,19 @@ static struct bpf_align_test tests[] = { · 31 unmodified lines
161161 },
162162 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
163163 .matches = {
164− {7, "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))"},
166− {8, "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))"},
168− {10, "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))"},
170− {18, "R3=pkt_end(id=0,off=0,imm=0)"},
171− {18, "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))"},
173− {20, "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))"},
175− {22, "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))"},
164+ {6, "R0_w=pkt(id=0,off=8,r=8,imm=0)"},
165+ {6, "R3_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},
166+ {7, "R3_w=inv(id=0,umax_value=510,var_off=(0x0; 0x1fe))"},
167+ {8, "R3_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
168+ {9, "R3_w=inv(id=0,umax_value=2040,var_off=(0x0; 0x7f8))"},
169+ {10, "R3_w=inv(id=0,umax_value=4080,var_off=(0x0; 0xff0))"},
170+ {12, "R3_w=pkt_end(id=0,off=0,imm=0)"},
171+ {17, "R4_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},
172+ {18, "R4_w=inv(id=0,umax_value=8160,var_off=(0x0; 0x1fe0))"},
173+ {19, "R4_w=inv(id=0,umax_value=4080,var_off=(0x0; 0xff0))"},
174+ {20, "R4_w=inv(id=0,umax_value=2040,var_off=(0x0; 0x7f8))"},
175+ {21, "R4_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
176+ {22, "R4_w=inv(id=0,umax_value=510,var_off=(0x0; 0x1fe))"},
177177 },
178178 },
179179 {
@@ -194,16 +194,16 @@ static struct bpf_align_test tests[] = { · 14 unmodified lines
194194 },
195195 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
196196 .matches = {
197− {7, "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))"},
199− {9, "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))"},
201− {11, "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))"},
203− {13, "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))"},
205− {15, "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))"},
197+ {6, "R3_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},
198+ {7, "R4_w=inv(id=1,umax_value=255,var_off=(0x0; 0xff))"},
199+ {8, "R4_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},
200+ {9, "R4_w=inv(id=1,umax_value=255,var_off=(0x0; 0xff))"},
201+ {10, "R4_w=inv(id=0,umax_value=510,var_off=(0x0; 0x1fe))"},
202+ {11, "R4_w=inv(id=1,umax_value=255,var_off=(0x0; 0xff))"},
203+ {12, "R4_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
204+ {13, "R4_w=inv(id=1,umax_value=255,var_off=(0x0; 0xff))"},
205+ {14, "R4_w=inv(id=0,umax_value=2040,var_off=(0x0; 0x7f8))"},
206+ {15, "R4_w=inv(id=0,umax_value=4080,var_off=(0x0; 0xff0))"},
207207 },
208208 },
209209 {
@@ -234,14 +234,14 @@ static struct bpf_align_test tests[] = { · 24 unmodified lines
234234 },
235235 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
236236 .matches = {
237− {4, "R5_w=pkt(id=0,off=0,r=0,imm=0)"},
238− {5, "R5_w=pkt(id=0,off=14,r=0,imm=0)"},
239− {6, "R4_w=pkt(id=0,off=14,r=0,imm=0)"},
240− {10, "R2=pkt(id=0,off=0,r=18,imm=0)"},
237+ {2, "R5_w=pkt(id=0,off=0,r=0,imm=0)"},
238+ {4, "R5_w=pkt(id=0,off=14,r=0,imm=0)"},
239+ {5, "R4_w=pkt(id=0,off=14,r=0,imm=0)"},
240+ {9, "R2=pkt(id=0,off=0,r=18,imm=0)"},
241241 {10, "R5=pkt(id=0,off=14,r=18,imm=0)"},
242242 {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))"},
243244 {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))"},
245245 },
246246 },
247247 {
@@ -296,8 +296,8 @@ static struct bpf_align_test tests[] = { · 48 unmodified lines
296296 /* Calculated offset in R6 has unknown value, but known
297297 * alignment of 4.
298298 */
299− {8, "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))"},
299+ {6, "R2_w=pkt(id=0,off=0,r=8,imm=0)"},
300+ {7, "R6_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
301301 /* Offset is added to packet pointer R5, resulting in
302302 * known fixed offset, and variable offset from R6.
303303 */
@@ -313,11 +313,11 @@ static struct bpf_align_test tests[] = { · 9 unmodified lines
313313 /* Variable offset is added to R5 packet pointer,
314314 * resulting in auxiliary alignment of 4.
315315 */
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))"},
317317 /* Constant offset is added to R5, resulting in
318318 * reg->off of 14.
319319 */
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))"},
321321 /* At the time the word size load is performed from R5,
322322 * its total fixed offset is NET_IP_ALIGN + reg->off
323323 * (14) which is 16. Then the variable offset is 4-byte
@@ -329,18 +329,18 @@ static struct bpf_align_test tests[] = { · 5 unmodified lines
329329 /* Constant offset is added to R5 packet pointer,
330330 * resulting in reg->off value of 14.
331331 */
332− {26, "R5_w=pkt(id=0,off=14,r=8"},
332+ {25, "R5_w=pkt(id=0,off=14,r=8"},
333333 /* Variable offset is added to R5, resulting in a
334334 * variable offset of (4n).
335335 */
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))"},
337337 /* 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))"},
339339 /* And once more we add a variable; resulting var_off
340340 * is still (4n), fixed offset is not changed.
341341 * Also, we create a new reg->id.
342342 */
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)"},
344344 /* At the time the word size load is performed from R5,
345345 * its total fixed offset is NET_IP_ALIGN + reg->off (18)
346346 * which is 20. Then the variable offset is (4n), so
@@ -386,13 +386,13 @@ static struct bpf_align_test tests[] = { · 39 unmodified lines
386386 /* Calculated offset in R6 has unknown value, but known
387387 * alignment of 4.
388388 */
389− {8, "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))"},
389+ {6, "R2_w=pkt(id=0,off=0,r=8,imm=0)"},
390+ {7, "R6_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
391391 /* 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))"},
393393 /* Packet pointer has (4n+2) offset */
394394 {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)"},
396396 /* At the time the word size load is performed from R5,
397397 * its total fixed offset is NET_IP_ALIGN + reg->off (0)
398398 * which is 2. Then the variable offset is (4n+2), so
@@ -403,12 +403,12 @@ static struct bpf_align_test tests[] = { · 4 unmodified lines
403403 /* Newly read value in R6 was shifted left by 2, so has
404404 * known alignment of 4.
405405 */
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))"},
407407 /* Added (4n) to packet pointer's (4n+2) var_off, giving
408408 * another (4n+2).
409409 */
410410 {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)"},
412412 /* At the time the word size load is performed from R5,
413413 * its total fixed offset is NET_IP_ALIGN + reg->off (0)
414414 * which is 2. Then the variable offset is (4n+2), so
@@ -448,18 +448,18 @@ static struct bpf_align_test tests[] = { · 33 unmodified lines
448448 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
449449 .result = REJECT,
450450 .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)"},
452452 /* (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)"},
454454 /* (4n) + 14 == (4n+2). We blow our bounds, because
455455 * the add could overflow.
456456 */
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)"},
458458 /* Checked s>=0 */
459459 {9, "R5=inv(id=0,umin_value=2,umax_value=9223372036854775806,var_off=(0x2; 0x7ffffffffffffffc)"},
460460 /* packet pointer + nonnegative (4n+2) */
461461 {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)"},
463463 /* NET_IP_ALIGN + (4n+2) == (4n), alignment is fine.
464464 * We checked the bounds, but it might have been able
465465 * to overflow if the packet pointer started in the
@@ -502,14 +502,14 @@ static struct bpf_align_test tests[] = { · 36 unmodified lines
502502 /* Calculated offset in R6 has unknown value, but known
503503 * alignment of 4.
504504 */
505− {7, "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))"},
505+ {6, "R2_w=pkt(id=0,off=0,r=8,imm=0)"},
506+ {8, "R6_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
507507 /* 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))"},
509509 /* 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))"},
511511 /* 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)"},
513513 /* Checked s>= 0 */
514514 {14, "R6=inv(id=0,umin_value=2,umax_value=1034,var_off=(0x2; 0x7fc))"},
515515 /* At the time the word size load is performed from R5,
@@ -556,14 +556,14 @@ static struct bpf_align_test tests[] = { · 40 unmodified lines
556556 /* Calculated offset in R6 has unknown value, but known
557557 * alignment of 4.
558558 */
559− {7, "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))"},
559+ {6, "R2_w=pkt(id=0,off=0,r=8,imm=0)"},
560+ {9, "R6_w=inv(id=0,umax_value=60,var_off=(0x0; 0x3c))"},
561561 /* 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))"},
563563 /* Subtracting from packet pointer overflows ubounds */
564564 {13, "R5_w=pkt(id=2,off=0,r=8,umin_value=18446744073709551542,umax_value=18446744073709551602,var_off=(0xffffffffffffff82; 0x7c)"},
565565 /* 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))"},
567567 /* Adding it to packet pointer gives nice bounds again */
568568 {16, "R5_w=pkt(id=3,off=0,r=0,umin_value=2,umax_value=1082,var_off=(0x2; 0xfffffffc)"},
569569 /* 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
625625 line_ptr = strtok(bpf_vlog_copy, "\n");
626626 for (i = 0; i < MAX_MATCHES; i++) {
627627 struct bpf_reg_match m = test->matches[i];
628+ int tmp;
628629
629630 if (!m.match)
630631 break;
631632 while (line_ptr) {
632633 cur_line = -1;
633634 sscanf(line_ptr, "%u: ", &cur_line);
635+ if (cur_line == -1)
636+ sscanf(line_ptr, "from %u to %u: ", &tmp, &cur_line);
634637 if (cur_line == m.line)
635638 break;
636639 line_ptr = strtok(NULL, "\n");
@@ -642,7 +645,19 @@ static int do_test_single(struct bpf_align_test *test) · 5 unmodified lines
642645 printf("%s", bpf_vlog);
643646 break;
644647 }
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+ */
645654 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)) {
646661 printf("Failed to find match %u: %s\n",
647662 m.line, m.match);
648663 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
6565 if (CHECK_FAIL(err))
6666 goto done;
6767
68− prog = bpf_object__find_program_by_title(objs[i],
69− "raw_tp/sys_enter");
68+ prog = bpf_object__find_program_by_name(objs[i],
69+ "test_obj_id");
7070 if (CHECK_FAIL(!prog))
7171 goto done;
7272 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
217217 static int libbpf_debug_print(enum libbpf_print_level level,
218218 const char *format, va_list args)
219219 {
220− const char *log_buf;
220+ const char *prog_name, *log_buf;
221221
222222 if (level != LIBBPF_WARN ||
223223 !strstr(format, "-- BEGIN PROG LOAD LOG --")) {
@@ -225,15 +225,14 @@ static int libbpf_debug_print(enum libbpf_print_level level, · 1 unmodified line
225225 return 0;
226226 }
227227
228− /* skip prog_name */
229− va_arg(args, char *);
228+ prog_name = va_arg(args, char *);
230229 log_buf = va_arg(args, char *);
231230 if (!log_buf)
232231 goto out;
233232 if (err_str && strstr(log_buf, err_str) != NULL)
234233 found = true;
235234 out:
236− printf(format, log_buf);
235+ printf(format, prog_name, log_buf);
237236 return 0;
238237 }
239238
tools/testing/selftests/bpf/prog_tests/btf.c+0−1
@@ -22,7 +22,6 @@ · 21 unmodified lines
2222 #include <bpf/libbpf.h>
2323 #include <bpf/btf.h>
2424
25−#include "bpf_rlimit.h"
2625 #include "bpf_util.h"
2726 #include "../test_btf.h"
2827 #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
6767 goto close_bpf_object;
6868 }
6969
70− prog = bpf_object__find_program_by_title(obj, v4 ?
71− "cgroup/connect4" :
72− "cgroup/connect6");
70+ prog = bpf_object__find_program_by_name(obj, v4 ?
71+ "connect4" :
72+ "connect6");
7373 if (CHECK(!prog, "find_prog", "connect prog not found\n")) {
7474 err = -EIO;
7575 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
8383 goto close_bpf_object;
8484 }
8585
86− prog = bpf_object__find_program_by_title(obj, v4 ?
87− "cgroup/getpeername4" :
88− "cgroup/getpeername6");
86+ prog = bpf_object__find_program_by_name(obj, v4 ?
87+ "getpeername4" :
88+ "getpeername6");
8989 if (CHECK(!prog, "find_prog", "getpeername prog not found\n")) {
9090 err = -EIO;
9191 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
9999 goto close_bpf_object;
100100 }
101101
102− prog = bpf_object__find_program_by_title(obj, v4 ?
103− "cgroup/getsockname4" :
104− "cgroup/getsockname6");
102+ prog = bpf_object__find_program_by_name(obj, v4 ?
103+ "getsockname4" :
104+ "getsockname6");
105105 if (CHECK(!prog, "find_prog", "getsockname prog not found\n")) {
106106 err = -EIO;
107107 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
1010
1111 #define STRUCT_TO_CHAR_PTR(struct_name) (const char *)&(struct struct_name)
1212
13−#define MODULES_CASE(name, sec_name, tp_name) { \
13+#define MODULES_CASE(name, pg_name, tp_name) { \
1414 .case_name = name, \
1515 .bpf_obj_file = "test_core_reloc_module.o", \
1616 .btf_src_file = NULL, /* find in kernel module BTFs */ \
@@ -28,7 +28,7 @@ static int duration = 0; · 11 unmodified lines
2828 .comm_len = sizeof("test_progs"), \
2929 }, \
3030 .output_len = sizeof(struct core_reloc_module_output), \
31− .prog_sec_name = sec_name, \
31+ .prog_name = pg_name, \
3232 .raw_tp_name = tp_name, \
3333 .trigger = __trigger_module_test_read, \
3434 .needs_testmod = true, \
@@ -43,7 +43,9 @@ static int duration = 0; · 8 unmodified lines
4343 #define FLAVORS_CASE_COMMON(name) \
4444 .case_name = #name, \
4545 .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" \
4749
4850 #define FLAVORS_CASE(name) { \
4951 FLAVORS_CASE_COMMON(name), \
@@ -66,7 +68,9 @@ static int duration = 0; · 16 unmodified lines
6668 #define NESTING_CASE_COMMON(name) \
6769 .case_name = #name, \
6870 .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" \
7074
7175 #define NESTING_CASE(name) { \
7276 NESTING_CASE_COMMON(name), \
@@ -91,7 +95,9 @@ static int duration = 0; · 18 unmodified lines
9195 #define ARRAYS_CASE_COMMON(name) \
9296 .case_name = #name, \
9397 .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" \
95101
96102 #define ARRAYS_CASE(name) { \
97103 ARRAYS_CASE_COMMON(name), \
@@ -123,7 +129,9 @@ static int duration = 0; · 25 unmodified lines
123129 #define PRIMITIVES_CASE_COMMON(name) \
124130 .case_name = #name, \
125131 .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" \
127135
128136 #define PRIMITIVES_CASE(name) { \
129137 PRIMITIVES_CASE_COMMON(name), \
@@ -158,6 +166,8 @@ static int duration = 0; · 28 unmodified lines
158166 .e = 5, .f = 6, .g = 7, .h = 8, \
159167 }, \
160168 .output_len = sizeof(struct core_reloc_mods_output), \
169+ .raw_tp_name = "sys_enter", \
170+ .prog_name = "test_core_mods", \
161171 }
162172
163173 #define PTR_AS_ARR_CASE(name) { \
@@ -174,6 +184,8 @@ static int duration = 0; · 10 unmodified lines
174184 .a = 3, \
175185 }, \
176186 .output_len = sizeof(struct core_reloc_ptr_as_arr), \
187+ .raw_tp_name = "sys_enter", \
188+ .prog_name = "test_core_ptr_as_arr", \
177189 }
178190
179191 #define INTS_DATA(struct_name) STRUCT_TO_CHAR_PTR(struct_name) { \
@@ -190,7 +202,9 @@ static int duration = 0; · 10 unmodified lines
190202 #define INTS_CASE_COMMON(name) \
191203 .case_name = #name, \
192204 .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"
194208
195209 #define INTS_CASE(name) { \
196210 INTS_CASE_COMMON(name), \
@@ -208,7 +222,9 @@ static int duration = 0; · 11 unmodified lines
208222 #define FIELD_EXISTS_CASE_COMMON(name) \
209223 .case_name = #name, \
210224 .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"
212228
213229 #define BITFIELDS_CASE_COMMON(objfile, test_name_prefix, name) \
214230 .case_name = test_name_prefix#name, \
@@ -223,6 +239,8 @@ static int duration = 0; · 8 unmodified lines
223239 .output = STRUCT_TO_CHAR_PTR(core_reloc_bitfields_output) \
224240 __VA_ARGS__, \
225241 .output_len = sizeof(struct core_reloc_bitfields_output), \
242+ .raw_tp_name = "sys_enter", \
243+ .prog_name = "test_core_bitfields", \
226244 }, { \
227245 BITFIELDS_CASE_COMMON("test_core_reloc_bitfields_direct.o", \
228246 "direct:", name), \
@@ -231,7 +249,7 @@ static int duration = 0; · 2 unmodified lines
231249 .output = STRUCT_TO_CHAR_PTR(core_reloc_bitfields_output) \
232250 __VA_ARGS__, \
233251 .output_len = sizeof(struct core_reloc_bitfields_output), \
234− .prog_sec_name = "tp_btf/sys_enter", \
252+ .prog_name = "test_core_bitfields_direct", \
235253 }
236254
237255
@@ -239,17 +257,21 @@ static int duration = 0; · 1 unmodified line
239257 BITFIELDS_CASE_COMMON("test_core_reloc_bitfields_probed.o", \
240258 "probed:", name), \
241259 .fails = true, \
260+ .raw_tp_name = "sys_enter", \
261+ .prog_name = "test_core_bitfields", \
242262 }, { \
243263 BITFIELDS_CASE_COMMON("test_core_reloc_bitfields_direct.o", \
244264 "direct:", name), \
245− .prog_sec_name = "tp_btf/sys_enter", \
246265 .fails = true, \
266+ .prog_name = "test_core_bitfields_direct", \
247267 }
248268
249269 #define SIZE_CASE_COMMON(name) \
250270 .case_name = #name, \
251271 .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"
253275
254276 #define SIZE_OUTPUT_DATA(type) \
255277 STRUCT_TO_CHAR_PTR(core_reloc_size_output) { \
@@ -277,8 +299,10 @@ static int duration = 0; · 21 unmodified lines
277299
278300 #define TYPE_BASED_CASE_COMMON(name) \
279301 .case_name = #name, \
280− .bpf_obj_file = "test_core_reloc_type_based.o", \
281− .btf_src_file = "btf__core_reloc_" #name ".o" \
302+ .bpf_obj_file = "test_core_reloc_type_based.o", \
303+ .btf_src_file = "btf__core_reloc_" #name ".o", \
304+ .raw_tp_name = "sys_enter", \
305+ .prog_name = "test_core_type_based"
282306
283307 #define TYPE_BASED_CASE(name, ...) { \
284308 TYPE_BASED_CASE_COMMON(name), \
@@ -295,7 +319,9 @@ static int duration = 0; · 10 unmodified lines
295319 #define TYPE_ID_CASE_COMMON(name) \
296320 .case_name = #name, \
297321 .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"
299325
300326 #define TYPE_ID_CASE(name, setup_fn) { \
301327 TYPE_ID_CASE_COMMON(name), \
@@ -312,7 +338,9 @@ static int duration = 0; · 10 unmodified lines
312338 #define ENUMVAL_CASE_COMMON(name) \
313339 .case_name = #name, \
314340 .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"
316344
317345 #define ENUMVAL_CASE(name, ...) { \
318346 ENUMVAL_CASE_COMMON(name), \
@@ -342,7 +370,7 @@ struct core_reloc_test_case { · 23 unmodified lines
342370 bool fails;
343371 bool needs_testmod;
344372 bool relaxed_core_relocs;
345− const char *prog_sec_name;
373+ const char *prog_name;
346374 const char *raw_tp_name;
347375 setup_test_fn setup;
348376 trigger_test_fn trigger;
@@ -497,11 +525,13 @@ static struct core_reloc_test_case test_cases[] = { · 148 unmodified lines
497525 .comm_len = sizeof("test_progs"),
498526 },
499527 .output_len = sizeof(struct core_reloc_kernel_output),
528+ .raw_tp_name = "sys_enter",
529+ .prog_name = "test_core_kernel",
500530 },
501531
502532 /* 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"),
504− MODULES_CASE("module_direct", "tp_btf/bpf_testmod_test_read", NULL),
533+ MODULES_CASE("module_probed", "test_core_module_probed", "bpf_testmod_test_read"),
534+ MODULES_CASE("module_direct", "test_core_module_direct", NULL),
505535
506536 /* validate BPF program can use multiple flavors to match against
507537 * single target BTF type
@@ -580,6 +610,8 @@ static struct core_reloc_test_case test_cases[] = { · 72 unmodified lines
580610 .c = 0, /* BUG in clang, should be 3 */
581611 },
582612 .output_len = sizeof(struct core_reloc_misc_output),
613+ .raw_tp_name = "sys_enter",
614+ .prog_name = "test_core_misc",
583615 },
584616
585617 /* validate field existence checks */
@@ -848,14 +880,9 @@ void test_core_reloc(void) · 262 unmodified lines
848880 if (!ASSERT_OK_PTR(obj, "obj_open"))
849881 goto cleanup;
850882
851− probe_name = "raw_tracepoint/sys_enter";
852− tp_name = "sys_enter";
853− if (test_case->prog_sec_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);
883+ probe_name = test_case->prog_name;
884+ tp_name = test_case->raw_tp_name; /* NULL for tp_btf */
885+ prog = bpf_object__find_program_by_name(obj, probe_name);
859886 if (CHECK(!prog, "find_probe",
860887 "prog '%s' not found\n", probe_name))
861888 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
101101
102102 for (i = 0; i < prog_cnt; i++) {
103103 struct bpf_link_info link_info;
104+ struct bpf_program *pos;
105+ const char *pos_sec_name;
104106 char *tgt_name;
105107 __s32 btf_id;
106108
@@ -109,7 +111,14 @@ static void test_fexit_bpf2bpf_common(const char *obj_file, · 2 unmodified lines
109111 goto close_prog;
110112 btf_id = btf__find_by_name_kind(btf, tgt_name + 1, BTF_KIND_FUNC);
111113
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+ }
113122 if (!ASSERT_OK_PTR(prog[i], prog_name[i]))
114123 goto close_prog;
115124
@@ -211,8 +220,8 @@ static void test_func_replace_verify(void) · 95 unmodified lines
211220
212221 static int test_second_attach(struct bpf_object *obj)
213222 {
214− const char *prog_name = "freplace/get_constant";
215− const char *tgt_name = prog_name + 9; /* cut off freplace/ */
223+ const char *prog_name = "security_new_get_constant";
224+ const char *tgt_name = "get_constant";
216225 const char *tgt_obj_file = "./test_pkt_access.o";
217226 struct bpf_program *prog = NULL;
218227 struct bpf_object *tgt_obj;
@@ -220,7 +229,7 @@ static int test_second_attach(struct bpf_object *obj) · 1 unmodified line
220229 struct bpf_link *link;
221230 int err = 0, tgt_fd;
222231
223− prog = bpf_object__find_program_by_title(obj, prog_name);
232+ prog = bpf_object__find_program_by_name(obj, prog_name);
224233 if (CHECK(!prog, "find_prog", "prog %s not found\n", prog_name))
225234 return -ENOENT;
226235
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+
5+void 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+
42+cleanup:
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
8989 {
9090 const char *file = "./test_get_stack_rawtp.o";
9191 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";
9393 int i, err, prog_fd, exp_cnt = MAX_CNT_RAWTP;
9494 struct perf_buffer *pb = NULL;
9595 struct bpf_link *link = NULL;
@@ -107,7 +107,7 @@ void test_get_stack_raw_tp(void) · 11 unmodified lines
107107 if (CHECK(err, "prog_load raw tp", "err %d errno %d\n", err, errno))
108108 return;
109109
110− prog = bpf_object__find_program_by_title(obj, prog_name);
110+ prog = bpf_object__find_program_by_name(obj, prog_name);
111111 if (CHECK(!prog, "find_probe", "prog '%s' not found\n", prog_name))
112112 goto close_prog;
113113
tools/testing/selftests/bpf/prog_tests/ksyms_btf.c+14−0
@@ -8,6 +8,7 @@ · 7 unmodified lines
88 #include "test_ksyms_btf_null_check.skel.h"
99 #include "test_ksyms_weak.skel.h"
1010 #include "test_ksyms_weak.lskel.h"
11+#include "test_ksyms_btf_write_check.skel.h"
1112
1213 static int duration;
1314
@@ -137,6 +138,16 @@ cleanup: · 123 unmodified lines
137138 test_ksyms_weak_lskel__destroy(skel);
138139 }
139140
141+static 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+
140151 void test_ksyms_btf(void)
141152 {
142153 int percpu_datasec;
@@ -167,4 +178,7 @@ void test_ksyms_btf(void) · 24 unmodified lines
167178
168179 if (test__start_subtest("weak_ksyms_lskel"))
169180 test_weak_syms_lskel();
181+
182+ if (test__start_subtest("write_check"))
183+ test_write_check();
170184 }
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+
7+void 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+
41+cleanup:
42+ btf__free(btf);
43+}
44+
45+void 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+
79+cleanup:
80+ btf__free(btf);
81+}
82+
83+void 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
1818 #include <netinet/in.h>
1919 #include <bpf/bpf.h>
2020 #include <bpf/libbpf.h>
21−#include "bpf_rlimit.h"
2221 #include "bpf_util.h"
2322
2423 #include "test_progs.h"
tools/testing/selftests/bpf/prog_tests/sk_lookup.c+0−1
@@ -30,7 +30,6 @@ · 29 unmodified lines
3030 #include <bpf/bpf.h>
3131
3232 #include "test_progs.h"
33−#include "bpf_rlimit.h"
3433 #include "bpf_util.h"
3534 #include "cgroup_helpers.h"
3635 #include "network_helpers.h"
tools/testing/selftests/bpf/prog_tests/sock_fields.c+0−1
@@ -15,7 +15,6 @@ · 14 unmodified lines
1515 #include "network_helpers.h"
1616 #include "cgroup_helpers.h"
1717 #include "test_progs.h"
18−#include "bpf_rlimit.h"
1918 #include "test_sock_fields.skel.h"
2019
2120 enum 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
136136 return fd;
137137 }
138138
139−static int prog_attach(struct bpf_object *obj, int cgroup_fd, const char *title)
139+static int prog_attach(struct bpf_object *obj, int cgroup_fd, const char *title,
140+ const char *prog_name)
140141 {
141142 enum bpf_attach_type attach_type;
142143 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
145146
146147 err = libbpf_prog_type_by_name(title, &prog_type, &attach_type);
147148 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);
149150 return -1;
150151 }
151152
152− prog = bpf_object__find_program_by_title(obj, title);
153+ prog = bpf_object__find_program_by_name(obj, prog_name);
153154 if (!prog) {
154− log_err("Failed to find %s BPF program", title);
155+ log_err("Failed to find %s BPF program", prog_name);
155156 return -1;
156157 }
157158
158159 err = bpf_prog_attach(bpf_program__fd(prog), cgroup_fd,
159160 attach_type, 0);
160161 if (err) {
161− log_err("Failed to attach %s BPF program", title);
162+ log_err("Failed to attach %s BPF program", prog_name);
162163 return -1;
163164 }
164165
@@ -181,11 +182,11 @@ static void run_test(int cgroup_fd) · 16 unmodified lines
181182 if (!ASSERT_OK(err, "obj_load"))
182183 goto close_bpf_object;
183184
184− err = prog_attach(obj, cgroup_fd, "cgroup/getsockopt");
185+ err = prog_attach(obj, cgroup_fd, "cgroup/getsockopt", "_getsockopt");
185186 if (CHECK_FAIL(err))
186187 goto close_bpf_object;
187188
188− err = prog_attach(obj, cgroup_fd, "cgroup/setsockopt");
189+ err = prog_attach(obj, cgroup_fd, "cgroup/setsockopt", "_setsockopt");
189190 if (CHECK_FAIL(err))
190191 goto close_bpf_object;
191192
tools/testing/selftests/bpf/prog_tests/stacktrace_map.c+2−2
@@ -4,7 +4,7 @@ · 3 unmodified lines
44 void test_stacktrace_map(void)
55 {
66 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";
88 int err, prog_fd, stack_trace_len;
99 const char *file = "./test_stacktrace_map.o";
1010 __u32 key, val, duration = 0;
@@ -16,7 +16,7 @@ void test_stacktrace_map(void) · 5 unmodified lines
1616 if (CHECK(err, "prog_load", "err %d errno %d\n", err, errno))
1717 return;
1818
19− prog = bpf_object__find_program_by_title(obj, prog_name);
19+ prog = bpf_object__find_program_by_name(obj, prog_name);
2020 if (CHECK(!prog, "find_prog", "prog '%s' not found\n", prog_name))
2121 goto close_prog;
2222
tools/testing/selftests/bpf/prog_tests/stacktrace_map_raw_tp.c+2−2
@@ -3,7 +3,7 @@ · 2 unmodified lines
33
44 void test_stacktrace_map_raw_tp(void)
55 {
6− const char *prog_name = "tracepoint/sched/sched_switch";
6+ const char *prog_name = "oncpu";
77 int control_map_fd, stackid_hmap_fd, stackmap_fd;
88 const char *file = "./test_stacktrace_map.o";
99 __u32 key, val, duration = 0;
@@ -16,7 +16,7 @@ void test_stacktrace_map_raw_tp(void) · 6 unmodified lines
1616 if (CHECK(err, "prog_load raw tp", "err %d errno %d\n", err, errno))
1717 return;
1818
19− prog = bpf_object__find_program_by_title(obj, prog_name);
19+ prog = bpf_object__find_program_by_name(obj, prog_name);
2020 if (CHECK(!prog, "find_prog", "prog '%s' not found\n", prog_name))
2121 goto close_prog;
2222
tools/testing/selftests/bpf/prog_tests/test_local_storage.c+6−14
@@ -28,10 +28,6 @@ static unsigned int duration; · 27 unmodified lines
2828 struct storage {
2929 void *inode;
3030 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;
3531 };
3632
3733 /* 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
6662
6763 static bool check_syscall_operations(int map_fd, int obj_fd)
6864 {
69− struct storage val = { .value = TEST_STORAGE_VALUE, .lock = { 0 } },
70− lookup_val = { .value = 0, .lock = { 0 } };
65+ struct storage val = { .value = TEST_STORAGE_VALUE },
66+ lookup_val = { .value = 0 };
7167 int err;
7268
7369 /* Looking up an existing element should fail initially */
74− err = bpf_map_lookup_elem_flags(map_fd, &obj_fd, &lookup_val,
75− BPF_F_LOCK);
70+ err = bpf_map_lookup_elem_flags(map_fd, &obj_fd, &lookup_val, 0);
7671 if (CHECK(!err || errno != ENOENT, "bpf_map_lookup_elem",
7772 "err:%d errno:%d\n", err, errno))
7873 return false;
7974
8075 /* Create a new element */
81− err = bpf_map_update_elem(map_fd, &obj_fd, &val,
82− BPF_NOEXIST | BPF_F_LOCK);
76+ err = bpf_map_update_elem(map_fd, &obj_fd, &val, BPF_NOEXIST);
8377 if (CHECK(err < 0, "bpf_map_update_elem", "err:%d errno:%d\n", err,
8478 errno))
8579 return false;
8680
8781 /* Lookup the newly created element */
88− err = bpf_map_lookup_elem_flags(map_fd, &obj_fd, &lookup_val,
89− BPF_F_LOCK);
82+ err = bpf_map_lookup_elem_flags(map_fd, &obj_fd, &lookup_val, 0);
9083 if (CHECK(err < 0, "bpf_map_lookup_elem", "err:%d errno:%d", err,
9184 errno))
9285 return false;
@@ -102,8 +95,7 @@ static bool check_syscall_operations(int map_fd, int obj_fd) · 9 unmodified lines
10295 return false;
10396
10497 /* The lookup should fail, now that the element has been deleted */
105− err = bpf_map_lookup_elem_flags(map_fd, &obj_fd, &lookup_val,
106− BPF_F_LOCK);
98+ err = bpf_map_lookup_elem_flags(map_fd, &obj_fd, &lookup_val, 0);
10799 if (CHECK(!err || errno != ENOENT, "bpf_map_lookup_elem",
108100 "err:%d errno:%d\n", err, errno))
109101 return false;
tools/testing/selftests/bpf/prog_tests/test_overhead.c+10−10
@@ -56,11 +56,11 @@ static void setaffinity(void) · 55 unmodified lines
5656
5757 void test_test_overhead(void)
5858 {
59− const char *kprobe_name = "kprobe/__set_task_comm";
60− const char *kretprobe_name = "kretprobe/__set_task_comm";
61− const char *raw_tp_name = "raw_tp/task_rename";
62− const char *fentry_name = "fentry/__set_task_comm";
63− const char *fexit_name = "fexit/__set_task_comm";
59+ const char *kprobe_name = "prog1";
60+ const char *kretprobe_name = "prog2";
61+ const char *raw_tp_name = "prog3";
62+ const char *fentry_name = "prog4";
63+ const char *fexit_name = "prog5";
6464 const char *kprobe_func = "__set_task_comm";
6565 struct bpf_program *kprobe_prog, *kretprobe_prog, *raw_tp_prog;
6666 struct bpf_program *fentry_prog, *fexit_prog;
@@ -76,23 +76,23 @@ void test_test_overhead(void) · 9 unmodified lines
7676 if (!ASSERT_OK_PTR(obj, "obj_open_file"))
7777 return;
7878
79− kprobe_prog = bpf_object__find_program_by_title(obj, kprobe_name);
79+ kprobe_prog = bpf_object__find_program_by_name(obj, kprobe_name);
8080 if (CHECK(!kprobe_prog, "find_probe",
8181 "prog '%s' not found\n", kprobe_name))
8282 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);
8484 if (CHECK(!kretprobe_prog, "find_probe",
8585 "prog '%s' not found\n", kretprobe_name))
8686 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);
8888 if (CHECK(!raw_tp_prog, "find_probe",
8989 "prog '%s' not found\n", raw_tp_name))
9090 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);
9292 if (CHECK(!fentry_prog, "find_probe",
9393 "prog '%s' not found\n", fentry_name))
9494 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);
9696 if (CHECK(!fexit_prog, "find_probe",
9797 "prog '%s' not found\n", fexit_name))
9898 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+
6+static 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+ */
24+static 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+
44+static 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);
87+out:
88+ strncmp_test__destroy(skel);
89+}
90+
91+static 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+
113+static 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+
135+static 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+
157+void 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
3535 struct bpf_program *prog;
3636 int duration = 0;
3737
38− prog = bpf_object__find_program_by_title(obj, name);
38+ prog = bpf_object__find_program_by_name(obj, name);
3939 if (CHECK(!prog, "find_probe", "prog '%s' not found\n", name))
4040 return ERR_PTR(-EINVAL);
4141 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
4444 /* TODO: use different target function to run in concurrent mode */
4545 void serial_test_trampoline_count(void)
4646 {
47− const char *fentry_name = "fentry/__set_task_comm";
48− const char *fexit_name = "fexit/__set_task_comm";
47+ const char *fentry_name = "prog1";
48+ const char *fexit_name = "prog2";
4949 const char *object = "test_trampoline_count.o";
5050 struct inst inst[MAX_TRAMP_PROGS] = {};
5151 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+
7+char _license[] SEC("license") = "GPL";
8+
9+__u64 test1_result = 0;
10+SEC("fentry/bpf_fentry_test1")
11+int 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;
43+SEC("fexit/bpf_fentry_test2")
44+int 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;
70+SEC("fmod_ret/bpf_modify_return_test")
71+int 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;
99+SEC("fexit/bpf_modify_return_test")
100+int 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
2020 struct local_storage {
2121 struct inode *exec_inode;
2222 __u32 value;
23− struct bpf_spin_lock lock;
2423 };
2524
2625 struct {
@@ -58,9 +57,7 @@ int BPF_PROG(unlink_hook, struct inode *dir, struct dentry *victim) · 31 unmodified lines
5857 bpf_get_current_task_btf(), 0, 0);
5958 if (storage) {
6059 /* Don't let an executable delete itself */
61− bpf_spin_lock(&storage->lock);
6260 is_self_unlink = storage->exec_inode == victim->d_inode;
63− bpf_spin_unlock(&storage->lock);
6461 if (is_self_unlink)
6562 return -EPERM;
6663 }
@@ -68,7 +65,7 @@ int BPF_PROG(unlink_hook, struct inode *dir, struct dentry *victim) · 1 unmodified line
6865 return 0;
6966 }
7067
71−SEC("lsm/inode_rename")
68+SEC("lsm.s/inode_rename")
7269 int BPF_PROG(inode_rename, struct inode *old_dir, struct dentry *old_dentry,
7370 struct inode *new_dir, struct dentry *new_dentry,
7471 unsigned int flags)
@@ -89,10 +86,8 @@ int BPF_PROG(inode_rename, struct inode *old_dir, struct dentry *old_dentry, · 14 unmodified lines
8986 if (!storage)
9087 return 0;
9188
92− bpf_spin_lock(&storage->lock);
9389 if (storage->value != DUMMY_STORAGE_VALUE)
9490 inode_storage_result = -1;
95− bpf_spin_unlock(&storage->lock);
9691
9792 err = bpf_inode_storage_delete(&inode_storage_map, old_dentry->d_inode);
9893 if (!err)
@@ -101,7 +96,7 @@ int BPF_PROG(inode_rename, struct inode *old_dir, struct dentry *old_dentry, · 2 unmodified lines
10196 return 0;
10297 }
10398
104−SEC("lsm/socket_bind")
99+SEC("lsm.s/socket_bind")
105100 int BPF_PROG(socket_bind, struct socket *sock, struct sockaddr *address,
106101 int addrlen)
107102 {
@@ -117,10 +112,8 @@ int BPF_PROG(socket_bind, struct socket *sock, struct sockaddr *address, · 9 unmodified lines
117112 if (!storage)
118113 return 0;
119114
120− bpf_spin_lock(&storage->lock);
121115 if (storage->value != DUMMY_STORAGE_VALUE)
122116 sk_storage_result = -1;
123− bpf_spin_unlock(&storage->lock);
124117
125118 err = bpf_sk_storage_delete(&sk_storage_map, sock->sk);
126119 if (!err)
@@ -129,7 +122,7 @@ int BPF_PROG(socket_bind, struct socket *sock, struct sockaddr *address, · 2 unmodified lines
129122 return 0;
130123 }
131124
132−SEC("lsm/socket_post_create")
125+SEC("lsm.s/socket_post_create")
133126 int BPF_PROG(socket_post_create, struct socket *sock, int family, int type,
134127 int protocol, int kern)
135128 {
@@ -144,9 +137,7 @@ int BPF_PROG(socket_post_create, struct socket *sock, int family, int type, · 8 unmodified lines
144137 if (!storage)
145138 return 0;
146139
147− bpf_spin_lock(&storage->lock);
148140 storage->value = DUMMY_STORAGE_VALUE;
149− bpf_spin_unlock(&storage->lock);
150141
151142 return 0;
152143 }
@@ -154,7 +145,7 @@ int BPF_PROG(socket_post_create, struct socket *sock, int family, int type, · 1 unmodified line
154145 /* This uses the local storage to remember the inode of the binary that a
155146 * process was originally executing.
156147 */
157−SEC("lsm/bprm_committed_creds")
148+SEC("lsm.s/bprm_committed_creds")
158149 void BPF_PROG(exec, struct linux_binprm *bprm)
159150 {
160151 __u32 pid = bpf_get_current_pid_tgid() >> 32;
@@ -166,18 +157,13 @@ void BPF_PROG(exec, struct linux_binprm *bprm) · 5 unmodified lines
166157 storage = bpf_task_storage_get(&task_storage_map,
167158 bpf_get_current_task_btf(), 0,
168159 BPF_LOCAL_STORAGE_GET_F_CREATE);
169− if (storage) {
170− bpf_spin_lock(&storage->lock);
160+ if (storage)
171161 storage->exec_inode = bprm->file->f_inode;
172− bpf_spin_unlock(&storage->lock);
173− }
174162
175163 storage = bpf_inode_storage_get(&inode_storage_map, bprm->file->f_inode,
176164 0, BPF_LOCAL_STORAGE_GET_F_CREATE);
177165 if (!storage)
178166 return;
179167
180− bpf_spin_lock(&storage->lock);
181168 storage->value = DUMMY_STORAGE_VALUE;
182− bpf_spin_unlock(&storage->lock);
183169 }
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 */
11+const volatile unsigned int cmp_str_len = 1;
12+const char target[STRNCMP_STR_SZ];
13+
14+long hits = 0;
15+char str[STRNCMP_STR_SZ];
16+
17+char _license[] SEC("license") = "GPL";
18+
19+static __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+
35+SEC("tp/syscalls/sys_enter_getpgid")
36+int 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+
43+SEC("tp/syscalls/sys_enter_getpgid")
44+int 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+
11+const char target[STRNCMP_STR_SZ] = "EEEEEEE";
12+char str[STRNCMP_STR_SZ];
13+int cmp_ret = 0;
14+int target_pid = 0;
15+
16+const char no_str_target[STRNCMP_STR_SZ] = "12345678";
17+char writable_target[STRNCMP_STR_SZ];
18+unsigned int no_const_str_size = STRNCMP_STR_SZ;
19+
20+char _license[] SEC("license") = "GPL";
21+
22+SEC("tp/syscalls/sys_enter_nanosleep")
23+int 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+
32+SEC("tp/syscalls/sys_enter_nanosleep")
33+int 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+
40+SEC("tp/syscalls/sys_enter_nanosleep")
41+int 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+
48+SEC("tp/syscalls/sys_enter_nanosleep")
49+int 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+
8+extern const int bpf_prog_active __ksym; /* int type global var. */
9+
10+SEC("raw_tp/sys_enter")
11+int 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+
29+char _license[] SEC("license") = "GPL";
tools/testing/selftests/bpf/test_cpp.cpp+8−1
@@ -7,9 +7,15 @@ · 6 unmodified lines
77
88 /* do nothing, just make sure we can link successfully */
99
10+static void dump_printf(void *ctx, const char *fmt, va_list args)
11+{
12+}
13+
1014 int main(int argc, char *argv[])
1115 {
16+ struct btf_dump_opts opts = { };
1217 struct test_core_extern *skel;
18+ struct btf *btf;
1319
1420 /* libbpf.h */
1521 libbpf_set_print(NULL);
@@ -18,7 +24,8 @@ int main(int argc, char *argv[]) · 2 unmodified lines
1824 bpf_prog_get_fd_by_id(0);
1925
2026 /* btf.h */
21− btf__new(NULL, 0);
27+ btf = btf__new(NULL, 0);
28+ btf_dump__new(btf, dump_printf, nullptr, &opts);
2229
2330 /* BPF skeleton */
2431 skel = test_core_extern__open_and_load();
tools/testing/selftests/bpf/test_maps.c+0−1
@@ -23,7 +23,6 @@ · 22 unmodified lines
2323 #include <bpf/libbpf.h>
2424
2525 #include "bpf_util.h"
26−#include "bpf_rlimit.h"
2726 #include "test_maps.h"
2827 #include "testing_helpers.h"
2928
tools/testing/selftests/bpf/test_progs.c+0−2
@@ -4,7 +4,6 @@ · 3 unmodified lines
44 #define _GNU_SOURCE
55 #include "test_progs.h"
66 #include "cgroup_helpers.h"
7−#include "bpf_rlimit.h"
87 #include <argp.h>
98 #include <pthread.h>
109 #include <sched.h>
@@ -1342,7 +1341,6 @@ int main(int argc, char **argv) · 1331 unmodified lines
13421341
13431342 /* Use libbpf 1.0 API mode */
13441343 libbpf_set_strict_mode(LIBBPF_STRICT_ALL);
1345−
13461344 libbpf_set_print(libbpf_print_fn);
13471345
13481346 srand(time(NULL));
tools/testing/selftests/bpf/test_verifier.c+8−10
@@ -41,7 +41,6 @@ · 40 unmodified lines
4141 # define CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS 1
4242 # endif
4343 #endif
44−#include "bpf_rlimit.h"
4544 #include "bpf_rand.h"
4645 #include "bpf_util.h"
4746 #include "test_btf.h"
@@ -701,22 +700,18 @@ static int create_sk_storage_map(void) · 653 unmodified lines
701700
702701 static int create_map_timer(void)
703702 {
704− struct bpf_create_map_attr attr = {
705− .name = "test_map",
706− .map_type = BPF_MAP_TYPE_ARRAY,
707− .key_size = 4,
708− .value_size = 16,
709− .max_entries = 1,
703+ LIBBPF_OPTS(bpf_map_create_opts, opts,
710704 .btf_key_type_id = 1,
711705 .btf_value_type_id = 5,
712− };
706+ );
713707 int fd, btf_fd;
714708
715709 btf_fd = load_btf();
716710 if (btf_fd < 0)
717711 return -1;
718− attr.btf_fd = btf_fd;
719− fd = bpf_create_map_xattr(&attr);
712+
713+ opts.btf_fd = btf_fd;
714+ fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, "test_map", 4, 16, 1, &opts);
720715 if (fd < 0)
721716 printf("Failed to create map with timer\n");
722717 return fd;
@@ -1399,6 +1394,9 @@ int main(int argc, char **argv) · 676 unmodified lines
13991394 return EXIT_FAILURE;
14001395 }
14011396
1397+ /* Use libbpf 1.0 API mode */
1398+ libbpf_set_strict_mode(LIBBPF_STRICT_ALL);
1399+
14021400 bpf_semi_rand_init();
14031401 return do_test(unpriv, from, to);
14041402 }
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
3232 OUTPUT_DIR="$HOME/.bpf_selftests"
3333 KCONFIG_URL="https://raw.githubusercontent.com/libbpf/libbpf/master/travis-ci/vmtest/configs/config-latest.${ARCH}"
3434 KCONFIG_API_URL="https://api.github.com/repos/libbpf/libbpf/contents/travis-ci/vmtest/configs/config-latest.${ARCH}"
35−INDEX_URL="https://raw.githubusercontent.com/libbpf/libbpf/master/travis-ci/vmtest/configs/INDEX"
35+INDEX_URL="https://raw.githubusercontent.com/libbpf/ci/master/INDEX"
3636 NUM_COMPILE_JOBS="$(nproc)"
3737 LOG_FILE_BASE="$(date +"bpf_selftests.%Y-%m-%d_%H-%M-%S")"
3838 LOG_FILE="${LOG_FILE_BASE}.log"