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. ====================
Showing the changes to tools (65 of 221 files). Show all
Unified · Split
| @@ -57,7 +57,7 @@ $(LIBBPF_INTERNAL_HDRS): $(LIBBPF_HDRS_DIR)/%.h: $(BPF_DIR)/%.h | $(LIBBPF_HDRS_ · 56 unmodified lines | ||
| 57 | 57 | $(LIBBPF_BOOTSTRAP): $(wildcard $(BPF_DIR)/*.[ch] $(BPF_DIR)/Makefile) | $(LIBBPF_BOOTSTRAP_OUTPUT) |
| 58 | 58 | $(Q)$(MAKE) -C $(BPF_DIR) OUTPUT=$(LIBBPF_BOOTSTRAP_OUTPUT) \ |
| 59 | 59 | DESTDIR=$(LIBBPF_BOOTSTRAP_DESTDIR) prefix= \ |
| 60 | − ARCH= CC=$(HOSTCC) LD=$(HOSTLD) $@ install_headers | |
| 60 | + ARCH= CROSS_COMPILE= CC=$(HOSTCC) LD=$(HOSTLD) $@ install_headers | |
| 61 | 61 | |
| 62 | 62 | $(LIBBPF_BOOTSTRAP_INTERNAL_HDRS): $(LIBBPF_BOOTSTRAP_HDRS_DIR)/%.h: $(BPF_DIR)/%.h | $(LIBBPF_BOOTSTRAP_HDRS_DIR) |
| 63 | 63 | $(call QUIET_INSTALL, $@) |
| @@ -152,6 +152,9 @@ CFLAGS += -DHAVE_LIBBFD_SUPPORT · 88 unmodified lines | ||
| 152 | 152 | SRCS += $(BFD_SRCS) |
| 153 | 153 | endif |
| 154 | 154 | |
| 155 | +HOST_CFLAGS = $(subst -I$(LIBBPF_INCLUDE),-I$(LIBBPF_BOOTSTRAP_INCLUDE),\ | |
| 156 | + $(subst $(CLANG_CROSS_FLAGS),,$(CFLAGS))) | |
| 157 | + | |
| 155 | 158 | BPFTOOL_BOOTSTRAP := $(BOOTSTRAP_OUTPUT)bpftool |
| 156 | 159 | |
| 157 | 160 | 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 | ||
| 202 | 205 | CFLAGS += $(if $(BUILD_BPF_SKELS),,-DBPFTOOL_WITHOUT_SKELETONS) |
| 203 | 206 | |
| 204 | 207 | $(BOOTSTRAP_OUTPUT)disasm.o: $(srctree)/kernel/bpf/disasm.c |
| 205 | − $(QUIET_CC)$(HOSTCC) $(CFLAGS) -c -MMD $< -o $@ | |
| 208 | + $(QUIET_CC)$(HOSTCC) $(HOST_CFLAGS) -c -MMD $< -o $@ | |
| 206 | 209 | |
| 207 | 210 | $(OUTPUT)disasm.o: $(srctree)/kernel/bpf/disasm.c |
| 208 | 211 | $(QUIET_CC)$(CC) $(CFLAGS) -c -MMD $< -o $@ |
| @@ -213,15 +216,13 @@ ifneq ($(feature-zlib), 1) · 4 unmodified lines | ||
| 213 | 216 | endif |
| 214 | 217 | |
| 215 | 218 | $(BPFTOOL_BOOTSTRAP): $(BOOTSTRAP_OBJS) $(LIBBPF_BOOTSTRAP) |
| 216 | − $(QUIET_LINK)$(HOSTCC) $(CFLAGS) $(LDFLAGS) $(BOOTSTRAP_OBJS) $(LIBS_BOOTSTRAP) -o $@ | |
| 219 | + $(QUIET_LINK)$(HOSTCC) $(HOST_CFLAGS) $(LDFLAGS) $(BOOTSTRAP_OBJS) $(LIBS_BOOTSTRAP) -o $@ | |
| 217 | 220 | |
| 218 | 221 | $(OUTPUT)bpftool: $(OBJS) $(LIBBPF) |
| 219 | 222 | $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) -o $@ |
| 220 | 223 | |
| 221 | 224 | $(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 $@ | |
| 225 | 226 | |
| 226 | 227 | $(OUTPUT)%.o: %.c |
| 227 | 228 | $(QUIET_CC)$(CC) $(CFLAGS) -c -MMD $< -o $@ |
| @@ -642,12 +642,32 @@ probe_helpers_for_progtype(enum bpf_prog_type prog_type, bool supported_type, · 641 unmodified lines | ||
| 642 | 642 | printf("\n"); |
| 643 | 643 | } |
| 644 | 644 | |
| 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) | |
| 647 | 651 | { |
| 652 | + LIBBPF_OPTS(bpf_prog_load_opts, opts, | |
| 653 | + .prog_ifindex = ifindex, | |
| 654 | + ); | |
| 655 | + struct bpf_insn insns[BPF_MAXINSNS + 1]; | |
| 648 | 656 | bool res; |
| 657 | + int i, fd; | |
| 658 | + | |
| 659 | + for (i = 0; i < BPF_MAXINSNS; i++) | |
| 660 | + insns[i] = BPF_MOV64_IMM(BPF_REG_0, 1); | |
| 661 | + insns[BPF_MAXINSNS] = BPF_EXIT_INSN(); | |
| 662 | + | |
| 663 | + errno = 0; | |
| 664 | + fd = bpf_prog_load(BPF_PROG_TYPE_SCHED_CLS, NULL, "GPL", | |
| 665 | + insns, ARRAY_SIZE(insns), &opts); | |
| 666 | + res = fd >= 0 || (errno != E2BIG && errno != EINVAL); | |
| 667 | + | |
| 668 | + if (fd >= 0) | |
| 669 | + close(fd); | |
| 649 | 670 | |
| 650 | − res = bpf_probe_large_insn_limit(ifindex); | |
| 651 | 671 | print_bool_feature("have_large_insn_limit", |
| 652 | 672 | "Large program size limit", |
| 653 | 673 | "LARGE_INSN_LIMIT", |
| @@ -408,6 +408,8 @@ int main(int argc, char **argv) · 407 unmodified lines | ||
| 408 | 408 | bool version_requested = false; |
| 409 | 409 | int opt, ret; |
| 410 | 410 | |
| 411 | + setlinebuf(stdout); | |
| 412 | + | |
| 411 | 413 | last_do_help = do_help; |
| 412 | 414 | pretty_output = false; |
| 413 | 415 | json_output = false; |
| @@ -19,6 +19,7 @@ CC = $(HOSTCC) · 18 unmodified lines | ||
| 19 | 19 | LD = $(HOSTLD) |
| 20 | 20 | ARCH = $(HOSTARCH) |
| 21 | 21 | RM ?= rm |
| 22 | +CROSS_COMPILE = | |
| 22 | 23 | |
| 23 | 24 | OUTPUT ?= $(srctree)/tools/bpf/resolve_btfids/ |
| 24 | 25 | |
| @@ -12,7 +12,7 @@ BPFOBJ := $(BPFOBJ_OUTPUT)libbpf.a · 11 unmodified lines | ||
| 12 | 12 | BPF_DESTDIR := $(BPFOBJ_OUTPUT) |
| 13 | 13 | BPF_INCLUDE := $(BPF_DESTDIR)/include |
| 14 | 14 | INCLUDES := -I$(OUTPUT) -I$(BPF_INCLUDE) -I$(abspath ../../include/uapi) |
| 15 | −CFLAGS := -g -Wall | |
| 15 | +CFLAGS := -g -Wall $(CLANG_CROSS_FLAGS) | |
| 16 | 16 | |
| 17 | 17 | # Try to detect best kernel BTF source |
| 18 | 18 | KERNEL_REL := $(shell uname -r) |
| @@ -88,4 +88,4 @@ $(BPFOBJ): $(wildcard $(LIBBPF_SRC)/*.[ch] $(LIBBPF_SRC)/Makefile) | $(BPFOBJ_OU · 69 unmodified lines | ||
| 88 | 88 | |
| 89 | 89 | $(DEFAULT_BPFTOOL): $(BPFOBJ) | $(BPFTOOL_OUTPUT) |
| 90 | 90 | $(Q)$(MAKE) $(submake_extras) -C ../bpftool OUTPUT=$(BPFTOOL_OUTPUT) \ |
| 91 | − CC=$(HOSTCC) LD=$(HOSTLD) | |
| 91 | + ARCH= CROSS_COMPILE= CC=$(HOSTCC) LD=$(HOSTLD) | |
| @@ -4983,6 +4983,41 @@ union bpf_attr { · 4982 unmodified lines | ||
| 4983 | 4983 | * Return |
| 4984 | 4984 | * The number of loops performed, **-EINVAL** for invalid **flags**, |
| 4985 | 4985 | * **-E2BIG** if **nr_loops** exceeds the maximum number of loops. |
| 4986 | + * | |
| 4987 | + * long bpf_strncmp(const char *s1, u32 s1_sz, const char *s2) | |
| 4988 | + * Description | |
| 4989 | + * Do strncmp() between **s1** and **s2**. **s1** doesn't need | |
| 4990 | + * to be null-terminated and **s1_sz** is the maximum storage | |
| 4991 | + * size of **s1**. **s2** must be a read-only string. | |
| 4992 | + * Return | |
| 4993 | + * An integer less than, equal to, or greater than zero | |
| 4994 | + * if the first **s1_sz** bytes of **s1** is found to be | |
| 4995 | + * less than, to match, or be greater than **s2**. | |
| 4996 | + * | |
| 4997 | + * long bpf_get_func_arg(void *ctx, u32 n, u64 *value) | |
| 4998 | + * Description | |
| 4999 | + * Get **n**-th argument (zero based) of the traced function (for tracing programs) | |
| 5000 | + * returned in **value**. | |
| 5001 | + * | |
| 5002 | + * Return | |
| 5003 | + * 0 on success. | |
| 5004 | + * **-EINVAL** if n >= arguments count of traced function. | |
| 5005 | + * | |
| 5006 | + * long bpf_get_func_ret(void *ctx, u64 *value) | |
| 5007 | + * Description | |
| 5008 | + * Get return value of the traced function (for tracing programs) | |
| 5009 | + * in **value**. | |
| 5010 | + * | |
| 5011 | + * Return | |
| 5012 | + * 0 on success. | |
| 5013 | + * **-EOPNOTSUPP** for tracing programs other than BPF_TRACE_FEXIT or BPF_MODIFY_RETURN. | |
| 5014 | + * | |
| 5015 | + * long bpf_get_func_arg_cnt(void *ctx) | |
| 5016 | + * Description | |
| 5017 | + * Get number of arguments of the traced function (for tracing programs). | |
| 5018 | + * | |
| 5019 | + * Return | |
| 5020 | + * The number of arguments of the traced function. | |
| 4986 | 5021 | */ |
| 4987 | 5022 | #define __BPF_FUNC_MAPPER(FN) \ |
| 4988 | 5023 | FN(unspec), \ |
| @@ -5167,6 +5202,10 @@ union bpf_attr { · 178 unmodified lines | ||
| 5167 | 5202 | FN(kallsyms_lookup_name), \ |
| 5168 | 5203 | FN(find_vma), \ |
| 5169 | 5204 | FN(loop), \ |
| 5205 | + FN(strncmp), \ | |
| 5206 | + FN(get_func_arg), \ | |
| 5207 | + FN(get_func_ret), \ | |
| 5208 | + FN(get_func_arg_cnt), \ | |
| 5170 | 5209 | /* */ |
| 5171 | 5210 | |
| 5172 | 5211 | /* integer value in 'imm' field of BPF_CALL instruction selects which helper |
| @@ -90,6 +90,7 @@ override CFLAGS += -Werror -Wall · 89 unmodified lines | ||
| 90 | 90 | override CFLAGS += $(INCLUDES) |
| 91 | 91 | override CFLAGS += -fvisibility=hidden |
| 92 | 92 | override CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 |
| 93 | +override CFLAGS += $(CLANG_CROSS_FLAGS) | |
| 93 | 94 | |
| 94 | 95 | # flags specific for shared library |
| 95 | 96 | SHLIB_FLAGS := -DSHARED -fPIC |
| @@ -162,7 +163,7 @@ $(BPF_HELPER_DEFS): $(srctree)/tools/include/uapi/linux/bpf.h · 66 unmodified lines | ||
| 162 | 163 | $(OUTPUT)libbpf.so: $(OUTPUT)libbpf.so.$(LIBBPF_VERSION) |
| 163 | 164 | |
| 164 | 165 | $(OUTPUT)libbpf.so.$(LIBBPF_VERSION): $(BPF_IN_SHARED) $(VERSION_SCRIPT) |
| 165 | − $(QUIET_LINK)$(CC) $(LDFLAGS) \ | |
| 166 | + $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) \ | |
| 166 | 167 | --shared -Wl,-soname,libbpf.so.$(LIBBPF_MAJOR_VERSION) \ |
| 167 | 168 | -Wl,--version-script=$(VERSION_SCRIPT) $< -lelf -lz -o $@ |
| 168 | 169 | @ln -sf $(@F) $(OUTPUT)libbpf.so |
| @@ -28,7 +28,9 @@ · 27 unmodified lines | ||
| 28 | 28 | #include <asm/unistd.h> |
| 29 | 29 | #include <errno.h> |
| 30 | 30 | #include <linux/bpf.h> |
| 31 | +#include <linux/filter.h> | |
| 31 | 32 | #include <limits.h> |
| 33 | +#include <sys/resource.h> | |
| 32 | 34 | #include "bpf.h" |
| 33 | 35 | #include "libbpf.h" |
| 34 | 36 | #include "libbpf_internal.h" |
| @@ -94,6 +96,77 @@ static inline int sys_bpf_prog_load(union bpf_attr *attr, unsigned int size, int · 59 unmodified lines | ||
| 94 | 96 | return fd; |
| 95 | 97 | } |
| 96 | 98 | |
| 99 | +/* Probe whether kernel switched from memlock-based (RLIMIT_MEMLOCK) to | |
| 100 | + * memcg-based memory accounting for BPF maps and progs. This was done in [0]. | |
| 101 | + * We use the support for bpf_ktime_get_coarse_ns() helper, which was added in | |
| 102 | + * the same 5.11 Linux release ([1]), to detect memcg-based accounting for BPF. | |
| 103 | + * | |
| 104 | + * [0] https://lore.kernel.org/bpf/20201201215900.3569844-1-guro@fb.com/ | |
| 105 | + * [1] d05512618056 ("bpf: Add bpf_ktime_get_coarse_ns helper") | |
| 106 | + */ | |
| 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 | + | |
| 97 | 170 | int bpf_map_create(enum bpf_map_type map_type, |
| 98 | 171 | const char *map_name, |
| 99 | 172 | __u32 key_size, |
| @@ -105,6 +178,8 @@ int bpf_map_create(enum bpf_map_type map_type, · 5 unmodified lines | ||
| 105 | 178 | union bpf_attr attr; |
| 106 | 179 | int fd; |
| 107 | 180 | |
| 181 | + bump_rlimit_memlock(); | |
| 182 | + | |
| 108 | 183 | memset(&attr, 0, attr_sz); |
| 109 | 184 | |
| 110 | 185 | if (!OPTS_VALID(opts, bpf_map_create_opts)) |
| @@ -112,7 +187,7 @@ int bpf_map_create(enum bpf_map_type map_type, · 1 unmodified line | ||
| 112 | 187 | |
| 113 | 188 | attr.map_type = map_type; |
| 114 | 189 | if (map_name) |
| 115 | − strncat(attr.map_name, map_name, sizeof(attr.map_name) - 1); | |
| 190 | + libbpf_strlcpy(attr.map_name, map_name, sizeof(attr.map_name)); | |
| 116 | 191 | attr.key_size = key_size; |
| 117 | 192 | attr.value_size = value_size; |
| 118 | 193 | attr.max_entries = max_entries; |
| @@ -251,6 +326,8 @@ int bpf_prog_load_v0_6_0(enum bpf_prog_type prog_type, · 132 unmodified lines | ||
| 251 | 326 | union bpf_attr attr; |
| 252 | 327 | char *log_buf; |
| 253 | 328 | |
| 329 | + bump_rlimit_memlock(); | |
| 330 | + | |
| 254 | 331 | if (!OPTS_VALID(opts, bpf_prog_load_opts)) |
| 255 | 332 | return libbpf_err(-EINVAL); |
| 256 | 333 | |
| @@ -271,7 +348,7 @@ int bpf_prog_load_v0_6_0(enum bpf_prog_type prog_type, · 14 unmodified lines | ||
| 271 | 348 | attr.kern_version = OPTS_GET(opts, kern_version, 0); |
| 272 | 349 | |
| 273 | 350 | if (prog_name) |
| 274 | − strncat(attr.prog_name, prog_name, sizeof(attr.prog_name) - 1); | |
| 351 | + libbpf_strlcpy(attr.prog_name, prog_name, sizeof(attr.prog_name)); | |
| 275 | 352 | attr.license = ptr_to_u64(license); |
| 276 | 353 | |
| 277 | 354 | if (insn_cnt > UINT_MAX) |
| @@ -456,6 +533,8 @@ int bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns, · 178 unmodified lines | ||
| 456 | 533 | union bpf_attr attr; |
| 457 | 534 | int fd; |
| 458 | 535 | |
| 536 | + bump_rlimit_memlock(); | |
| 537 | + | |
| 459 | 538 | memset(&attr, 0, sizeof(attr)); |
| 460 | 539 | attr.prog_type = type; |
| 461 | 540 | attr.insn_cnt = (__u32)insns_cnt; |
| @@ -1056,6 +1135,8 @@ int bpf_btf_load(const void *btf_data, size_t btf_size, const struct bpf_btf_loa · 594 unmodified lines | ||
| 1056 | 1135 | __u32 log_level; |
| 1057 | 1136 | int fd; |
| 1058 | 1137 | |
| 1138 | + bump_rlimit_memlock(); | |
| 1139 | + | |
| 1059 | 1140 | memset(&attr, 0, attr_sz); |
| 1060 | 1141 | |
| 1061 | 1142 | if (!OPTS_VALID(opts, bpf_btf_load_opts)) |
| @@ -35,6 +35,8 @@ · 34 unmodified lines | ||
| 35 | 35 | extern "C" { |
| 36 | 36 | #endif |
| 37 | 37 | |
| 38 | +int libbpf_set_memlock_rlim(size_t memlock_bytes); | |
| 39 | + | |
| 38 | 40 | struct bpf_map_create_opts { |
| 39 | 41 | size_t sz; /* size of this struct for forward/backward compatibility */ |
| 40 | 42 | |
| @@ -66,277 +66,204 @@ · 65 unmodified lines | ||
| 66 | 66 | |
| 67 | 67 | #if defined(__KERNEL__) || defined(__VMLINUX_H__) |
| 68 | 68 | |
| 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 | |
| 90 | 79 | |
| 91 | 80 | #else |
| 92 | 81 | |
| 93 | 82 | #ifdef __i386__ |
| 94 | −/* i386 kernel is built with -mregparm=3 */ | |
| 95 | −#define PT_REGS_PARM1(x) ((x)->eax) | |
| 96 | −#define PT_REGS_PARM2(x) ((x)->edx) | |
| 97 | −#define PT_REGS_PARM3(x) ((x)->ecx) | |
| 98 | −#define PT_REGS_PARM4(x) 0 | |
| 99 | −#define PT_REGS_PARM5(x) 0 | |
| 100 | −#define PT_REGS_RET(x) ((x)->esp) | |
| 101 | −#define PT_REGS_FP(x) ((x)->ebp) | |
| 102 | −#define PT_REGS_RC(x) ((x)->eax) | |
| 103 | −#define PT_REGS_SP(x) ((x)->esp) | |
| 104 | −#define PT_REGS_IP(x) ((x)->eip) | |
| 105 | − | |
| 106 | −#define PT_REGS_PARM1_CORE(x) BPF_CORE_READ((x), eax) | |
| 107 | −#define PT_REGS_PARM2_CORE(x) BPF_CORE_READ((x), edx) | |
| 108 | −#define PT_REGS_PARM3_CORE(x) BPF_CORE_READ((x), ecx) | |
| 109 | −#define PT_REGS_PARM4_CORE(x) 0 | |
| 110 | −#define PT_REGS_PARM5_CORE(x) 0 | |
| 111 | −#define PT_REGS_RET_CORE(x) BPF_CORE_READ((x), esp) | |
| 112 | −#define PT_REGS_FP_CORE(x) BPF_CORE_READ((x), ebp) | |
| 113 | −#define PT_REGS_RC_CORE(x) BPF_CORE_READ((x), eax) | |
| 114 | −#define PT_REGS_SP_CORE(x) BPF_CORE_READ((x), esp) | |
| 115 | −#define PT_REGS_IP_CORE(x) BPF_CORE_READ((x), eip) | |
| 116 | − | |
| 117 | −#else | |
| 118 | 83 | |
| 119 | −#define PT_REGS_PARM1(x) ((x)->rdi) | |
| 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__ */ | |
| 143 | 112 | |
| 144 | 113 | #elif defined(bpf_target_s390) |
| 145 | 114 | |
| 146 | 115 | /* 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 | |
| 171 | 127 | |
| 172 | 128 | #elif defined(bpf_target_arm) |
| 173 | 129 | |
| 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] | |
| 195 | 140 | |
| 196 | 141 | #elif defined(bpf_target_arm64) |
| 197 | 142 | |
| 198 | 143 | /* 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 | |
| 223 | 155 | |
| 224 | 156 | #elif defined(bpf_target_mips) |
| 225 | 157 | |
| 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 | |
| 247 | 168 | |
| 248 | 169 | #elif defined(bpf_target_powerpc) |
| 249 | 170 | |
| 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 | |
| 267 | 181 | |
| 268 | 182 | #elif defined(bpf_target_sparc) |
| 269 | 183 | |
| 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] | |
| 288 | 193 | /* Should this also be a bpf_target check for the sparc case? */ |
| 289 | 194 | #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 | |
| 292 | 196 | #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 | |
| 295 | 198 | #endif |
| 296 | 199 | |
| 297 | 200 | #elif defined(bpf_target_riscv) |
| 298 | 201 | |
| 202 | +#define __PT_REGS_CAST(x) ((const struct user_regs_struct *)(x)) | |
| 203 | +#define __PT_PARM1_REG a0 | |
| 204 | +#define __PT_PARM2_REG a1 | |
| 205 | +#define __PT_PARM3_REG a2 | |
| 206 | +#define __PT_PARM4_REG a3 | |
| 207 | +#define __PT_PARM5_REG a4 | |
| 208 | +#define __PT_RET_REG ra | |
| 209 | +#define __PT_FP_REG fp | |
| 210 | +#define __PT_RC_REG a5 | |
| 211 | +#define __PT_SP_REG sp | |
| 212 | +#define __PT_IP_REG epc | |
| 213 | + | |
| 214 | +#endif | |
| 215 | + | |
| 216 | +#if defined(bpf_target_defined) | |
| 217 | + | |
| 299 | 218 | 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) | |
| 322 | 219 | |
| 220 | +/* allow some architecutres to override `struct pt_regs` */ | |
| 221 | +#ifndef __PT_REGS_CAST | |
| 222 | +#define __PT_REGS_CAST(x) (x) | |
| 323 | 223 | #endif |
| 324 | 224 | |
| 225 | +#define PT_REGS_PARM1(x) (__PT_REGS_CAST(x)->__PT_PARM1_REG) | |
| 226 | +#define PT_REGS_PARM2(x) (__PT_REGS_CAST(x)->__PT_PARM2_REG) | |
| 227 | +#define PT_REGS_PARM3(x) (__PT_REGS_CAST(x)->__PT_PARM3_REG) | |
| 228 | +#define PT_REGS_PARM4(x) (__PT_REGS_CAST(x)->__PT_PARM4_REG) | |
| 229 | +#define PT_REGS_PARM5(x) (__PT_REGS_CAST(x)->__PT_PARM5_REG) | |
| 230 | +#define PT_REGS_RET(x) (__PT_REGS_CAST(x)->__PT_RET_REG) | |
| 231 | +#define PT_REGS_FP(x) (__PT_REGS_CAST(x)->__PT_FP_REG) | |
| 232 | +#define PT_REGS_RC(x) (__PT_REGS_CAST(x)->__PT_RC_REG) | |
| 233 | +#define PT_REGS_SP(x) (__PT_REGS_CAST(x)->__PT_SP_REG) | |
| 234 | +#define PT_REGS_IP(x) (__PT_REGS_CAST(x)->__PT_IP_REG) | |
| 235 | + | |
| 236 | +#define PT_REGS_PARM1_CORE(x) BPF_CORE_READ(__PT_REGS_CAST(x), __PT_PARM1_REG) | |
| 237 | +#define PT_REGS_PARM2_CORE(x) BPF_CORE_READ(__PT_REGS_CAST(x), __PT_PARM2_REG) | |
| 238 | +#define PT_REGS_PARM3_CORE(x) BPF_CORE_READ(__PT_REGS_CAST(x), __PT_PARM3_REG) | |
| 239 | +#define PT_REGS_PARM4_CORE(x) BPF_CORE_READ(__PT_REGS_CAST(x), __PT_PARM4_REG) | |
| 240 | +#define PT_REGS_PARM5_CORE(x) BPF_CORE_READ(__PT_REGS_CAST(x), __PT_PARM5_REG) | |
| 241 | +#define PT_REGS_RET_CORE(x) BPF_CORE_READ(__PT_REGS_CAST(x), __PT_RET_REG) | |
| 242 | +#define PT_REGS_FP_CORE(x) BPF_CORE_READ(__PT_REGS_CAST(x), __PT_FP_REG) | |
| 243 | +#define PT_REGS_RC_CORE(x) BPF_CORE_READ(__PT_REGS_CAST(x), __PT_RC_REG) | |
| 244 | +#define PT_REGS_SP_CORE(x) BPF_CORE_READ(__PT_REGS_CAST(x), __PT_SP_REG) | |
| 245 | +#define PT_REGS_IP_CORE(x) BPF_CORE_READ(__PT_REGS_CAST(x), __PT_IP_REG) | |
| 246 | + | |
| 325 | 247 | #if defined(bpf_target_powerpc) |
| 248 | + | |
| 326 | 249 | #define BPF_KPROBE_READ_RET_IP(ip, ctx) ({ (ip) = (ctx)->link; }) |
| 327 | 250 | #define BPF_KRETPROBE_READ_RET_IP BPF_KPROBE_READ_RET_IP |
| 251 | + | |
| 328 | 252 | #elif defined(bpf_target_sparc) |
| 253 | + | |
| 329 | 254 | #define BPF_KPROBE_READ_RET_IP(ip, ctx) ({ (ip) = PT_REGS_RET(ctx); }) |
| 330 | 255 | #define BPF_KRETPROBE_READ_RET_IP BPF_KPROBE_READ_RET_IP |
| 331 | −#elif defined(bpf_target_defined) | |
| 256 | + | |
| 257 | +#else | |
| 258 | + | |
| 332 | 259 | #define BPF_KPROBE_READ_RET_IP(ip, ctx) \ |
| 333 | 260 | ({ bpf_probe_read_kernel(&(ip), sizeof(ip), (void *)PT_REGS_RET(ctx)); }) |
| 334 | 261 | #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 | + | |
| 337 | 264 | #endif |
| 338 | 265 | |
| 339 | −#if !defined(bpf_target_defined) | |
| 266 | +#else /* defined(bpf_target_defined) */ | |
| 340 | 267 | |
| 341 | 268 | #define PT_REGS_PARM1(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; }) |
| 342 | 269 | #define PT_REGS_PARM2(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; }) |
| @@ -363,7 +290,7 @@ struct pt_regs; · 20 unmodified lines | ||
| 363 | 290 | #define BPF_KPROBE_READ_RET_IP(ip, ctx) ({ _Pragma(__BPF_TARGET_MISSING); 0l; }) |
| 364 | 291 | #define BPF_KRETPROBE_READ_RET_IP(ip, ctx) ({ _Pragma(__BPF_TARGET_MISSING); 0l; }) |
| 365 | 292 | |
| 366 | −#endif /* !defined(bpf_target_defined) */ | |
| 293 | +#endif /* defined(bpf_target_defined) */ | |
| 367 | 294 | |
| 368 | 295 | #ifndef ___bpf_concat |
| 369 | 296 | #define ___bpf_concat(a, b) a ## b |
| @@ -375,25 +302,23 @@ struct pt_regs; · 5 unmodified lines | ||
| 375 | 302 | #define ___bpf_nth(_, _1, _2, _3, _4, _5, _6, _7, _8, _9, _a, _b, _c, N, ...) N |
| 376 | 303 | #endif |
| 377 | 304 | #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) | |
| 380 | 306 | #endif |
| 381 | 307 | |
| 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] | |
| 392 | 318 | #define ___bpf_ctx_cast10(x, args...) ___bpf_ctx_cast9(args), (void *)ctx[9] |
| 393 | 319 | #define ___bpf_ctx_cast11(x, args...) ___bpf_ctx_cast10(args), (void *)ctx[10] |
| 394 | 320 | #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) | |
| 397 | 322 | |
| 398 | 323 | /* |
| 399 | 324 | * BPF_PROG is a convenience wrapper for generic tp_btf/fentry/fexit and |
| @@ -426,19 +351,13 @@ ____##name(unsigned long long *ctx, ##args) · 26 unmodified lines | ||
| 426 | 351 | |
| 427 | 352 | struct pt_regs; |
| 428 | 353 | |
| 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) | |
| 442 | 361 | |
| 443 | 362 | /* |
| 444 | 363 | * 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 | ||
| 464 | 383 | static __attribute__((always_inline)) typeof(name(0)) \ |
| 465 | 384 | ____##name(struct pt_regs *ctx, ##args) |
| 466 | 385 | |
| 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) | |
| 472 | 389 | |
| 473 | 390 | /* |
| 474 | 391 | * BPF_KRETPROBE is similar to BPF_KPROBE, except, it only provides optional |
| @@ -313,12 +313,18 @@ LIBBPF_API struct btf_dump *btf_dump__new_deprecated(const struct btf *btf, · 312 unmodified lines | ||
| 313 | 313 | * |
| 314 | 314 | * The rest works just like in case of ___libbpf_override() usage with symbol |
| 315 | 315 | * versioning. |
| 316 | + * | |
| 317 | + * C++ compilers don't support __builtin_types_compatible_p(), so at least | |
| 318 | + * don't screw up compilation for them and let C++ users pick btf_dump__new | |
| 319 | + * vs btf_dump__new_deprecated explicitly. | |
| 316 | 320 | */ |
| 321 | +#ifndef __cplusplus | |
| 317 | 322 | #define btf_dump__new(a1, a2, a3, a4) __builtin_choose_expr( \ |
| 318 | 323 | __builtin_types_compatible_p(typeof(a4), btf_dump_printf_fn_t) || \ |
| 319 | 324 | __builtin_types_compatible_p(typeof(a4), void(void *, const char *, va_list)), \ |
| 320 | 325 | btf_dump__new_deprecated((void *)a1, (void *)a2, (void *)a3, (void *)a4), \ |
| 321 | 326 | btf_dump__new((void *)a1, (void *)a2, (void *)a3, (void *)a4)) |
| 327 | +#endif | |
| 322 | 328 | |
| 323 | 329 | LIBBPF_API void btf_dump__free(struct btf_dump *d); |
| 324 | 330 | |
| @@ -2321,8 +2321,8 @@ int btf_dump__dump_type_data(struct btf_dump *d, __u32 id, · 2320 unmodified lines | ||
| 2321 | 2321 | if (!opts->indent_str) |
| 2322 | 2322 | d->typed_dump->indent_str[0] = '\t'; |
| 2323 | 2323 | 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)); | |
| 2326 | 2326 | |
| 2327 | 2327 | d->typed_dump->compact = OPTS_GET(opts, compact, false); |
| 2328 | 2328 | d->typed_dump->skip_names = OPTS_GET(opts, skip_names, false); |
| @@ -371,8 +371,9 @@ int bpf_gen__finish(struct bpf_gen *gen, int nr_progs, int nr_maps) · 370 unmodified lines | ||
| 371 | 371 | { |
| 372 | 372 | int i; |
| 373 | 373 | |
| 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); | |
| 376 | 377 | gen->error = -EFAULT; |
| 377 | 378 | return gen->error; |
| 378 | 379 | } |
| @@ -462,8 +463,7 @@ void bpf_gen__map_create(struct bpf_gen *gen, · 83 unmodified lines | ||
| 462 | 463 | attr.map_flags = map_attr->map_flags; |
| 463 | 464 | attr.map_extra = map_attr->map_extra; |
| 464 | 465 | 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)); | |
| 467 | 467 | attr.numa_node = map_attr->numa_node; |
| 468 | 468 | attr.map_ifindex = map_attr->map_ifindex; |
| 469 | 469 | attr.max_entries = max_entries; |
| @@ -969,8 +969,7 @@ void bpf_gen__prog_load(struct bpf_gen *gen, · 499 unmodified lines | ||
| 969 | 969 | core_relos = add_data(gen, gen->core_relos, |
| 970 | 970 | attr.core_relo_cnt * attr.core_relo_rec_size); |
| 971 | 971 | |
| 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)); | |
| 974 | 973 | prog_load_attr = add_data(gen, &attr, attr_size); |
| 975 | 974 | |
| 976 | 975 | /* populate union bpf_attr with a pointer to license */ |
| @@ -187,42 +187,6 @@ const char *libbpf_version_string(void) · 186 unmodified lines | ||
| 187 | 187 | #undef __S |
| 188 | 188 | } |
| 189 | 189 | |
| 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 | − | |
| 226 | 190 | enum reloc_type { |
| 227 | 191 | RELO_LD64, |
| 228 | 192 | RELO_CALL, |
| @@ -831,11 +795,36 @@ bpf_object__add_programs(struct bpf_object *obj, Elf_Data *sec_data, · 602 unmodified lines | ||
| 831 | 795 | return 0; |
| 832 | 796 | } |
| 833 | 797 | |
| 834 | −static __u32 get_kernel_version(void) | |
| 798 | +__u32 get_kernel_version(void) | |
| 835 | 799 | { |
| 800 | + /* On Ubuntu LINUX_VERSION_CODE doesn't correspond to info.release, | |
| 801 | + * but Ubuntu provides /proc/version_signature file, as described at | |
| 802 | + * https://ubuntu.com/kernel, with an example contents below, which we | |
| 803 | + * can use to get a proper LINUX_VERSION_CODE. | |
| 804 | + * | |
| 805 | + * Ubuntu 5.4.0-12.15-generic 5.4.8 | |
| 806 | + * | |
| 807 | + * In the above, 5.4.8 is what kernel is actually expecting, while | |
| 808 | + * uname() call will return 5.4.0 in info.release. | |
| 809 | + */ | |
| 810 | + const char *ubuntu_kver_file = "/proc/version_signature"; | |
| 836 | 811 | __u32 major, minor, patch; |
| 837 | 812 | struct utsname info; |
| 838 | 813 | |
| 814 | + if (access(ubuntu_kver_file, R_OK) == 0) { | |
| 815 | + FILE *f; | |
| 816 | + | |
| 817 | + f = fopen(ubuntu_kver_file, "r"); | |
| 818 | + if (f) { | |
| 819 | + if (fscanf(f, "%*s %*s %d.%d.%d\n", &major, &minor, &patch) == 3) { | |
| 820 | + fclose(f); | |
| 821 | + return KERNEL_VERSION(major, minor, patch); | |
| 822 | + } | |
| 823 | + fclose(f); | |
| 824 | + } | |
| 825 | + /* something went wrong, fall back to uname() approach */ | |
| 826 | + } | |
| 827 | + | |
| 839 | 828 | uname(&info); |
| 840 | 829 | if (sscanf(info.release, "%u.%u.%u", &major, &minor, &patch) != 3) |
| 841 | 830 | return 0; |
| @@ -1201,12 +1190,10 @@ static struct bpf_object *bpf_object__new(const char *path, · 359 unmodified lines | ||
| 1201 | 1190 | |
| 1202 | 1191 | strcpy(obj->path, path); |
| 1203 | 1192 | 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)); | |
| 1206 | 1194 | } else { |
| 1207 | 1195 | /* 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)); | |
| 1210 | 1197 | end = strchr(obj->name, '.'); |
| 1211 | 1198 | if (end) |
| 1212 | 1199 | *end = 0; |
| @@ -1358,7 +1345,10 @@ static int bpf_object__check_endianness(struct bpf_object *obj) · 145 unmodified lines | ||
| 1358 | 1345 | static int |
| 1359 | 1346 | bpf_object__init_license(struct bpf_object *obj, void *data, size_t size) |
| 1360 | 1347 | { |
| 1361 | − memcpy(obj->license, data, min(size, sizeof(obj->license) - 1)); | |
| 1348 | + /* libbpf_strlcpy() only copies first N - 1 bytes, so size + 1 won't | |
| 1349 | + * go over allowed ELF data section buffer | |
| 1350 | + */ | |
| 1351 | + libbpf_strlcpy(obj->license, data, min(size + 1, sizeof(obj->license))); | |
| 1362 | 1352 | pr_debug("license of %s is %s\n", obj->path, obj->license); |
| 1363 | 1353 | return 0; |
| 1364 | 1354 | } |
| @@ -4354,6 +4344,10 @@ bpf_object__probe_loading(struct bpf_object *obj) · 2989 unmodified lines | ||
| 4354 | 4344 | if (obj->gen_loader) |
| 4355 | 4345 | return 0; |
| 4356 | 4346 | |
| 4347 | + ret = bump_rlimit_memlock(); | |
| 4348 | + if (ret) | |
| 4349 | + pr_warn("Failed to bump RLIMIT_MEMLOCK (err = %d), you might need to do it explicitly!\n", ret); | |
| 4350 | + | |
| 4357 | 4351 | /* make sure basic loading works */ |
| 4358 | 4352 | ret = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, NULL, "GPL", insns, insn_cnt, NULL); |
| 4359 | 4353 | if (ret < 0) |
| @@ -4720,14 +4714,17 @@ static struct kern_feature_desc { · 360 unmodified lines | ||
| 4720 | 4714 | [FEAT_BTF_TYPE_TAG] = { |
| 4721 | 4715 | "BTF_KIND_TYPE_TAG support", probe_kern_btf_type_tag, |
| 4722 | 4716 | }, |
| 4717 | + [FEAT_MEMCG_ACCOUNT] = { | |
| 4718 | + "memcg-based memory accounting", probe_memcg_account, | |
| 4719 | + }, | |
| 4723 | 4720 | }; |
| 4724 | 4721 | |
| 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) | |
| 4726 | 4723 | { |
| 4727 | 4724 | struct kern_feature_desc *feat = &feature_probes[feat_id]; |
| 4728 | 4725 | int ret; |
| 4729 | 4726 | |
| 4730 | − if (obj->gen_loader) | |
| 4727 | + if (obj && obj->gen_loader) | |
| 4731 | 4728 | /* To generate loader program assume the latest kernel |
| 4732 | 4729 | * to avoid doing extra prog_load, map_create syscalls. |
| 4733 | 4730 | */ |
| @@ -227,6 +227,7 @@ struct btf; · 226 unmodified lines | ||
| 227 | 227 | LIBBPF_API struct btf *bpf_object__btf(const struct bpf_object *obj); |
| 228 | 228 | LIBBPF_API int bpf_object__btf_fd(const struct bpf_object *obj); |
| 229 | 229 | |
| 230 | +LIBBPF_DEPRECATED_SINCE(0, 7, "use bpf_object__find_program_by_name() instead") | |
| 230 | 231 | LIBBPF_API struct bpf_program * |
| 231 | 232 | bpf_object__find_program_by_title(const struct bpf_object *obj, |
| 232 | 233 | const char *title); |
| @@ -339,7 +340,31 @@ LIBBPF_DEPRECATED_SINCE(0, 7, "multi-instance bpf_program support is deprecated" · 106 unmodified lines | ||
| 339 | 340 | LIBBPF_API int bpf_program__unpin_instance(struct bpf_program *prog, |
| 340 | 341 | const char *path, |
| 341 | 342 | int instance); |
| 343 | + | |
| 344 | +/** | |
| 345 | + * @brief **bpf_program__pin()** pins the BPF program to a file | |
| 346 | + * in the BPF FS specified by a path. This increments the programs | |
| 347 | + * reference count, allowing it to stay loaded after the process | |
| 348 | + * which loaded it has exited. | |
| 349 | + * | |
| 350 | + * @param prog BPF program to pin, must already be loaded | |
| 351 | + * @param path file path in a BPF file system | |
| 352 | + * @return 0, on success; negative error code, otherwise | |
| 353 | + */ | |
| 342 | 354 | 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 | + */ | |
| 343 | 368 | LIBBPF_API int bpf_program__unpin(struct bpf_program *prog, const char *path); |
| 344 | 369 | LIBBPF_API void bpf_program__unload(struct bpf_program *prog); |
| 345 | 370 | |
| @@ -1027,13 +1052,57 @@ bpf_prog_linfo__lfind(const struct bpf_prog_linfo *prog_linfo, · 681 unmodified lines | ||
| 1027 | 1052 | * user, causing subsequent probes to fail. In this case, the caller may want |
| 1028 | 1053 | * to adjust that limit with setrlimit(). |
| 1029 | 1054 | */ |
| 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") | |
| 1032 | 1058 | 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") | |
| 1035 | 1062 | LIBBPF_API bool bpf_probe_large_insn_limit(__u32 ifindex); |
| 1036 | 1063 | |
| 1064 | +/** | |
| 1065 | + * @brief **libbpf_probe_bpf_prog_type()** detects if host kernel supports | |
| 1066 | + * BPF programs of a given type. | |
| 1067 | + * @param prog_type BPF program type to detect kernel support for | |
| 1068 | + * @param opts reserved for future extensibility, should be NULL | |
| 1069 | + * @return 1, if given program type is supported; 0, if given program type is | |
| 1070 | + * not supported; negative error code if feature detection failed or can't be | |
| 1071 | + * performed | |
| 1072 | + * | |
| 1073 | + * Make sure the process has required set of CAP_* permissions (or runs as | |
| 1074 | + * root) when performing feature checking. | |
| 1075 | + */ | |
| 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 | + | |
| 1037 | 1106 | /* |
| 1038 | 1107 | * Get bpf_prog_info in continuous memory |
| 1039 | 1108 | * |
| @@ -427,4 +427,8 @@ LIBBPF_0.7.0 { · 426 unmodified lines | ||
| 427 | 427 | bpf_program__log_level; |
| 428 | 428 | bpf_program__set_log_buf; |
| 429 | 429 | bpf_program__set_log_level; |
| 430 | + libbpf_probe_bpf_helper; | |
| 431 | + libbpf_probe_bpf_map_type; | |
| 432 | + libbpf_probe_bpf_prog_type; | |
| 433 | + libbpf_set_memlock_rlim_max; | |
| 430 | 434 | }; |
| @@ -169,6 +169,27 @@ static inline void *libbpf_reallocarray(void *ptr, size_t nmemb, size_t size) · 168 unmodified lines | ||
| 169 | 169 | return realloc(ptr, total); |
| 170 | 170 | } |
| 171 | 171 | |
| 172 | +/* Copy up to sz - 1 bytes from zero-terminated src string and ensure that dst | |
| 173 | + * is zero-terminated string no matter what (unless sz == 0, in which case | |
| 174 | + * it's a no-op). It's conceptually close to FreeBSD's strlcpy(), but differs | |
| 175 | + * in what is returned. Given this is internal helper, it's trivial to extend | |
| 176 | + * this, when necessary. Use this instead of strncpy inside libbpf source code. | |
| 177 | + */ | |
| 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 | + | |
| 172 | 193 | struct btf; |
| 173 | 194 | struct btf_type; |
| 174 | 195 | |
| @@ -272,6 +293,45 @@ static inline bool libbpf_validate_opts(const char *opts, · 97 unmodified lines | ||
| 272 | 293 | (opts)->sz - __off); \ |
| 273 | 294 | }) |
| 274 | 295 | |
| 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); | |
| 275 | 335 | |
| 276 | 336 | int parse_cpu_mask_str(const char *s, bool **mask, int *mask_sz); |
| 277 | 337 | int parse_cpu_mask_file(const char *fcpu, bool **mask, int *mask_sz); |
| @@ -45,7 +45,6 @@ enum libbpf_strict_mode { · 44 unmodified lines | ||
| 45 | 45 | * (positive) error code. |
| 46 | 46 | */ |
| 47 | 47 | LIBBPF_STRICT_DIRECT_ERRS = 0x02, |
| 48 | − | |
| 49 | 48 | /* |
| 50 | 49 | * Enforce strict BPF program section (SEC()) names. |
| 51 | 50 | * E.g., while prefiously SEC("xdp_whatever") or SEC("perf_event_blah") were |
| @@ -63,6 +62,17 @@ enum libbpf_strict_mode { · 11 unmodified lines | ||
| 63 | 62 | * Clients can maintain it on their own if it is valuable for them. |
| 64 | 63 | */ |
| 65 | 64 | LIBBPF_STRICT_NO_OBJECT_LIST = 0x08, |
| 65 | + /* | |
| 66 | + * Automatically bump RLIMIT_MEMLOCK using setrlimit() before the | |
| 67 | + * first BPF program or map creation operation. This is done only if | |
| 68 | + * kernel is too old to support memcg-based memory accounting for BPF | |
| 69 | + * subsystem. By default, RLIMIT_MEMLOCK limit is set to RLIM_INFINITY, | |
| 70 | + * but it can be overriden with libbpf_set_memlock_rlim_max() API. | |
| 71 | + * Note that libbpf_set_memlock_rlim_max() needs to be called before | |
| 72 | + * the very first bpf_prog_load(), bpf_map_create() or bpf_object__load() | |
| 73 | + * operation. | |
| 74 | + */ | |
| 75 | + LIBBPF_STRICT_AUTO_RLIMIT_MEMLOCK = 0x10, | |
| 66 | 76 | |
| 67 | 77 | __LIBBPF_STRICT_LAST, |
| 68 | 78 | }; |
| @@ -48,28 +48,20 @@ static int get_vendor_id(int ifindex) · 47 unmodified lines | ||
| 48 | 48 | return strtol(buf, NULL, 0); |
| 49 | 49 | } |
| 50 | 50 | |
| 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) | |
| 52 | 55 | { |
| 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]; | |
| 73 | 65 | |
| 74 | 66 | switch (prog_type) { |
| 75 | 67 | case BPF_PROG_TYPE_CGROUP_SOCK_ADDR: |
| @@ -84,6 +76,38 @@ probe_load(enum bpf_prog_type prog_type, const struct bpf_insn *insns, · 8 unmodified lines | ||
| 84 | 76 | case BPF_PROG_TYPE_KPROBE: |
| 85 | 77 | opts.kern_version = get_kernel_version(); |
| 86 | 78 | break; |
| 79 | + case BPF_PROG_TYPE_LIRC_MODE2: | |
| 80 | + opts.expected_attach_type = BPF_LIRC_MODE2; | |
| 81 | + break; | |
| 82 | + case BPF_PROG_TYPE_TRACING: | |
| 83 | + case BPF_PROG_TYPE_LSM: | |
| 84 | + opts.log_buf = buf; | |
| 85 | + opts.log_size = sizeof(buf); | |
| 86 | + opts.log_level = 1; | |
| 87 | + if (prog_type == BPF_PROG_TYPE_TRACING) | |
| 88 | + opts.expected_attach_type = BPF_TRACE_FENTRY; | |
| 89 | + else | |
| 90 | + opts.expected_attach_type = BPF_MODIFY_RETURN; | |
| 91 | + opts.attach_btf_id = 1; | |
| 92 | + | |
| 93 | + exp_err = -EINVAL; | |
| 94 | + exp_msg = "attach_btf_id 1 is not a function"; | |
| 95 | + break; | |
| 96 | + case BPF_PROG_TYPE_EXT: | |
| 97 | + opts.log_buf = buf; | |
| 98 | + opts.log_size = sizeof(buf); | |
| 99 | + opts.log_level = 1; | |
| 100 | + opts.attach_btf_id = 1; | |
| 101 | + | |
| 102 | + exp_err = -EINVAL; | |
| 103 | + exp_msg = "Cannot replace kernel functions"; | |
| 104 | + break; | |
| 105 | + case BPF_PROG_TYPE_SYSCALL: | |
| 106 | + opts.prog_flags = BPF_F_SLEEPABLE; | |
| 107 | + break; | |
| 108 | + case BPF_PROG_TYPE_STRUCT_OPS: | |
| 109 | + exp_err = -524; /* -ENOTSUPP */ | |
| 110 | + break; | |
| 87 | 111 | case BPF_PROG_TYPE_UNSPEC: |
| 88 | 112 | case BPF_PROG_TYPE_SOCKET_FILTER: |
| 89 | 113 | case BPF_PROG_TYPE_SCHED_CLS: |
| @@ -103,25 +127,42 @@ probe_load(enum bpf_prog_type prog_type, const struct bpf_insn *insns, · 13 unmodified lines | ||
| 103 | 127 | case BPF_PROG_TYPE_RAW_TRACEPOINT: |
| 104 | 128 | case BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE: |
| 105 | 129 | case BPF_PROG_TYPE_LWT_SEG6LOCAL: |
| 106 | − case BPF_PROG_TYPE_LIRC_MODE2: | |
| 107 | 130 | case BPF_PROG_TYPE_SK_REUSEPORT: |
| 108 | 131 | case BPF_PROG_TYPE_FLOW_DISSECTOR: |
| 109 | 132 | case BPF_PROG_TYPE_CGROUP_SYSCTL: |
| 110 | − case BPF_PROG_TYPE_TRACING: | |
| 111 | − case BPF_PROG_TYPE_STRUCT_OPS: | |
| 112 | − case BPF_PROG_TYPE_EXT: | |
| 113 | − case BPF_PROG_TYPE_LSM: | |
| 114 | − default: | |
| 115 | 133 | break; |
| 134 | + default: | |
| 135 | + return -EOPNOTSUPP; | |
| 116 | 136 | } |
| 117 | 137 | |
| 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; | |
| 123 | 140 | if (fd >= 0) |
| 124 | 141 | close(fd); |
| 142 | + if (exp_err) { | |
| 143 | + if (fd >= 0 || err != exp_err) | |
| 144 | + return 0; | |
| 145 | + if (exp_msg && !strstr(buf, exp_msg)) | |
| 146 | + return 0; | |
| 147 | + return 1; | |
| 148 | + } | |
| 149 | + return fd >= 0 ? 1 : 0; | |
| 150 | +} | |
| 151 | + | |
| 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); | |
| 125 | 166 | } |
| 126 | 167 | |
| 127 | 168 | 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 | ||
| 131 | 172 | BPF_EXIT_INSN() |
| 132 | 173 | }; |
| 133 | 174 | |
| 175 | + /* prefer libbpf_probe_bpf_prog_type() unless offload is requested */ | |
| 176 | + if (ifindex == 0) | |
| 177 | + return libbpf_probe_bpf_prog_type(prog_type, NULL) == 1; | |
| 178 | + | |
| 134 | 179 | if (ifindex && prog_type == BPF_PROG_TYPE_SCHED_CLS) |
| 135 | 180 | /* nfp returns -EINVAL on exit(0) with TC offload */ |
| 136 | 181 | insns[0].imm = 2; |
| 137 | 182 | |
| 138 | 183 | errno = 0; |
| 139 | − probe_load(prog_type, insns, ARRAY_SIZE(insns), NULL, 0, ifindex); | |
| 184 | + probe_prog_load(prog_type, insns, ARRAY_SIZE(insns), NULL, 0, ifindex); | |
| 140 | 185 | |
| 141 | 186 | return errno != EINVAL && errno != EOPNOTSUPP; |
| 142 | 187 | } |
| @@ -197,16 +242,18 @@ static int load_local_storage_btf(void) · 54 unmodified lines | ||
| 197 | 242 | strs, sizeof(strs)); |
| 198 | 243 | } |
| 199 | 244 | |
| 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) | |
| 201 | 246 | { |
| 202 | − int key_size, value_size, max_entries, map_flags; | |
| 247 | + LIBBPF_OPTS(bpf_map_create_opts, opts); | |
| 248 | + int key_size, value_size, max_entries; | |
| 203 | 249 | __u32 btf_key_type_id = 0, btf_value_type_id = 0; |
| 204 | − int fd = -1, btf_fd = -1, fd_inner; | |
| 250 | + int fd = -1, btf_fd = -1, fd_inner = -1, exp_err = 0, err; | |
| 251 | + | |
| 252 | + opts.map_ifindex = ifindex; | |
| 205 | 253 | |
| 206 | 254 | key_size = sizeof(__u32); |
| 207 | 255 | value_size = sizeof(__u32); |
| 208 | 256 | max_entries = 1; |
| 209 | − map_flags = 0; | |
| 210 | 257 | |
| 211 | 258 | switch (map_type) { |
| 212 | 259 | case BPF_MAP_TYPE_STACK_TRACE: |
| @@ -215,7 +262,7 @@ bool bpf_probe_map_type(enum bpf_map_type map_type, __u32 ifindex) · 2 unmodified lines | ||
| 215 | 262 | case BPF_MAP_TYPE_LPM_TRIE: |
| 216 | 263 | key_size = sizeof(__u64); |
| 217 | 264 | value_size = sizeof(__u64); |
| 218 | − map_flags = BPF_F_NO_PREALLOC; | |
| 265 | + opts.map_flags = BPF_F_NO_PREALLOC; | |
| 219 | 266 | break; |
| 220 | 267 | case BPF_MAP_TYPE_CGROUP_STORAGE: |
| 221 | 268 | case BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE: |
| @@ -234,17 +281,25 @@ bool bpf_probe_map_type(enum bpf_map_type map_type, __u32 ifindex) · 12 unmodified lines | ||
| 234 | 281 | btf_value_type_id = 3; |
| 235 | 282 | value_size = 8; |
| 236 | 283 | max_entries = 0; |
| 237 | − map_flags = BPF_F_NO_PREALLOC; | |
| 284 | + opts.map_flags = BPF_F_NO_PREALLOC; | |
| 238 | 285 | btf_fd = load_local_storage_btf(); |
| 239 | 286 | if (btf_fd < 0) |
| 240 | − return false; | |
| 287 | + return btf_fd; | |
| 241 | 288 | break; |
| 242 | 289 | case BPF_MAP_TYPE_RINGBUF: |
| 243 | 290 | key_size = 0; |
| 244 | 291 | value_size = 0; |
| 245 | 292 | max_entries = 4096; |
| 246 | 293 | break; |
| 247 | − case BPF_MAP_TYPE_UNSPEC: | |
| 294 | + case BPF_MAP_TYPE_STRUCT_OPS: | |
| 295 | + /* we'll get -ENOTSUPP for invalid BTF type ID for struct_ops */ | |
| 296 | + opts.btf_vmlinux_value_type_id = 1; | |
| 297 | + exp_err = -524; /* -ENOTSUPP */ | |
| 298 | + break; | |
| 299 | + case BPF_MAP_TYPE_BLOOM_FILTER: | |
| 300 | + key_size = 0; | |
| 301 | + max_entries = 1; | |
| 302 | + break; | |
| 248 | 303 | case BPF_MAP_TYPE_HASH: |
| 249 | 304 | case BPF_MAP_TYPE_ARRAY: |
| 250 | 305 | case BPF_MAP_TYPE_PROG_ARRAY: |
| @@ -263,49 +318,114 @@ bool bpf_probe_map_type(enum bpf_map_type map_type, __u32 ifindex) · 12 unmodified lines | ||
| 263 | 318 | case BPF_MAP_TYPE_XSKMAP: |
| 264 | 319 | case BPF_MAP_TYPE_SOCKHASH: |
| 265 | 320 | case BPF_MAP_TYPE_REUSEPORT_SOCKARRAY: |
| 266 | − case BPF_MAP_TYPE_STRUCT_OPS: | |
| 267 | − default: | |
| 268 | 321 | break; |
| 322 | + case BPF_MAP_TYPE_UNSPEC: | |
| 323 | + default: | |
| 324 | + return -EOPNOTSUPP; | |
| 269 | 325 | } |
| 270 | 326 | |
| 271 | 327 | if (map_type == BPF_MAP_TYPE_ARRAY_OF_MAPS || |
| 272 | 328 | map_type == BPF_MAP_TYPE_HASH_OF_MAPS) { |
| 273 | − LIBBPF_OPTS(bpf_map_create_opts, opts); | |
| 274 | − | |
| 275 | 329 | /* TODO: probe for device, once libbpf has a function to create |
| 276 | 330 | * map-in-map for offload |
| 277 | 331 | */ |
| 278 | 332 | if (ifindex) |
| 279 | − return false; | |
| 333 | + goto cleanup; | |
| 280 | 334 | |
| 281 | 335 | fd_inner = bpf_map_create(BPF_MAP_TYPE_HASH, NULL, |
| 282 | 336 | sizeof(__u32), sizeof(__u32), 1, NULL); |
| 283 | 337 | if (fd_inner < 0) |
| 284 | − return false; | |
| 338 | + goto cleanup; | |
| 285 | 339 | |
| 286 | 340 | 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 | + } | |
| 300 | 342 | |
| 301 | − fd = bpf_map_create(map_type, NULL, key_size, value_size, max_entries, &opts); | |
| 343 | + if (btf_fd >= 0) { | |
| 344 | + opts.btf_fd = btf_fd; | |
| 345 | + opts.btf_key_type_id = btf_key_type_id; | |
| 346 | + opts.btf_value_type_id = btf_value_type_id; | |
| 302 | 347 | } |
| 348 | + | |
| 349 | + fd = bpf_map_create(map_type, NULL, key_size, value_size, max_entries, &opts); | |
| 350 | + err = -errno; | |
| 351 | + | |
| 352 | +cleanup: | |
| 303 | 353 | if (fd >= 0) |
| 304 | 354 | close(fd); |
| 355 | + if (fd_inner >= 0) | |
| 356 | + close(fd_inner); | |
| 305 | 357 | if (btf_fd >= 0) |
| 306 | 358 | close(btf_fd); |
| 307 | 359 | |
| 308 | − return fd >= 0; | |
| 360 | + if (exp_err) | |
| 361 | + return fd < 0 && err == exp_err ? 1 : 0; | |
| 362 | + else | |
| 363 | + return fd >= 0 ? 1 : 0; | |
| 364 | +} | |
| 365 | + | |
| 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 */ | |
| 309 | 429 | } |
| 310 | 430 | |
| 311 | 431 | 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 | ||
| 318 | 438 | char buf[4096] = {}; |
| 319 | 439 | bool res; |
| 320 | 440 | |
| 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); | |
| 323 | 442 | res = !grep(buf, "invalid func ") && !grep(buf, "unknown func "); |
| 324 | 443 | |
| 325 | 444 | if (ifindex) { |
| @@ -351,8 +470,8 @@ bool bpf_probe_large_insn_limit(__u32 ifindex) · 25 unmodified lines | ||
| 351 | 470 | insns[BPF_MAXINSNS] = BPF_EXIT_INSN(); |
| 352 | 471 | |
| 353 | 472 | 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); | |
| 356 | 475 | |
| 357 | 476 | return errno != E2BIG && errno != EINVAL; |
| 358 | 477 | } |
| @@ -709,10 +709,14 @@ static int bpf_core_calc_field_relo(const char *prog_name, · 708 unmodified lines | ||
| 709 | 709 | |
| 710 | 710 | static int bpf_core_calc_type_relo(const struct bpf_core_relo *relo, |
| 711 | 711 | const struct bpf_core_spec *spec, |
| 712 | − __u32 *val) | |
| 712 | + __u32 *val, bool *validate) | |
| 713 | 713 | { |
| 714 | 714 | __s64 sz; |
| 715 | 715 | |
| 716 | + /* by default, always check expected value in bpf_insn */ | |
| 717 | + if (validate) | |
| 718 | + *validate = true; | |
| 719 | + | |
| 716 | 720 | /* type-based relos return zero when target type is not found */ |
| 717 | 721 | if (!spec) { |
| 718 | 722 | *val = 0; |
| @@ -722,6 +726,11 @@ static int bpf_core_calc_type_relo(const struct bpf_core_relo *relo, · 3 unmodified lines | ||
| 722 | 726 | switch (relo->kind) { |
| 723 | 727 | case BPF_CORE_TYPE_ID_TARGET: |
| 724 | 728 | *val = spec->root_type_id; |
| 729 | + /* type ID, embedded in bpf_insn, might change during linking, | |
| 730 | + * so enforcing it is pointless | |
| 731 | + */ | |
| 732 | + if (validate) | |
| 733 | + *validate = false; | |
| 725 | 734 | break; |
| 726 | 735 | case BPF_CORE_TYPE_EXISTS: |
| 727 | 736 | *val = 1; |
| @@ -861,8 +870,8 @@ static int bpf_core_calc_relo(const char *prog_name, · 133 unmodified lines | ||
| 861 | 870 | res->fail_memsz_adjust = true; |
| 862 | 871 | } |
| 863 | 872 | } 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); | |
| 866 | 875 | } else if (core_relo_is_enumval_based(relo->kind)) { |
| 867 | 876 | err = bpf_core_calc_enumval_relo(relo, local_spec, &res->orig_val); |
| 868 | 877 | err = err ?: bpf_core_calc_enumval_relo(relo, targ_spec, &res->new_val); |
| @@ -1213,7 +1222,9 @@ int bpf_core_apply_relo_insn(const char *prog_name, struct bpf_insn *insn, · 344 unmodified lines | ||
| 1213 | 1222 | |
| 1214 | 1223 | /* TYPE_ID_LOCAL relo is special and doesn't need candidate search */ |
| 1215 | 1224 | if (relo->kind == BPF_CORE_TYPE_ID_LOCAL) { |
| 1216 | − targ_res.validate = true; | |
| 1225 | + /* bpf_insn's imm value could get out of sync during linking */ | |
| 1226 | + memset(&targ_res, 0, sizeof(targ_res)); | |
| 1227 | + targ_res.validate = false; | |
| 1217 | 1228 | targ_res.poison = false; |
| 1218 | 1229 | targ_res.orig_val = local_spec->root_type_id; |
| 1219 | 1230 | targ_res.new_val = local_spec->root_type_id; |
| @@ -1227,7 +1238,6 @@ int bpf_core_apply_relo_insn(const char *prog_name, struct bpf_insn *insn, · 7 unmodified lines | ||
| 1227 | 1238 | return -EOPNOTSUPP; |
| 1228 | 1239 | } |
| 1229 | 1240 | |
| 1230 | − | |
| 1231 | 1241 | for (i = 0, j = 0; i < cands->len; i++) { |
| 1232 | 1242 | err = bpf_core_spec_match(local_spec, cands->cands[i].btf, |
| 1233 | 1243 | cands->cands[i].id, cand_spec); |
| @@ -548,8 +548,7 @@ static int xsk_get_max_queues(struct xsk_socket *xsk) · 547 unmodified lines | ||
| 548 | 548 | return -errno; |
| 549 | 549 | |
| 550 | 550 | 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); | |
| 553 | 552 | err = ioctl(fd, SIOCETHTOOL, &ifr); |
| 554 | 553 | if (err && errno != EOPNOTSUPP) { |
| 555 | 554 | ret = -errno; |
| @@ -768,8 +767,7 @@ static int xsk_create_xsk_struct(int ifindex, struct xsk_socket *xsk) · 212 unmodified lines | ||
| 768 | 767 | } |
| 769 | 768 | |
| 770 | 769 | ctx->ifindex = ifindex; |
| 771 | − memcpy(ctx->ifname, ifname, IFNAMSIZ -1); | |
| 772 | − ctx->ifname[IFNAMSIZ - 1] = 0; | |
| 770 | + libbpf_strlcpy(ctx->ifname, ifname, IFNAMSIZ); | |
| 773 | 771 | |
| 774 | 772 | xsk->ctx = ctx; |
| 775 | 773 | xsk->ctx->has_bpf_link = xsk_probe_bpf_link(); |
| @@ -951,8 +949,7 @@ static struct xsk_ctx *xsk_create_ctx(struct xsk_socket *xsk, · 175 unmodified lines | ||
| 951 | 949 | ctx->refcount = 1; |
| 952 | 950 | ctx->umem = umem; |
| 953 | 951 | 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); | |
| 956 | 953 | |
| 957 | 954 | ctx->fill = fill; |
| 958 | 955 | ctx->comp = comp; |
| @@ -3257,10 +3257,21 @@ static void trace__set_bpf_map_syscalls(struct trace *trace) · 3256 unmodified lines | ||
| 3257 | 3257 | |
| 3258 | 3258 | static struct bpf_program *trace__find_bpf_program_by_title(struct trace *trace, const char *name) |
| 3259 | 3259 | { |
| 3260 | + struct bpf_program *pos, *prog = NULL; | |
| 3261 | + const char *sec_name; | |
| 3262 | + | |
| 3260 | 3263 | if (trace->bpf_obj == NULL) |
| 3261 | 3264 | return NULL; |
| 3262 | 3265 | |
| 3263 | − return bpf_object__find_program_by_title(trace->bpf_obj, name); | |
| 3266 | + bpf_object__for_each_program(pos, trace->bpf_obj) { | |
| 3267 | + sec_name = bpf_program__section_name(pos); | |
| 3268 | + if (sec_name && !strcmp(sec_name, name)) { | |
| 3269 | + prog = pos; | |
| 3270 | + break; | |
| 3271 | + } | |
| 3272 | + } | |
| 3273 | + | |
| 3274 | + return prog; | |
| 3264 | 3275 | } |
| 3265 | 3276 | |
| 3266 | 3277 | static struct bpf_program *trace__find_syscall_bpf_prog(struct trace *trace, struct syscall *sc, |
| @@ -87,7 +87,18 @@ LLVM_STRIP ?= llvm-strip · 86 unmodified lines | ||
| 87 | 87 | |
| 88 | 88 | ifeq ($(CC_NO_CLANG), 1) |
| 89 | 89 | 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 | |
| 91 | 102 | |
| 92 | 103 | # Hack to avoid type-punned warnings on old systems such as RHEL5: |
| 93 | 104 | # We should be changing CFLAGS and checking gcc version, but this |
| @@ -170,7 +170,7 @@ $(OUTPUT)/%:%.c · 169 unmodified lines | ||
| 170 | 170 | |
| 171 | 171 | $(OUTPUT)/urandom_read: urandom_read.c |
| 172 | 172 | $(call msg,BINARY,,$@) |
| 173 | − $(Q)$(CC) $(LDFLAGS) $< $(LDLIBS) -Wl,--build-id=sha1 -o $@ | |
| 173 | + $(Q)$(CC) $(CFLAGS) $(LDFLAGS) $< $(LDLIBS) -Wl,--build-id=sha1 -o $@ | |
| 174 | 174 | |
| 175 | 175 | $(OUTPUT)/bpf_testmod.ko: $(VMLINUX_BTF) $(wildcard bpf_testmod/Makefile bpf_testmod/*.[ch]) |
| 176 | 176 | $(call msg,MOD,,$@) |
| @@ -217,7 +217,7 @@ BPFTOOL ?= $(DEFAULT_BPFTOOL) · 40 unmodified lines | ||
| 217 | 217 | $(DEFAULT_BPFTOOL): $(wildcard $(BPFTOOLDIR)/*.[ch] $(BPFTOOLDIR)/Makefile) \ |
| 218 | 218 | $(HOST_BPFOBJ) | $(HOST_BUILD_DIR)/bpftool |
| 219 | 219 | $(Q)$(MAKE) $(submake_extras) -C $(BPFTOOLDIR) \ |
| 220 | − CC=$(HOSTCC) LD=$(HOSTLD) \ | |
| 220 | + ARCH= CROSS_COMPILE= CC=$(HOSTCC) LD=$(HOSTLD) \ | |
| 221 | 221 | EXTRA_CFLAGS='-g -O0' \ |
| 222 | 222 | OUTPUT=$(HOST_BUILD_DIR)/bpftool/ \ |
| 223 | 223 | LIBBPF_OUTPUT=$(HOST_BUILD_DIR)/libbpf/ \ |
| @@ -248,7 +248,7 @@ $(HOST_BPFOBJ): $(wildcard $(BPFDIR)/*.[ch] $(BPFDIR)/Makefile) \ · 24 unmodified lines | ||
| 248 | 248 | $(APIDIR)/linux/bpf.h \ |
| 249 | 249 | | $(HOST_BUILD_DIR)/libbpf |
| 250 | 250 | $(Q)$(MAKE) $(submake_extras) -C $(BPFDIR) \ |
| 251 | − EXTRA_CFLAGS='-g -O0' \ | |
| 251 | + EXTRA_CFLAGS='-g -O0' ARCH= CROSS_COMPILE= \ | |
| 252 | 252 | OUTPUT=$(HOST_BUILD_DIR)/libbpf/ CC=$(HOSTCC) LD=$(HOSTLD) \ |
| 253 | 253 | DESTDIR=$(HOST_SCRATCH_DIR)/ prefix= all install_headers |
| 254 | 254 | endif |
| @@ -537,6 +537,7 @@ $(OUTPUT)/bench_ringbufs.o: $(OUTPUT)/ringbuf_bench.skel.h \ · 282 unmodified lines | ||
| 537 | 537 | $(OUTPUT)/perfbuf_bench.skel.h |
| 538 | 538 | $(OUTPUT)/bench_bloom_filter_map.o: $(OUTPUT)/bloom_filter_bench.skel.h |
| 539 | 539 | $(OUTPUT)/bench_bpf_loop.o: $(OUTPUT)/bpf_loop_bench.skel.h |
| 540 | +$(OUTPUT)/bench_strncmp.o: $(OUTPUT)/strncmp_bench.skel.h | |
| 540 | 541 | $(OUTPUT)/bench.o: bench.h testing_helpers.h $(BPFOBJ) |
| 541 | 542 | $(OUTPUT)/bench: LDLIBS += -lm |
| 542 | 543 | $(OUTPUT)/bench: $(OUTPUT)/bench.o \ |
| @@ -547,9 +548,10 @@ $(OUTPUT)/bench: $(OUTPUT)/bench.o \ · 4 unmodified lines | ||
| 547 | 548 | $(OUTPUT)/bench_trigger.o \ |
| 548 | 549 | $(OUTPUT)/bench_ringbufs.o \ |
| 549 | 550 | $(OUTPUT)/bench_bloom_filter_map.o \ |
| 550 | − $(OUTPUT)/bench_bpf_loop.o | |
| 551 | + $(OUTPUT)/bench_bpf_loop.o \ | |
| 552 | + $(OUTPUT)/bench_strncmp.o | |
| 551 | 553 | $(call msg,BINARY,,$@) |
| 552 | − $(Q)$(CC) $(LDFLAGS) $(filter %.a %.o,$^) $(LDLIBS) -o $@ | |
| 554 | + $(Q)$(CC) $(CFLAGS) $(LDFLAGS) $(filter %.a %.o,$^) $(LDLIBS) -o $@ | |
| 553 | 555 | |
| 554 | 556 | EXTRA_CLEAN := $(TEST_CUSTOM_PROGS) $(SCRATCH_DIR) $(HOST_SCRATCH_DIR) \ |
| 555 | 557 | prog_tests/tests.h map_tests/tests.h verifier/tests.h \ |
| @@ -29,26 +29,10 @@ static int libbpf_print_fn(enum libbpf_print_level level, · 28 unmodified lines | ||
| 29 | 29 | return vfprintf(stderr, format, args); |
| 30 | 30 | } |
| 31 | 31 | |
| 32 | −static int bump_memlock_rlimit(void) | |
| 32 | +void setup_libbpf(void) | |
| 33 | 33 | { |
| 34 | − struct rlimit rlim_new = { | |
| 35 | − .rlim_cur = RLIM_INFINITY, | |
| 36 | − .rlim_max = RLIM_INFINITY, | |
| 37 | − }; | |
| 38 | − | |
| 39 | − return setrlimit(RLIMIT_MEMLOCK, &rlim_new); | |
| 40 | −} | |
| 41 | − | |
| 42 | −void setup_libbpf() | |
| 43 | −{ | |
| 44 | − int err; | |
| 45 | − | |
| 46 | 34 | libbpf_set_strict_mode(LIBBPF_STRICT_ALL); |
| 47 | 35 | libbpf_set_print(libbpf_print_fn); |
| 48 | − | |
| 49 | − err = bump_memlock_rlimit(); | |
| 50 | − if (err) | |
| 51 | − fprintf(stderr, "failed to increase RLIMIT_MEMLOCK: %d", err); | |
| 52 | 36 | } |
| 53 | 37 | |
| 54 | 38 | 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 | ||
| 205 | 189 | extern struct argp bench_ringbufs_argp; |
| 206 | 190 | extern struct argp bench_bloom_map_argp; |
| 207 | 191 | extern struct argp bench_bpf_loop_argp; |
| 192 | +extern struct argp bench_strncmp_argp; | |
| 208 | 193 | |
| 209 | 194 | static const struct argp_child bench_parsers[] = { |
| 210 | 195 | { &bench_ringbufs_argp, 0, "Ring buffers benchmark", 0 }, |
| 211 | 196 | { &bench_bloom_map_argp, 0, "Bloom filter map benchmark", 0 }, |
| 212 | 197 | { &bench_bpf_loop_argp, 0, "bpf_loop helper benchmark", 0 }, |
| 198 | + { &bench_strncmp_argp, 0, "bpf_strncmp helper benchmark", 0 }, | |
| 213 | 199 | {}, |
| 214 | 200 | }; |
| 215 | 201 | |
| @@ -409,6 +395,8 @@ extern const struct bench bench_bloom_false_positive; · 193 unmodified lines | ||
| 409 | 395 | extern const struct bench bench_hashmap_without_bloom; |
| 410 | 396 | extern const struct bench bench_hashmap_with_bloom; |
| 411 | 397 | extern const struct bench bench_bpf_loop; |
| 398 | +extern const struct bench bench_strncmp_no_helper; | |
| 399 | +extern const struct bench bench_strncmp_helper; | |
| 412 | 400 | |
| 413 | 401 | static const struct bench *benchs[] = { |
| 414 | 402 | &bench_count_global, |
| @@ -441,6 +429,8 @@ static const struct bench *benchs[] = { · 26 unmodified lines | ||
| 441 | 429 | &bench_hashmap_without_bloom, |
| 442 | 430 | &bench_hashmap_with_bloom, |
| 443 | 431 | &bench_bpf_loop, |
| 432 | + &bench_strncmp_no_helper, | |
| 433 | + &bench_strncmp_helper, | |
| 444 | 434 | }; |
| 445 | 435 | |
| 446 | 436 | static void setup_benchmark() |
| @@ -38,8 +38,8 @@ struct bench_res { · 37 unmodified lines | ||
| 38 | 38 | |
| 39 | 39 | struct bench { |
| 40 | 40 | const char *name; |
| 41 | − void (*validate)(); | |
| 42 | − void (*setup)(); | |
| 41 | + void (*validate)(void); | |
| 42 | + void (*setup)(void); | |
| 43 | 43 | void *(*producer_thread)(void *ctx); |
| 44 | 44 | void *(*consumer_thread)(void *ctx); |
| 45 | 45 | void (*measure)(struct bench_res* res); |
| @@ -54,7 +54,7 @@ struct counter { · 8 unmodified lines | ||
| 54 | 54 | extern struct env env; |
| 55 | 55 | extern const struct bench *bench; |
| 56 | 56 | |
| 57 | −void setup_libbpf(); | |
| 57 | +void setup_libbpf(void); | |
| 58 | 58 | void hits_drops_report_progress(int iter, struct bench_res *res, long delta_ns); |
| 59 | 59 | void hits_drops_report_final(struct bench_res res[], int res_cnt); |
| 60 | 60 | 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 | ||
| 62 | 62 | void ops_report_progress(int iter, struct bench_res *res, long delta_ns); |
| 63 | 63 | void ops_report_final(struct bench_res res[], int res_cnt); |
| 64 | 64 | |
| 65 | −static inline __u64 get_time_ns() { | |
| 65 | +static inline __u64 get_time_ns(void) | |
| 66 | +{ | |
| 66 | 67 | struct timespec t; |
| 67 | 68 | |
| 68 | 69 | clock_gettime(CLOCK_MONOTONIC, &t); |
| @@ -36,7 +36,7 @@ static struct count_local_ctx { · 35 unmodified lines | ||
| 36 | 36 | struct counter *hits; |
| 37 | 37 | } count_local_ctx; |
| 38 | 38 | |
| 39 | −static void count_local_setup() | |
| 39 | +static void count_local_setup(void) | |
| 40 | 40 | { |
| 41 | 41 | struct count_local_ctx *ctx = &count_local_ctx; |
| 42 | 42 | |
| @@ -11,7 +11,7 @@ static struct ctx { · 10 unmodified lines | ||
| 11 | 11 | int fd; |
| 12 | 12 | } ctx; |
| 13 | 13 | |
| 14 | −static void validate() | |
| 14 | +static void validate(void) | |
| 15 | 15 | { |
| 16 | 16 | if (env.producer_cnt != 1) { |
| 17 | 17 | fprintf(stderr, "benchmark doesn't support multi-producer!\n"); |
| @@ -43,7 +43,7 @@ static void measure(struct bench_res *res) · 25 unmodified lines | ||
| 43 | 43 | res->hits = atomic_swap(&ctx.hits.value, 0); |
| 44 | 44 | } |
| 45 | 45 | |
| 46 | −static void setup_ctx() | |
| 46 | +static void setup_ctx(void) | |
| 47 | 47 | { |
| 48 | 48 | setup_libbpf(); |
| 49 | 49 | |
| @@ -71,36 +71,36 @@ static void attach_bpf(struct bpf_program *prog) · 21 unmodified lines | ||
| 71 | 71 | } |
| 72 | 72 | } |
| 73 | 73 | |
| 74 | −static void setup_base() | |
| 74 | +static void setup_base(void) | |
| 75 | 75 | { |
| 76 | 76 | setup_ctx(); |
| 77 | 77 | } |
| 78 | 78 | |
| 79 | −static void setup_kprobe() | |
| 79 | +static void setup_kprobe(void) | |
| 80 | 80 | { |
| 81 | 81 | setup_ctx(); |
| 82 | 82 | attach_bpf(ctx.skel->progs.prog1); |
| 83 | 83 | } |
| 84 | 84 | |
| 85 | −static void setup_kretprobe() | |
| 85 | +static void setup_kretprobe(void) | |
| 86 | 86 | { |
| 87 | 87 | setup_ctx(); |
| 88 | 88 | attach_bpf(ctx.skel->progs.prog2); |
| 89 | 89 | } |
| 90 | 90 | |
| 91 | −static void setup_rawtp() | |
| 91 | +static void setup_rawtp(void) | |
| 92 | 92 | { |
| 93 | 93 | setup_ctx(); |
| 94 | 94 | attach_bpf(ctx.skel->progs.prog3); |
| 95 | 95 | } |
| 96 | 96 | |
| 97 | −static void setup_fentry() | |
| 97 | +static void setup_fentry(void) | |
| 98 | 98 | { |
| 99 | 99 | setup_ctx(); |
| 100 | 100 | attach_bpf(ctx.skel->progs.prog4); |
| 101 | 101 | } |
| 102 | 102 | |
| 103 | −static void setup_fexit() | |
| 103 | +static void setup_fexit(void) | |
| 104 | 104 | { |
| 105 | 105 | setup_ctx(); |
| 106 | 106 | attach_bpf(ctx.skel->progs.prog5); |
| @@ -88,12 +88,12 @@ const struct argp bench_ringbufs_argp = { · 87 unmodified lines | ||
| 88 | 88 | |
| 89 | 89 | static struct counter buf_hits; |
| 90 | 90 | |
| 91 | −static inline void bufs_trigger_batch() | |
| 91 | +static inline void bufs_trigger_batch(void) | |
| 92 | 92 | { |
| 93 | 93 | (void)syscall(__NR_getpgid); |
| 94 | 94 | } |
| 95 | 95 | |
| 96 | −static void bufs_validate() | |
| 96 | +static void bufs_validate(void) | |
| 97 | 97 | { |
| 98 | 98 | if (env.consumer_cnt != 1) { |
| 99 | 99 | fprintf(stderr, "rb-libbpf benchmark doesn't support multi-consumer!\n"); |
| @@ -132,7 +132,7 @@ static void ringbuf_libbpf_measure(struct bench_res *res) · 32 unmodified lines | ||
| 132 | 132 | res->drops = atomic_swap(&ctx->skel->bss->dropped, 0); |
| 133 | 133 | } |
| 134 | 134 | |
| 135 | −static struct ringbuf_bench *ringbuf_setup_skeleton() | |
| 135 | +static struct ringbuf_bench *ringbuf_setup_skeleton(void) | |
| 136 | 136 | { |
| 137 | 137 | struct ringbuf_bench *skel; |
| 138 | 138 | |
| @@ -167,7 +167,7 @@ static int buf_process_sample(void *ctx, void *data, size_t len) · 28 unmodified lines | ||
| 167 | 167 | return 0; |
| 168 | 168 | } |
| 169 | 169 | |
| 170 | −static void ringbuf_libbpf_setup() | |
| 170 | +static void ringbuf_libbpf_setup(void) | |
| 171 | 171 | { |
| 172 | 172 | struct ringbuf_libbpf_ctx *ctx = &ringbuf_libbpf_ctx; |
| 173 | 173 | struct bpf_link *link; |
| @@ -223,7 +223,7 @@ static void ringbuf_custom_measure(struct bench_res *res) · 49 unmodified lines | ||
| 223 | 223 | res->drops = atomic_swap(&ctx->skel->bss->dropped, 0); |
| 224 | 224 | } |
| 225 | 225 | |
| 226 | −static void ringbuf_custom_setup() | |
| 226 | +static void ringbuf_custom_setup(void) | |
| 227 | 227 | { |
| 228 | 228 | struct ringbuf_custom_ctx *ctx = &ringbuf_custom_ctx; |
| 229 | 229 | const size_t page_size = getpagesize(); |
| @@ -352,7 +352,7 @@ static void perfbuf_measure(struct bench_res *res) · 122 unmodified lines | ||
| 352 | 352 | res->drops = atomic_swap(&ctx->skel->bss->dropped, 0); |
| 353 | 353 | } |
| 354 | 354 | |
| 355 | −static struct perfbuf_bench *perfbuf_setup_skeleton() | |
| 355 | +static struct perfbuf_bench *perfbuf_setup_skeleton(void) | |
| 356 | 356 | { |
| 357 | 357 | struct perfbuf_bench *skel; |
| 358 | 358 | |
| @@ -390,7 +390,7 @@ perfbuf_process_sample_raw(void *input_ctx, int cpu, · 31 unmodified lines | ||
| 390 | 390 | return LIBBPF_PERF_EVENT_CONT; |
| 391 | 391 | } |
| 392 | 392 | |
| 393 | −static void perfbuf_libbpf_setup() | |
| 393 | +static void perfbuf_libbpf_setup(void) | |
| 394 | 394 | { |
| 395 | 395 | struct perfbuf_libbpf_ctx *ctx = &perfbuf_libbpf_ctx; |
| 396 | 396 | struct perf_event_attr attr; |
| @@ -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 | +}; | |
| @@ -11,7 +11,7 @@ static struct trigger_ctx { · 10 unmodified lines | ||
| 11 | 11 | |
| 12 | 12 | static struct counter base_hits; |
| 13 | 13 | |
| 14 | −static void trigger_validate() | |
| 14 | +static void trigger_validate(void) | |
| 15 | 15 | { |
| 16 | 16 | if (env.consumer_cnt != 1) { |
| 17 | 17 | fprintf(stderr, "benchmark doesn't support multi-consumer!\n"); |
| @@ -45,7 +45,7 @@ static void trigger_measure(struct bench_res *res) · 27 unmodified lines | ||
| 45 | 45 | res->hits = atomic_swap(&ctx.skel->bss->hits, 0); |
| 46 | 46 | } |
| 47 | 47 | |
| 48 | −static void setup_ctx() | |
| 48 | +static void setup_ctx(void) | |
| 49 | 49 | { |
| 50 | 50 | setup_libbpf(); |
| 51 | 51 | |
| @@ -67,37 +67,37 @@ static void attach_bpf(struct bpf_program *prog) · 15 unmodified lines | ||
| 67 | 67 | } |
| 68 | 68 | } |
| 69 | 69 | |
| 70 | −static void trigger_tp_setup() | |
| 70 | +static void trigger_tp_setup(void) | |
| 71 | 71 | { |
| 72 | 72 | setup_ctx(); |
| 73 | 73 | attach_bpf(ctx.skel->progs.bench_trigger_tp); |
| 74 | 74 | } |
| 75 | 75 | |
| 76 | −static void trigger_rawtp_setup() | |
| 76 | +static void trigger_rawtp_setup(void) | |
| 77 | 77 | { |
| 78 | 78 | setup_ctx(); |
| 79 | 79 | attach_bpf(ctx.skel->progs.bench_trigger_raw_tp); |
| 80 | 80 | } |
| 81 | 81 | |
| 82 | −static void trigger_kprobe_setup() | |
| 82 | +static void trigger_kprobe_setup(void) | |
| 83 | 83 | { |
| 84 | 84 | setup_ctx(); |
| 85 | 85 | attach_bpf(ctx.skel->progs.bench_trigger_kprobe); |
| 86 | 86 | } |
| 87 | 87 | |
| 88 | −static void trigger_fentry_setup() | |
| 88 | +static void trigger_fentry_setup(void) | |
| 89 | 89 | { |
| 90 | 90 | setup_ctx(); |
| 91 | 91 | attach_bpf(ctx.skel->progs.bench_trigger_fentry); |
| 92 | 92 | } |
| 93 | 93 | |
| 94 | −static void trigger_fentry_sleep_setup() | |
| 94 | +static void trigger_fentry_sleep_setup(void) | |
| 95 | 95 | { |
| 96 | 96 | setup_ctx(); |
| 97 | 97 | attach_bpf(ctx.skel->progs.bench_trigger_fentry_sleep); |
| 98 | 98 | } |
| 99 | 99 | |
| 100 | −static void trigger_fmodret_setup() | |
| 100 | +static void trigger_fmodret_setup(void) | |
| 101 | 101 | { |
| 102 | 102 | setup_ctx(); |
| 103 | 103 | attach_bpf(ctx.skel->progs.bench_trigger_fmodret); |
| @@ -183,22 +183,22 @@ static void usetup(bool use_retprobe, bool use_nop) · 79 unmodified lines | ||
| 183 | 183 | ctx.skel->links.bench_trigger_uprobe = link; |
| 184 | 184 | } |
| 185 | 185 | |
| 186 | −static void uprobe_setup_with_nop() | |
| 186 | +static void uprobe_setup_with_nop(void) | |
| 187 | 187 | { |
| 188 | 188 | usetup(false, true); |
| 189 | 189 | } |
| 190 | 190 | |
| 191 | −static void uretprobe_setup_with_nop() | |
| 191 | +static void uretprobe_setup_with_nop(void) | |
| 192 | 192 | { |
| 193 | 193 | usetup(true, true); |
| 194 | 194 | } |
| 195 | 195 | |
| 196 | −static void uprobe_setup_without_nop() | |
| 196 | +static void uprobe_setup_without_nop(void) | |
| 197 | 197 | { |
| 198 | 198 | usetup(false, false); |
| 199 | 199 | } |
| 200 | 200 | |
| 201 | −static void uretprobe_setup_without_nop() | |
| 201 | +static void uretprobe_setup_without_nop(void) | |
| 202 | 202 | { |
| 203 | 203 | usetup(true, false); |
| 204 | 204 | } |
| @@ -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 | |
| @@ -38,7 +38,9 @@ CONFIG_IPV6_SIT=m · 37 unmodified lines | ||
| 38 | 38 | CONFIG_BPF_JIT=y |
| 39 | 39 | CONFIG_BPF_LSM=y |
| 40 | 40 | CONFIG_SECURITY=y |
| 41 | +CONFIG_RC_CORE=y | |
| 41 | 42 | CONFIG_LIRC=y |
| 43 | +CONFIG_BPF_LIRC_MODE2=y | |
| 42 | 44 | CONFIG_IMA=y |
| 43 | 45 | CONFIG_SECURITYFS=y |
| 44 | 46 | CONFIG_IMA_WRITE_POLICY=y |
| @@ -39,13 +39,13 @@ static struct bpf_align_test tests[] = { · 38 unmodified lines | ||
| 39 | 39 | }, |
| 40 | 40 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, |
| 41 | 41 | .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"}, | |
| 49 | 49 | }, |
| 50 | 50 | }, |
| 51 | 51 | { |
| @@ -67,19 +67,19 @@ static struct bpf_align_test tests[] = { · 15 unmodified lines | ||
| 67 | 67 | }, |
| 68 | 68 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, |
| 69 | 69 | .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"}, | |
| 83 | 83 | }, |
| 84 | 84 | }, |
| 85 | 85 | { |
| @@ -96,14 +96,14 @@ static struct bpf_align_test tests[] = { · 10 unmodified lines | ||
| 96 | 96 | }, |
| 97 | 97 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, |
| 98 | 98 | .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"}, | |
| 107 | 107 | }, |
| 108 | 108 | }, |
| 109 | 109 | { |
| @@ -118,12 +118,12 @@ static struct bpf_align_test tests[] = { · 8 unmodified lines | ||
| 118 | 118 | }, |
| 119 | 119 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, |
| 120 | 120 | .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"}, | |
| 123 | 124 | {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"}, | |
| 127 | 127 | }, |
| 128 | 128 | }, |
| 129 | 129 | |
| @@ -161,19 +161,19 @@ static struct bpf_align_test tests[] = { · 31 unmodified lines | ||
| 161 | 161 | }, |
| 162 | 162 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, |
| 163 | 163 | .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))"}, | |
| 177 | 177 | }, |
| 178 | 178 | }, |
| 179 | 179 | { |
| @@ -194,16 +194,16 @@ static struct bpf_align_test tests[] = { · 14 unmodified lines | ||
| 194 | 194 | }, |
| 195 | 195 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, |
| 196 | 196 | .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))"}, | |
| 207 | 207 | }, |
| 208 | 208 | }, |
| 209 | 209 | { |
| @@ -234,14 +234,14 @@ static struct bpf_align_test tests[] = { · 24 unmodified lines | ||
| 234 | 234 | }, |
| 235 | 235 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, |
| 236 | 236 | .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)"}, | |
| 241 | 241 | {10, "R5=pkt(id=0,off=14,r=18,imm=0)"}, |
| 242 | 242 | {10, "R4_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"}, |
| 243 | + {13, "R4_w=inv(id=0,umax_value=65535,var_off=(0x0; 0xffff))"}, | |
| 243 | 244 | {14, "R4_w=inv(id=0,umax_value=65535,var_off=(0x0; 0xffff))"}, |
| 244 | − {15, "R4_w=inv(id=0,umax_value=65535,var_off=(0x0; 0xffff))"}, | |
| 245 | 245 | }, |
| 246 | 246 | }, |
| 247 | 247 | { |
| @@ -296,8 +296,8 @@ static struct bpf_align_test tests[] = { · 48 unmodified lines | ||
| 296 | 296 | /* Calculated offset in R6 has unknown value, but known |
| 297 | 297 | * alignment of 4. |
| 298 | 298 | */ |
| 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))"}, | |
| 301 | 301 | /* Offset is added to packet pointer R5, resulting in |
| 302 | 302 | * known fixed offset, and variable offset from R6. |
| 303 | 303 | */ |
| @@ -313,11 +313,11 @@ static struct bpf_align_test tests[] = { · 9 unmodified lines | ||
| 313 | 313 | /* Variable offset is added to R5 packet pointer, |
| 314 | 314 | * resulting in auxiliary alignment of 4. |
| 315 | 315 | */ |
| 316 | − {18, "R5_w=pkt(id=2,off=0,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, | |
| 316 | + {17, "R5_w=pkt(id=2,off=0,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, | |
| 317 | 317 | /* Constant offset is added to R5, resulting in |
| 318 | 318 | * reg->off of 14. |
| 319 | 319 | */ |
| 320 | − {19, "R5_w=pkt(id=2,off=14,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, | |
| 320 | + {18, "R5_w=pkt(id=2,off=14,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, | |
| 321 | 321 | /* At the time the word size load is performed from R5, |
| 322 | 322 | * its total fixed offset is NET_IP_ALIGN + reg->off |
| 323 | 323 | * (14) which is 16. Then the variable offset is 4-byte |
| @@ -329,18 +329,18 @@ static struct bpf_align_test tests[] = { · 5 unmodified lines | ||
| 329 | 329 | /* Constant offset is added to R5 packet pointer, |
| 330 | 330 | * resulting in reg->off value of 14. |
| 331 | 331 | */ |
| 332 | − {26, "R5_w=pkt(id=0,off=14,r=8"}, | |
| 332 | + {25, "R5_w=pkt(id=0,off=14,r=8"}, | |
| 333 | 333 | /* Variable offset is added to R5, resulting in a |
| 334 | 334 | * variable offset of (4n). |
| 335 | 335 | */ |
| 336 | − {27, "R5_w=pkt(id=3,off=14,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, | |
| 336 | + {26, "R5_w=pkt(id=3,off=14,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, | |
| 337 | 337 | /* Constant is added to R5 again, setting reg->off to 18. */ |
| 338 | − {28, "R5_w=pkt(id=3,off=18,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, | |
| 338 | + {27, "R5_w=pkt(id=3,off=18,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, | |
| 339 | 339 | /* And once more we add a variable; resulting var_off |
| 340 | 340 | * is still (4n), fixed offset is not changed. |
| 341 | 341 | * Also, we create a new reg->id. |
| 342 | 342 | */ |
| 343 | − {29, "R5_w=pkt(id=4,off=18,r=0,umax_value=2040,var_off=(0x0; 0x7fc)"}, | |
| 343 | + {28, "R5_w=pkt(id=4,off=18,r=0,umax_value=2040,var_off=(0x0; 0x7fc)"}, | |
| 344 | 344 | /* At the time the word size load is performed from R5, |
| 345 | 345 | * its total fixed offset is NET_IP_ALIGN + reg->off (18) |
| 346 | 346 | * which is 20. Then the variable offset is (4n), so |
| @@ -386,13 +386,13 @@ static struct bpf_align_test tests[] = { · 39 unmodified lines | ||
| 386 | 386 | /* Calculated offset in R6 has unknown value, but known |
| 387 | 387 | * alignment of 4. |
| 388 | 388 | */ |
| 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))"}, | |
| 391 | 391 | /* Adding 14 makes R6 be (4n+2) */ |
| 392 | − {9, "R6_w=inv(id=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc))"}, | |
| 392 | + {8, "R6_w=inv(id=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc))"}, | |
| 393 | 393 | /* Packet pointer has (4n+2) offset */ |
| 394 | 394 | {11, "R5_w=pkt(id=1,off=0,r=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc)"}, |
| 395 | − {13, "R4=pkt(id=1,off=4,r=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc)"}, | |
| 395 | + {12, "R4=pkt(id=1,off=4,r=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc)"}, | |
| 396 | 396 | /* At the time the word size load is performed from R5, |
| 397 | 397 | * its total fixed offset is NET_IP_ALIGN + reg->off (0) |
| 398 | 398 | * which is 2. Then the variable offset is (4n+2), so |
| @@ -403,12 +403,12 @@ static struct bpf_align_test tests[] = { · 4 unmodified lines | ||
| 403 | 403 | /* Newly read value in R6 was shifted left by 2, so has |
| 404 | 404 | * known alignment of 4. |
| 405 | 405 | */ |
| 406 | − {18, "R6_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, | |
| 406 | + {17, "R6_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, | |
| 407 | 407 | /* Added (4n) to packet pointer's (4n+2) var_off, giving |
| 408 | 408 | * another (4n+2). |
| 409 | 409 | */ |
| 410 | 410 | {19, "R5_w=pkt(id=2,off=0,r=0,umin_value=14,umax_value=2054,var_off=(0x2; 0xffc)"}, |
| 411 | − {21, "R4=pkt(id=2,off=4,r=0,umin_value=14,umax_value=2054,var_off=(0x2; 0xffc)"}, | |
| 411 | + {20, "R4=pkt(id=2,off=4,r=0,umin_value=14,umax_value=2054,var_off=(0x2; 0xffc)"}, | |
| 412 | 412 | /* At the time the word size load is performed from R5, |
| 413 | 413 | * its total fixed offset is NET_IP_ALIGN + reg->off (0) |
| 414 | 414 | * which is 2. Then the variable offset is (4n+2), so |
| @@ -448,18 +448,18 @@ static struct bpf_align_test tests[] = { · 33 unmodified lines | ||
| 448 | 448 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, |
| 449 | 449 | .result = REJECT, |
| 450 | 450 | .matches = { |
| 451 | − {4, "R5_w=pkt_end(id=0,off=0,imm=0)"}, | |
| 451 | + {3, "R5_w=pkt_end(id=0,off=0,imm=0)"}, | |
| 452 | 452 | /* (ptr - ptr) << 2 == unknown, (4n) */ |
| 453 | − {6, "R5_w=inv(id=0,smax_value=9223372036854775804,umax_value=18446744073709551612,var_off=(0x0; 0xfffffffffffffffc)"}, | |
| 453 | + {5, "R5_w=inv(id=0,smax_value=9223372036854775804,umax_value=18446744073709551612,var_off=(0x0; 0xfffffffffffffffc)"}, | |
| 454 | 454 | /* (4n) + 14 == (4n+2). We blow our bounds, because |
| 455 | 455 | * the add could overflow. |
| 456 | 456 | */ |
| 457 | − {7, "R5_w=inv(id=0,smin_value=-9223372036854775806,smax_value=9223372036854775806,umin_value=2,umax_value=18446744073709551614,var_off=(0x2; 0xfffffffffffffffc)"}, | |
| 457 | + {6, "R5_w=inv(id=0,smin_value=-9223372036854775806,smax_value=9223372036854775806,umin_value=2,umax_value=18446744073709551614,var_off=(0x2; 0xfffffffffffffffc)"}, | |
| 458 | 458 | /* Checked s>=0 */ |
| 459 | 459 | {9, "R5=inv(id=0,umin_value=2,umax_value=9223372036854775806,var_off=(0x2; 0x7ffffffffffffffc)"}, |
| 460 | 460 | /* packet pointer + nonnegative (4n+2) */ |
| 461 | 461 | {11, "R6_w=pkt(id=1,off=0,r=0,umin_value=2,umax_value=9223372036854775806,var_off=(0x2; 0x7ffffffffffffffc)"}, |
| 462 | − {13, "R4_w=pkt(id=1,off=4,r=0,umin_value=2,umax_value=9223372036854775806,var_off=(0x2; 0x7ffffffffffffffc)"}, | |
| 462 | + {12, "R4_w=pkt(id=1,off=4,r=0,umin_value=2,umax_value=9223372036854775806,var_off=(0x2; 0x7ffffffffffffffc)"}, | |
| 463 | 463 | /* NET_IP_ALIGN + (4n+2) == (4n), alignment is fine. |
| 464 | 464 | * We checked the bounds, but it might have been able |
| 465 | 465 | * to overflow if the packet pointer started in the |
| @@ -502,14 +502,14 @@ static struct bpf_align_test tests[] = { · 36 unmodified lines | ||
| 502 | 502 | /* Calculated offset in R6 has unknown value, but known |
| 503 | 503 | * alignment of 4. |
| 504 | 504 | */ |
| 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))"}, | |
| 507 | 507 | /* Adding 14 makes R6 be (4n+2) */ |
| 508 | − {10, "R6_w=inv(id=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc))"}, | |
| 508 | + {9, "R6_w=inv(id=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc))"}, | |
| 509 | 509 | /* New unknown value in R7 is (4n) */ |
| 510 | − {11, "R7_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, | |
| 510 | + {10, "R7_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, | |
| 511 | 511 | /* Subtracting it from R6 blows our unsigned bounds */ |
| 512 | − {12, "R6=inv(id=0,smin_value=-1006,smax_value=1034,umin_value=2,umax_value=18446744073709551614,var_off=(0x2; 0xfffffffffffffffc)"}, | |
| 512 | + {11, "R6=inv(id=0,smin_value=-1006,smax_value=1034,umin_value=2,umax_value=18446744073709551614,var_off=(0x2; 0xfffffffffffffffc)"}, | |
| 513 | 513 | /* Checked s>= 0 */ |
| 514 | 514 | {14, "R6=inv(id=0,umin_value=2,umax_value=1034,var_off=(0x2; 0x7fc))"}, |
| 515 | 515 | /* At the time the word size load is performed from R5, |
| @@ -556,14 +556,14 @@ static struct bpf_align_test tests[] = { · 40 unmodified lines | ||
| 556 | 556 | /* Calculated offset in R6 has unknown value, but known |
| 557 | 557 | * alignment of 4. |
| 558 | 558 | */ |
| 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))"}, | |
| 561 | 561 | /* Adding 14 makes R6 be (4n+2) */ |
| 562 | − {11, "R6_w=inv(id=0,umin_value=14,umax_value=74,var_off=(0x2; 0x7c))"}, | |
| 562 | + {10, "R6_w=inv(id=0,umin_value=14,umax_value=74,var_off=(0x2; 0x7c))"}, | |
| 563 | 563 | /* Subtracting from packet pointer overflows ubounds */ |
| 564 | 564 | {13, "R5_w=pkt(id=2,off=0,r=8,umin_value=18446744073709551542,umax_value=18446744073709551602,var_off=(0xffffffffffffff82; 0x7c)"}, |
| 565 | 565 | /* New unknown value in R7 is (4n), >= 76 */ |
| 566 | − {15, "R7_w=inv(id=0,umin_value=76,umax_value=1096,var_off=(0x0; 0x7fc))"}, | |
| 566 | + {14, "R7_w=inv(id=0,umin_value=76,umax_value=1096,var_off=(0x0; 0x7fc))"}, | |
| 567 | 567 | /* Adding it to packet pointer gives nice bounds again */ |
| 568 | 568 | {16, "R5_w=pkt(id=3,off=0,r=0,umin_value=2,umax_value=1082,var_off=(0x2; 0xfffffffc)"}, |
| 569 | 569 | /* At the time the word size load is performed from R5, |
| @@ -625,12 +625,15 @@ static int do_test_single(struct bpf_align_test *test) · 55 unmodified lines | ||
| 625 | 625 | line_ptr = strtok(bpf_vlog_copy, "\n"); |
| 626 | 626 | for (i = 0; i < MAX_MATCHES; i++) { |
| 627 | 627 | struct bpf_reg_match m = test->matches[i]; |
| 628 | + int tmp; | |
| 628 | 629 | |
| 629 | 630 | if (!m.match) |
| 630 | 631 | break; |
| 631 | 632 | while (line_ptr) { |
| 632 | 633 | cur_line = -1; |
| 633 | 634 | sscanf(line_ptr, "%u: ", &cur_line); |
| 635 | + if (cur_line == -1) | |
| 636 | + sscanf(line_ptr, "from %u to %u: ", &tmp, &cur_line); | |
| 634 | 637 | if (cur_line == m.line) |
| 635 | 638 | break; |
| 636 | 639 | line_ptr = strtok(NULL, "\n"); |
| @@ -642,7 +645,19 @@ static int do_test_single(struct bpf_align_test *test) · 5 unmodified lines | ||
| 642 | 645 | printf("%s", bpf_vlog); |
| 643 | 646 | break; |
| 644 | 647 | } |
| 648 | + /* Check the next line as well in case the previous line | |
| 649 | + * did not have a corresponding bpf insn. Example: | |
| 650 | + * func#0 @0 | |
| 651 | + * 0: R1=ctx(id=0,off=0,imm=0) R10=fp0 | |
| 652 | + * 0: (b7) r3 = 2 ; R3_w=inv2 | |
| 653 | + */ | |
| 645 | 654 | if (!strstr(line_ptr, m.match)) { |
| 655 | + cur_line = -1; | |
| 656 | + line_ptr = strtok(NULL, "\n"); | |
| 657 | + sscanf(line_ptr, "%u: ", &cur_line); | |
| 658 | + } | |
| 659 | + if (cur_line != m.line || !line_ptr || | |
| 660 | + !strstr(line_ptr, m.match)) { | |
| 646 | 661 | printf("Failed to find match %u: %s\n", |
| 647 | 662 | m.line, m.match); |
| 648 | 663 | ret = 1; |
| @@ -65,8 +65,8 @@ void serial_test_bpf_obj_id(void) · 64 unmodified lines | ||
| 65 | 65 | if (CHECK_FAIL(err)) |
| 66 | 66 | goto done; |
| 67 | 67 | |
| 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"); | |
| 70 | 70 | if (CHECK_FAIL(!prog)) |
| 71 | 71 | goto done; |
| 72 | 72 | links[i] = bpf_program__attach(prog); |
| @@ -217,7 +217,7 @@ static bool found; · 216 unmodified lines | ||
| 217 | 217 | static int libbpf_debug_print(enum libbpf_print_level level, |
| 218 | 218 | const char *format, va_list args) |
| 219 | 219 | { |
| 220 | − const char *log_buf; | |
| 220 | + const char *prog_name, *log_buf; | |
| 221 | 221 | |
| 222 | 222 | if (level != LIBBPF_WARN || |
| 223 | 223 | !strstr(format, "-- BEGIN PROG LOAD LOG --")) { |
| @@ -225,15 +225,14 @@ static int libbpf_debug_print(enum libbpf_print_level level, · 1 unmodified line | ||
| 225 | 225 | return 0; |
| 226 | 226 | } |
| 227 | 227 | |
| 228 | − /* skip prog_name */ | |
| 229 | − va_arg(args, char *); | |
| 228 | + prog_name = va_arg(args, char *); | |
| 230 | 229 | log_buf = va_arg(args, char *); |
| 231 | 230 | if (!log_buf) |
| 232 | 231 | goto out; |
| 233 | 232 | if (err_str && strstr(log_buf, err_str) != NULL) |
| 234 | 233 | found = true; |
| 235 | 234 | out: |
| 236 | − printf(format, log_buf); | |
| 235 | + printf(format, prog_name, log_buf); | |
| 237 | 236 | return 0; |
| 238 | 237 | } |
| 239 | 238 | |
| @@ -22,7 +22,6 @@ · 21 unmodified lines | ||
| 22 | 22 | #include <bpf/libbpf.h> |
| 23 | 23 | #include <bpf/btf.h> |
| 24 | 24 | |
| 25 | −#include "bpf_rlimit.h" | |
| 26 | 25 | #include "bpf_util.h" |
| 27 | 26 | #include "../test_btf.h" |
| 28 | 27 | #include "test_progs.h" |
| @@ -67,9 +67,9 @@ static int run_test(int cgroup_fd, int server_fd, int family, int type) · 66 unmodified lines | ||
| 67 | 67 | goto close_bpf_object; |
| 68 | 68 | } |
| 69 | 69 | |
| 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"); | |
| 73 | 73 | if (CHECK(!prog, "find_prog", "connect prog not found\n")) { |
| 74 | 74 | err = -EIO; |
| 75 | 75 | goto close_bpf_object; |
| @@ -83,9 +83,9 @@ static int run_test(int cgroup_fd, int server_fd, int family, int type) · 7 unmodified lines | ||
| 83 | 83 | goto close_bpf_object; |
| 84 | 84 | } |
| 85 | 85 | |
| 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"); | |
| 89 | 89 | if (CHECK(!prog, "find_prog", "getpeername prog not found\n")) { |
| 90 | 90 | err = -EIO; |
| 91 | 91 | goto close_bpf_object; |
| @@ -99,9 +99,9 @@ static int run_test(int cgroup_fd, int server_fd, int family, int type) · 7 unmodified lines | ||
| 99 | 99 | goto close_bpf_object; |
| 100 | 100 | } |
| 101 | 101 | |
| 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"); | |
| 105 | 105 | if (CHECK(!prog, "find_prog", "getsockname prog not found\n")) { |
| 106 | 106 | err = -EIO; |
| 107 | 107 | goto close_bpf_object; |
| @@ -10,7 +10,7 @@ static int duration = 0; · 9 unmodified lines | ||
| 10 | 10 | |
| 11 | 11 | #define STRUCT_TO_CHAR_PTR(struct_name) (const char *)&(struct struct_name) |
| 12 | 12 | |
| 13 | −#define MODULES_CASE(name, sec_name, tp_name) { \ | |
| 13 | +#define MODULES_CASE(name, pg_name, tp_name) { \ | |
| 14 | 14 | .case_name = name, \ |
| 15 | 15 | .bpf_obj_file = "test_core_reloc_module.o", \ |
| 16 | 16 | .btf_src_file = NULL, /* find in kernel module BTFs */ \ |
| @@ -28,7 +28,7 @@ static int duration = 0; · 11 unmodified lines | ||
| 28 | 28 | .comm_len = sizeof("test_progs"), \ |
| 29 | 29 | }, \ |
| 30 | 30 | .output_len = sizeof(struct core_reloc_module_output), \ |
| 31 | − .prog_sec_name = sec_name, \ | |
| 31 | + .prog_name = pg_name, \ | |
| 32 | 32 | .raw_tp_name = tp_name, \ |
| 33 | 33 | .trigger = __trigger_module_test_read, \ |
| 34 | 34 | .needs_testmod = true, \ |
| @@ -43,7 +43,9 @@ static int duration = 0; · 8 unmodified lines | ||
| 43 | 43 | #define FLAVORS_CASE_COMMON(name) \ |
| 44 | 44 | .case_name = #name, \ |
| 45 | 45 | .bpf_obj_file = "test_core_reloc_flavors.o", \ |
| 46 | − .btf_src_file = "btf__core_reloc_" #name ".o" \ | |
| 46 | + .btf_src_file = "btf__core_reloc_" #name ".o", \ | |
| 47 | + .raw_tp_name = "sys_enter", \ | |
| 48 | + .prog_name = "test_core_flavors" \ | |
| 47 | 49 | |
| 48 | 50 | #define FLAVORS_CASE(name) { \ |
| 49 | 51 | FLAVORS_CASE_COMMON(name), \ |
| @@ -66,7 +68,9 @@ static int duration = 0; · 16 unmodified lines | ||
| 66 | 68 | #define NESTING_CASE_COMMON(name) \ |
| 67 | 69 | .case_name = #name, \ |
| 68 | 70 | .bpf_obj_file = "test_core_reloc_nesting.o", \ |
| 69 | − .btf_src_file = "btf__core_reloc_" #name ".o" | |
| 71 | + .btf_src_file = "btf__core_reloc_" #name ".o", \ | |
| 72 | + .raw_tp_name = "sys_enter", \ | |
| 73 | + .prog_name = "test_core_nesting" \ | |
| 70 | 74 | |
| 71 | 75 | #define NESTING_CASE(name) { \ |
| 72 | 76 | NESTING_CASE_COMMON(name), \ |
| @@ -91,7 +95,9 @@ static int duration = 0; · 18 unmodified lines | ||
| 91 | 95 | #define ARRAYS_CASE_COMMON(name) \ |
| 92 | 96 | .case_name = #name, \ |
| 93 | 97 | .bpf_obj_file = "test_core_reloc_arrays.o", \ |
| 94 | − .btf_src_file = "btf__core_reloc_" #name ".o" | |
| 98 | + .btf_src_file = "btf__core_reloc_" #name ".o", \ | |
| 99 | + .raw_tp_name = "sys_enter", \ | |
| 100 | + .prog_name = "test_core_arrays" \ | |
| 95 | 101 | |
| 96 | 102 | #define ARRAYS_CASE(name) { \ |
| 97 | 103 | ARRAYS_CASE_COMMON(name), \ |
| @@ -123,7 +129,9 @@ static int duration = 0; · 25 unmodified lines | ||
| 123 | 129 | #define PRIMITIVES_CASE_COMMON(name) \ |
| 124 | 130 | .case_name = #name, \ |
| 125 | 131 | .bpf_obj_file = "test_core_reloc_primitives.o", \ |
| 126 | − .btf_src_file = "btf__core_reloc_" #name ".o" | |
| 132 | + .btf_src_file = "btf__core_reloc_" #name ".o", \ | |
| 133 | + .raw_tp_name = "sys_enter", \ | |
| 134 | + .prog_name = "test_core_primitives" \ | |
| 127 | 135 | |
| 128 | 136 | #define PRIMITIVES_CASE(name) { \ |
| 129 | 137 | PRIMITIVES_CASE_COMMON(name), \ |
| @@ -158,6 +166,8 @@ static int duration = 0; · 28 unmodified lines | ||
| 158 | 166 | .e = 5, .f = 6, .g = 7, .h = 8, \ |
| 159 | 167 | }, \ |
| 160 | 168 | .output_len = sizeof(struct core_reloc_mods_output), \ |
| 169 | + .raw_tp_name = "sys_enter", \ | |
| 170 | + .prog_name = "test_core_mods", \ | |
| 161 | 171 | } |
| 162 | 172 | |
| 163 | 173 | #define PTR_AS_ARR_CASE(name) { \ |
| @@ -174,6 +184,8 @@ static int duration = 0; · 10 unmodified lines | ||
| 174 | 184 | .a = 3, \ |
| 175 | 185 | }, \ |
| 176 | 186 | .output_len = sizeof(struct core_reloc_ptr_as_arr), \ |
| 187 | + .raw_tp_name = "sys_enter", \ | |
| 188 | + .prog_name = "test_core_ptr_as_arr", \ | |
| 177 | 189 | } |
| 178 | 190 | |
| 179 | 191 | #define INTS_DATA(struct_name) STRUCT_TO_CHAR_PTR(struct_name) { \ |
| @@ -190,7 +202,9 @@ static int duration = 0; · 10 unmodified lines | ||
| 190 | 202 | #define INTS_CASE_COMMON(name) \ |
| 191 | 203 | .case_name = #name, \ |
| 192 | 204 | .bpf_obj_file = "test_core_reloc_ints.o", \ |
| 193 | − .btf_src_file = "btf__core_reloc_" #name ".o" | |
| 205 | + .btf_src_file = "btf__core_reloc_" #name ".o", \ | |
| 206 | + .raw_tp_name = "sys_enter", \ | |
| 207 | + .prog_name = "test_core_ints" | |
| 194 | 208 | |
| 195 | 209 | #define INTS_CASE(name) { \ |
| 196 | 210 | INTS_CASE_COMMON(name), \ |
| @@ -208,7 +222,9 @@ static int duration = 0; · 11 unmodified lines | ||
| 208 | 222 | #define FIELD_EXISTS_CASE_COMMON(name) \ |
| 209 | 223 | .case_name = #name, \ |
| 210 | 224 | .bpf_obj_file = "test_core_reloc_existence.o", \ |
| 211 | − .btf_src_file = "btf__core_reloc_" #name ".o" \ | |
| 225 | + .btf_src_file = "btf__core_reloc_" #name ".o", \ | |
| 226 | + .raw_tp_name = "sys_enter", \ | |
| 227 | + .prog_name = "test_core_existence" | |
| 212 | 228 | |
| 213 | 229 | #define BITFIELDS_CASE_COMMON(objfile, test_name_prefix, name) \ |
| 214 | 230 | .case_name = test_name_prefix#name, \ |
| @@ -223,6 +239,8 @@ static int duration = 0; · 8 unmodified lines | ||
| 223 | 239 | .output = STRUCT_TO_CHAR_PTR(core_reloc_bitfields_output) \ |
| 224 | 240 | __VA_ARGS__, \ |
| 225 | 241 | .output_len = sizeof(struct core_reloc_bitfields_output), \ |
| 242 | + .raw_tp_name = "sys_enter", \ | |
| 243 | + .prog_name = "test_core_bitfields", \ | |
| 226 | 244 | }, { \ |
| 227 | 245 | BITFIELDS_CASE_COMMON("test_core_reloc_bitfields_direct.o", \ |
| 228 | 246 | "direct:", name), \ |
| @@ -231,7 +249,7 @@ static int duration = 0; · 2 unmodified lines | ||
| 231 | 249 | .output = STRUCT_TO_CHAR_PTR(core_reloc_bitfields_output) \ |
| 232 | 250 | __VA_ARGS__, \ |
| 233 | 251 | .output_len = sizeof(struct core_reloc_bitfields_output), \ |
| 234 | − .prog_sec_name = "tp_btf/sys_enter", \ | |
| 252 | + .prog_name = "test_core_bitfields_direct", \ | |
| 235 | 253 | } |
| 236 | 254 | |
| 237 | 255 | |
| @@ -239,17 +257,21 @@ static int duration = 0; · 1 unmodified line | ||
| 239 | 257 | BITFIELDS_CASE_COMMON("test_core_reloc_bitfields_probed.o", \ |
| 240 | 258 | "probed:", name), \ |
| 241 | 259 | .fails = true, \ |
| 260 | + .raw_tp_name = "sys_enter", \ | |
| 261 | + .prog_name = "test_core_bitfields", \ | |
| 242 | 262 | }, { \ |
| 243 | 263 | BITFIELDS_CASE_COMMON("test_core_reloc_bitfields_direct.o", \ |
| 244 | 264 | "direct:", name), \ |
| 245 | − .prog_sec_name = "tp_btf/sys_enter", \ | |
| 246 | 265 | .fails = true, \ |
| 266 | + .prog_name = "test_core_bitfields_direct", \ | |
| 247 | 267 | } |
| 248 | 268 | |
| 249 | 269 | #define SIZE_CASE_COMMON(name) \ |
| 250 | 270 | .case_name = #name, \ |
| 251 | 271 | .bpf_obj_file = "test_core_reloc_size.o", \ |
| 252 | − .btf_src_file = "btf__core_reloc_" #name ".o" | |
| 272 | + .btf_src_file = "btf__core_reloc_" #name ".o", \ | |
| 273 | + .raw_tp_name = "sys_enter", \ | |
| 274 | + .prog_name = "test_core_size" | |
| 253 | 275 | |
| 254 | 276 | #define SIZE_OUTPUT_DATA(type) \ |
| 255 | 277 | STRUCT_TO_CHAR_PTR(core_reloc_size_output) { \ |
| @@ -277,8 +299,10 @@ static int duration = 0; · 21 unmodified lines | ||
| 277 | 299 | |
| 278 | 300 | #define TYPE_BASED_CASE_COMMON(name) \ |
| 279 | 301 | .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" | |
| 282 | 306 | |
| 283 | 307 | #define TYPE_BASED_CASE(name, ...) { \ |
| 284 | 308 | TYPE_BASED_CASE_COMMON(name), \ |
| @@ -295,7 +319,9 @@ static int duration = 0; · 10 unmodified lines | ||
| 295 | 319 | #define TYPE_ID_CASE_COMMON(name) \ |
| 296 | 320 | .case_name = #name, \ |
| 297 | 321 | .bpf_obj_file = "test_core_reloc_type_id.o", \ |
| 298 | − .btf_src_file = "btf__core_reloc_" #name ".o" \ | |
| 322 | + .btf_src_file = "btf__core_reloc_" #name ".o", \ | |
| 323 | + .raw_tp_name = "sys_enter", \ | |
| 324 | + .prog_name = "test_core_type_id" | |
| 299 | 325 | |
| 300 | 326 | #define TYPE_ID_CASE(name, setup_fn) { \ |
| 301 | 327 | TYPE_ID_CASE_COMMON(name), \ |
| @@ -312,7 +338,9 @@ static int duration = 0; · 10 unmodified lines | ||
| 312 | 338 | #define ENUMVAL_CASE_COMMON(name) \ |
| 313 | 339 | .case_name = #name, \ |
| 314 | 340 | .bpf_obj_file = "test_core_reloc_enumval.o", \ |
| 315 | − .btf_src_file = "btf__core_reloc_" #name ".o" \ | |
| 341 | + .btf_src_file = "btf__core_reloc_" #name ".o", \ | |
| 342 | + .raw_tp_name = "sys_enter", \ | |
| 343 | + .prog_name = "test_core_enumval" | |
| 316 | 344 | |
| 317 | 345 | #define ENUMVAL_CASE(name, ...) { \ |
| 318 | 346 | ENUMVAL_CASE_COMMON(name), \ |
| @@ -342,7 +370,7 @@ struct core_reloc_test_case { · 23 unmodified lines | ||
| 342 | 370 | bool fails; |
| 343 | 371 | bool needs_testmod; |
| 344 | 372 | bool relaxed_core_relocs; |
| 345 | − const char *prog_sec_name; | |
| 373 | + const char *prog_name; | |
| 346 | 374 | const char *raw_tp_name; |
| 347 | 375 | setup_test_fn setup; |
| 348 | 376 | trigger_test_fn trigger; |
| @@ -497,11 +525,13 @@ static struct core_reloc_test_case test_cases[] = { · 148 unmodified lines | ||
| 497 | 525 | .comm_len = sizeof("test_progs"), |
| 498 | 526 | }, |
| 499 | 527 | .output_len = sizeof(struct core_reloc_kernel_output), |
| 528 | + .raw_tp_name = "sys_enter", | |
| 529 | + .prog_name = "test_core_kernel", | |
| 500 | 530 | }, |
| 501 | 531 | |
| 502 | 532 | /* validate we can find kernel module BTF types for relocs/attach */ |
| 503 | − MODULES_CASE("module_probed", "raw_tp/bpf_testmod_test_read", "bpf_testmod_test_read"), | |
| 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), | |
| 505 | 535 | |
| 506 | 536 | /* validate BPF program can use multiple flavors to match against |
| 507 | 537 | * single target BTF type |
| @@ -580,6 +610,8 @@ static struct core_reloc_test_case test_cases[] = { · 72 unmodified lines | ||
| 580 | 610 | .c = 0, /* BUG in clang, should be 3 */ |
| 581 | 611 | }, |
| 582 | 612 | .output_len = sizeof(struct core_reloc_misc_output), |
| 613 | + .raw_tp_name = "sys_enter", | |
| 614 | + .prog_name = "test_core_misc", | |
| 583 | 615 | }, |
| 584 | 616 | |
| 585 | 617 | /* validate field existence checks */ |
| @@ -848,14 +880,9 @@ void test_core_reloc(void) · 262 unmodified lines | ||
| 848 | 880 | if (!ASSERT_OK_PTR(obj, "obj_open")) |
| 849 | 881 | goto cleanup; |
| 850 | 882 | |
| 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); | |
| 859 | 886 | if (CHECK(!prog, "find_probe", |
| 860 | 887 | "prog '%s' not found\n", probe_name)) |
| 861 | 888 | goto cleanup; |
| @@ -101,6 +101,8 @@ static void test_fexit_bpf2bpf_common(const char *obj_file, · 100 unmodified lines | ||
| 101 | 101 | |
| 102 | 102 | for (i = 0; i < prog_cnt; i++) { |
| 103 | 103 | struct bpf_link_info link_info; |
| 104 | + struct bpf_program *pos; | |
| 105 | + const char *pos_sec_name; | |
| 104 | 106 | char *tgt_name; |
| 105 | 107 | __s32 btf_id; |
| 106 | 108 | |
| @@ -109,7 +111,14 @@ static void test_fexit_bpf2bpf_common(const char *obj_file, · 2 unmodified lines | ||
| 109 | 111 | goto close_prog; |
| 110 | 112 | btf_id = btf__find_by_name_kind(btf, tgt_name + 1, BTF_KIND_FUNC); |
| 111 | 113 | |
| 112 | − prog[i] = bpf_object__find_program_by_title(obj, prog_name[i]); | |
| 114 | + prog[i] = NULL; | |
| 115 | + bpf_object__for_each_program(pos, obj) { | |
| 116 | + pos_sec_name = bpf_program__section_name(pos); | |
| 117 | + if (pos_sec_name && !strcmp(pos_sec_name, prog_name[i])) { | |
| 118 | + prog[i] = pos; | |
| 119 | + break; | |
| 120 | + } | |
| 121 | + } | |
| 113 | 122 | if (!ASSERT_OK_PTR(prog[i], prog_name[i])) |
| 114 | 123 | goto close_prog; |
| 115 | 124 | |
| @@ -211,8 +220,8 @@ static void test_func_replace_verify(void) · 95 unmodified lines | ||
| 211 | 220 | |
| 212 | 221 | static int test_second_attach(struct bpf_object *obj) |
| 213 | 222 | { |
| 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"; | |
| 216 | 225 | const char *tgt_obj_file = "./test_pkt_access.o"; |
| 217 | 226 | struct bpf_program *prog = NULL; |
| 218 | 227 | struct bpf_object *tgt_obj; |
| @@ -220,7 +229,7 @@ static int test_second_attach(struct bpf_object *obj) · 1 unmodified line | ||
| 220 | 229 | struct bpf_link *link; |
| 221 | 230 | int err = 0, tgt_fd; |
| 222 | 231 | |
| 223 | − prog = bpf_object__find_program_by_title(obj, prog_name); | |
| 232 | + prog = bpf_object__find_program_by_name(obj, prog_name); | |
| 224 | 233 | if (CHECK(!prog, "find_prog", "prog %s not found\n", prog_name)) |
| 225 | 234 | return -ENOENT; |
| 226 | 235 | |
| @@ -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 | +} | |
| @@ -89,7 +89,7 @@ void test_get_stack_raw_tp(void) · 88 unmodified lines | ||
| 89 | 89 | { |
| 90 | 90 | const char *file = "./test_get_stack_rawtp.o"; |
| 91 | 91 | const char *file_err = "./test_get_stack_rawtp_err.o"; |
| 92 | − const char *prog_name = "raw_tracepoint/sys_enter"; | |
| 92 | + const char *prog_name = "bpf_prog1"; | |
| 93 | 93 | int i, err, prog_fd, exp_cnt = MAX_CNT_RAWTP; |
| 94 | 94 | struct perf_buffer *pb = NULL; |
| 95 | 95 | struct bpf_link *link = NULL; |
| @@ -107,7 +107,7 @@ void test_get_stack_raw_tp(void) · 11 unmodified lines | ||
| 107 | 107 | if (CHECK(err, "prog_load raw tp", "err %d errno %d\n", err, errno)) |
| 108 | 108 | return; |
| 109 | 109 | |
| 110 | − prog = bpf_object__find_program_by_title(obj, prog_name); | |
| 110 | + prog = bpf_object__find_program_by_name(obj, prog_name); | |
| 111 | 111 | if (CHECK(!prog, "find_probe", "prog '%s' not found\n", prog_name)) |
| 112 | 112 | goto close_prog; |
| 113 | 113 | |
| @@ -8,6 +8,7 @@ · 7 unmodified lines | ||
| 8 | 8 | #include "test_ksyms_btf_null_check.skel.h" |
| 9 | 9 | #include "test_ksyms_weak.skel.h" |
| 10 | 10 | #include "test_ksyms_weak.lskel.h" |
| 11 | +#include "test_ksyms_btf_write_check.skel.h" | |
| 11 | 12 | |
| 12 | 13 | static int duration; |
| 13 | 14 | |
| @@ -137,6 +138,16 @@ cleanup: · 123 unmodified lines | ||
| 137 | 138 | test_ksyms_weak_lskel__destroy(skel); |
| 138 | 139 | } |
| 139 | 140 | |
| 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 | + | |
| 140 | 151 | void test_ksyms_btf(void) |
| 141 | 152 | { |
| 142 | 153 | int percpu_datasec; |
| @@ -167,4 +178,7 @@ void test_ksyms_btf(void) · 24 unmodified lines | ||
| 167 | 178 | |
| 168 | 179 | if (test__start_subtest("weak_ksyms_lskel")) |
| 169 | 180 | test_weak_syms_lskel(); |
| 181 | + | |
| 182 | + if (test__start_subtest("write_check")) | |
| 183 | + test_write_check(); | |
| 170 | 184 | } |
| @@ -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 | +} | |
| @@ -18,7 +18,6 @@ · 17 unmodified lines | ||
| 18 | 18 | #include <netinet/in.h> |
| 19 | 19 | #include <bpf/bpf.h> |
| 20 | 20 | #include <bpf/libbpf.h> |
| 21 | −#include "bpf_rlimit.h" | |
| 22 | 21 | #include "bpf_util.h" |
| 23 | 22 | |
| 24 | 23 | #include "test_progs.h" |
| @@ -30,7 +30,6 @@ · 29 unmodified lines | ||
| 30 | 30 | #include <bpf/bpf.h> |
| 31 | 31 | |
| 32 | 32 | #include "test_progs.h" |
| 33 | −#include "bpf_rlimit.h" | |
| 34 | 33 | #include "bpf_util.h" |
| 35 | 34 | #include "cgroup_helpers.h" |
| 36 | 35 | #include "network_helpers.h" |
| @@ -15,7 +15,6 @@ · 14 unmodified lines | ||
| 15 | 15 | #include "network_helpers.h" |
| 16 | 16 | #include "cgroup_helpers.h" |
| 17 | 17 | #include "test_progs.h" |
| 18 | −#include "bpf_rlimit.h" | |
| 19 | 18 | #include "test_sock_fields.skel.h" |
| 20 | 19 | |
| 21 | 20 | enum bpf_linum_array_idx { |
| @@ -136,7 +136,8 @@ static int start_server(void) · 135 unmodified lines | ||
| 136 | 136 | return fd; |
| 137 | 137 | } |
| 138 | 138 | |
| 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) | |
| 140 | 141 | { |
| 141 | 142 | enum bpf_attach_type attach_type; |
| 142 | 143 | enum bpf_prog_type prog_type; |
| @@ -145,20 +146,20 @@ static int prog_attach(struct bpf_object *obj, int cgroup_fd, const char *title) · 2 unmodified lines | ||
| 145 | 146 | |
| 146 | 147 | err = libbpf_prog_type_by_name(title, &prog_type, &attach_type); |
| 147 | 148 | if (err) { |
| 148 | − log_err("Failed to deduct types for %s BPF program", title); | |
| 149 | + log_err("Failed to deduct types for %s BPF program", prog_name); | |
| 149 | 150 | return -1; |
| 150 | 151 | } |
| 151 | 152 | |
| 152 | − prog = bpf_object__find_program_by_title(obj, title); | |
| 153 | + prog = bpf_object__find_program_by_name(obj, prog_name); | |
| 153 | 154 | if (!prog) { |
| 154 | − log_err("Failed to find %s BPF program", title); | |
| 155 | + log_err("Failed to find %s BPF program", prog_name); | |
| 155 | 156 | return -1; |
| 156 | 157 | } |
| 157 | 158 | |
| 158 | 159 | err = bpf_prog_attach(bpf_program__fd(prog), cgroup_fd, |
| 159 | 160 | attach_type, 0); |
| 160 | 161 | if (err) { |
| 161 | − log_err("Failed to attach %s BPF program", title); | |
| 162 | + log_err("Failed to attach %s BPF program", prog_name); | |
| 162 | 163 | return -1; |
| 163 | 164 | } |
| 164 | 165 | |
| @@ -181,11 +182,11 @@ static void run_test(int cgroup_fd) · 16 unmodified lines | ||
| 181 | 182 | if (!ASSERT_OK(err, "obj_load")) |
| 182 | 183 | goto close_bpf_object; |
| 183 | 184 | |
| 184 | − err = prog_attach(obj, cgroup_fd, "cgroup/getsockopt"); | |
| 185 | + err = prog_attach(obj, cgroup_fd, "cgroup/getsockopt", "_getsockopt"); | |
| 185 | 186 | if (CHECK_FAIL(err)) |
| 186 | 187 | goto close_bpf_object; |
| 187 | 188 | |
| 188 | − err = prog_attach(obj, cgroup_fd, "cgroup/setsockopt"); | |
| 189 | + err = prog_attach(obj, cgroup_fd, "cgroup/setsockopt", "_setsockopt"); | |
| 189 | 190 | if (CHECK_FAIL(err)) |
| 190 | 191 | goto close_bpf_object; |
| 191 | 192 | |
| @@ -4,7 +4,7 @@ · 3 unmodified lines | ||
| 4 | 4 | void test_stacktrace_map(void) |
| 5 | 5 | { |
| 6 | 6 | int control_map_fd, stackid_hmap_fd, stackmap_fd, stack_amap_fd; |
| 7 | − const char *prog_name = "tracepoint/sched/sched_switch"; | |
| 7 | + const char *prog_name = "oncpu"; | |
| 8 | 8 | int err, prog_fd, stack_trace_len; |
| 9 | 9 | const char *file = "./test_stacktrace_map.o"; |
| 10 | 10 | __u32 key, val, duration = 0; |
| @@ -16,7 +16,7 @@ void test_stacktrace_map(void) · 5 unmodified lines | ||
| 16 | 16 | if (CHECK(err, "prog_load", "err %d errno %d\n", err, errno)) |
| 17 | 17 | return; |
| 18 | 18 | |
| 19 | − prog = bpf_object__find_program_by_title(obj, prog_name); | |
| 19 | + prog = bpf_object__find_program_by_name(obj, prog_name); | |
| 20 | 20 | if (CHECK(!prog, "find_prog", "prog '%s' not found\n", prog_name)) |
| 21 | 21 | goto close_prog; |
| 22 | 22 | |
| @@ -3,7 +3,7 @@ · 2 unmodified lines | ||
| 3 | 3 | |
| 4 | 4 | void test_stacktrace_map_raw_tp(void) |
| 5 | 5 | { |
| 6 | − const char *prog_name = "tracepoint/sched/sched_switch"; | |
| 6 | + const char *prog_name = "oncpu"; | |
| 7 | 7 | int control_map_fd, stackid_hmap_fd, stackmap_fd; |
| 8 | 8 | const char *file = "./test_stacktrace_map.o"; |
| 9 | 9 | __u32 key, val, duration = 0; |
| @@ -16,7 +16,7 @@ void test_stacktrace_map_raw_tp(void) · 6 unmodified lines | ||
| 16 | 16 | if (CHECK(err, "prog_load raw tp", "err %d errno %d\n", err, errno)) |
| 17 | 17 | return; |
| 18 | 18 | |
| 19 | − prog = bpf_object__find_program_by_title(obj, prog_name); | |
| 19 | + prog = bpf_object__find_program_by_name(obj, prog_name); | |
| 20 | 20 | if (CHECK(!prog, "find_prog", "prog '%s' not found\n", prog_name)) |
| 21 | 21 | goto close_prog; |
| 22 | 22 | |
| @@ -28,10 +28,6 @@ static unsigned int duration; · 27 unmodified lines | ||
| 28 | 28 | struct storage { |
| 29 | 29 | void *inode; |
| 30 | 30 | unsigned int value; |
| 31 | − /* Lock ensures that spin locked versions of local stoage operations | |
| 32 | − * also work, most operations in this tests are still single threaded | |
| 33 | − */ | |
| 34 | − struct bpf_spin_lock lock; | |
| 35 | 31 | }; |
| 36 | 32 | |
| 37 | 33 | /* Fork and exec the provided rm binary and return the exit code of the |
| @@ -66,27 +62,24 @@ static int run_self_unlink(int *monitored_pid, const char *rm_path) · 28 unmodified lines | ||
| 66 | 62 | |
| 67 | 63 | static bool check_syscall_operations(int map_fd, int obj_fd) |
| 68 | 64 | { |
| 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 }; | |
| 71 | 67 | int err; |
| 72 | 68 | |
| 73 | 69 | /* 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); | |
| 76 | 71 | if (CHECK(!err || errno != ENOENT, "bpf_map_lookup_elem", |
| 77 | 72 | "err:%d errno:%d\n", err, errno)) |
| 78 | 73 | return false; |
| 79 | 74 | |
| 80 | 75 | /* 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); | |
| 83 | 77 | if (CHECK(err < 0, "bpf_map_update_elem", "err:%d errno:%d\n", err, |
| 84 | 78 | errno)) |
| 85 | 79 | return false; |
| 86 | 80 | |
| 87 | 81 | /* 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); | |
| 90 | 83 | if (CHECK(err < 0, "bpf_map_lookup_elem", "err:%d errno:%d", err, |
| 91 | 84 | errno)) |
| 92 | 85 | return false; |
| @@ -102,8 +95,7 @@ static bool check_syscall_operations(int map_fd, int obj_fd) · 9 unmodified lines | ||
| 102 | 95 | return false; |
| 103 | 96 | |
| 104 | 97 | /* The lookup should fail, now that the element has been deleted */ |
| 105 | − err = bpf_map_lookup_elem_flags(map_fd, &obj_fd, &lookup_val, | |
| 106 | − BPF_F_LOCK); | |
| 98 | + err = bpf_map_lookup_elem_flags(map_fd, &obj_fd, &lookup_val, 0); | |
| 107 | 99 | if (CHECK(!err || errno != ENOENT, "bpf_map_lookup_elem", |
| 108 | 100 | "err:%d errno:%d\n", err, errno)) |
| 109 | 101 | return false; |
| @@ -56,11 +56,11 @@ static void setaffinity(void) · 55 unmodified lines | ||
| 56 | 56 | |
| 57 | 57 | void test_test_overhead(void) |
| 58 | 58 | { |
| 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"; | |
| 64 | 64 | const char *kprobe_func = "__set_task_comm"; |
| 65 | 65 | struct bpf_program *kprobe_prog, *kretprobe_prog, *raw_tp_prog; |
| 66 | 66 | struct bpf_program *fentry_prog, *fexit_prog; |
| @@ -76,23 +76,23 @@ void test_test_overhead(void) · 9 unmodified lines | ||
| 76 | 76 | if (!ASSERT_OK_PTR(obj, "obj_open_file")) |
| 77 | 77 | return; |
| 78 | 78 | |
| 79 | − kprobe_prog = bpf_object__find_program_by_title(obj, kprobe_name); | |
| 79 | + kprobe_prog = bpf_object__find_program_by_name(obj, kprobe_name); | |
| 80 | 80 | if (CHECK(!kprobe_prog, "find_probe", |
| 81 | 81 | "prog '%s' not found\n", kprobe_name)) |
| 82 | 82 | goto cleanup; |
| 83 | − kretprobe_prog = bpf_object__find_program_by_title(obj, kretprobe_name); | |
| 83 | + kretprobe_prog = bpf_object__find_program_by_name(obj, kretprobe_name); | |
| 84 | 84 | if (CHECK(!kretprobe_prog, "find_probe", |
| 85 | 85 | "prog '%s' not found\n", kretprobe_name)) |
| 86 | 86 | goto cleanup; |
| 87 | − raw_tp_prog = bpf_object__find_program_by_title(obj, raw_tp_name); | |
| 87 | + raw_tp_prog = bpf_object__find_program_by_name(obj, raw_tp_name); | |
| 88 | 88 | if (CHECK(!raw_tp_prog, "find_probe", |
| 89 | 89 | "prog '%s' not found\n", raw_tp_name)) |
| 90 | 90 | goto cleanup; |
| 91 | − fentry_prog = bpf_object__find_program_by_title(obj, fentry_name); | |
| 91 | + fentry_prog = bpf_object__find_program_by_name(obj, fentry_name); | |
| 92 | 92 | if (CHECK(!fentry_prog, "find_probe", |
| 93 | 93 | "prog '%s' not found\n", fentry_name)) |
| 94 | 94 | goto cleanup; |
| 95 | − fexit_prog = bpf_object__find_program_by_title(obj, fexit_name); | |
| 95 | + fexit_prog = bpf_object__find_program_by_name(obj, fexit_name); | |
| 96 | 96 | if (CHECK(!fexit_prog, "find_probe", |
| 97 | 97 | "prog '%s' not found\n", fexit_name)) |
| 98 | 98 | goto cleanup; |
| @@ -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 | +} | |
| @@ -35,7 +35,7 @@ static struct bpf_link *load(struct bpf_object *obj, const char *name) · 34 unmodified lines | ||
| 35 | 35 | struct bpf_program *prog; |
| 36 | 36 | int duration = 0; |
| 37 | 37 | |
| 38 | − prog = bpf_object__find_program_by_title(obj, name); | |
| 38 | + prog = bpf_object__find_program_by_name(obj, name); | |
| 39 | 39 | if (CHECK(!prog, "find_probe", "prog '%s' not found\n", name)) |
| 40 | 40 | return ERR_PTR(-EINVAL); |
| 41 | 41 | return bpf_program__attach_trace(prog); |
| @@ -44,8 +44,8 @@ static struct bpf_link *load(struct bpf_object *obj, const char *name) · 2 unmodified lines | ||
| 44 | 44 | /* TODO: use different target function to run in concurrent mode */ |
| 45 | 45 | void serial_test_trampoline_count(void) |
| 46 | 46 | { |
| 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"; | |
| 49 | 49 | const char *object = "test_trampoline_count.o"; |
| 50 | 50 | struct inst inst[MAX_TRAMP_PROGS] = {}; |
| 51 | 51 | int err, i = 0, duration = 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 | +} | |
| @@ -20,7 +20,6 @@ int sk_storage_result = -1; · 19 unmodified lines | ||
| 20 | 20 | struct local_storage { |
| 21 | 21 | struct inode *exec_inode; |
| 22 | 22 | __u32 value; |
| 23 | − struct bpf_spin_lock lock; | |
| 24 | 23 | }; |
| 25 | 24 | |
| 26 | 25 | struct { |
| @@ -58,9 +57,7 @@ int BPF_PROG(unlink_hook, struct inode *dir, struct dentry *victim) · 31 unmodified lines | ||
| 58 | 57 | bpf_get_current_task_btf(), 0, 0); |
| 59 | 58 | if (storage) { |
| 60 | 59 | /* Don't let an executable delete itself */ |
| 61 | − bpf_spin_lock(&storage->lock); | |
| 62 | 60 | is_self_unlink = storage->exec_inode == victim->d_inode; |
| 63 | − bpf_spin_unlock(&storage->lock); | |
| 64 | 61 | if (is_self_unlink) |
| 65 | 62 | return -EPERM; |
| 66 | 63 | } |
| @@ -68,7 +65,7 @@ int BPF_PROG(unlink_hook, struct inode *dir, struct dentry *victim) · 1 unmodified line | ||
| 68 | 65 | return 0; |
| 69 | 66 | } |
| 70 | 67 | |
| 71 | −SEC("lsm/inode_rename") | |
| 68 | +SEC("lsm.s/inode_rename") | |
| 72 | 69 | int BPF_PROG(inode_rename, struct inode *old_dir, struct dentry *old_dentry, |
| 73 | 70 | struct inode *new_dir, struct dentry *new_dentry, |
| 74 | 71 | unsigned int flags) |
| @@ -89,10 +86,8 @@ int BPF_PROG(inode_rename, struct inode *old_dir, struct dentry *old_dentry, · 14 unmodified lines | ||
| 89 | 86 | if (!storage) |
| 90 | 87 | return 0; |
| 91 | 88 | |
| 92 | − bpf_spin_lock(&storage->lock); | |
| 93 | 89 | if (storage->value != DUMMY_STORAGE_VALUE) |
| 94 | 90 | inode_storage_result = -1; |
| 95 | − bpf_spin_unlock(&storage->lock); | |
| 96 | 91 | |
| 97 | 92 | err = bpf_inode_storage_delete(&inode_storage_map, old_dentry->d_inode); |
| 98 | 93 | if (!err) |
| @@ -101,7 +96,7 @@ int BPF_PROG(inode_rename, struct inode *old_dir, struct dentry *old_dentry, · 2 unmodified lines | ||
| 101 | 96 | return 0; |
| 102 | 97 | } |
| 103 | 98 | |
| 104 | −SEC("lsm/socket_bind") | |
| 99 | +SEC("lsm.s/socket_bind") | |
| 105 | 100 | int BPF_PROG(socket_bind, struct socket *sock, struct sockaddr *address, |
| 106 | 101 | int addrlen) |
| 107 | 102 | { |
| @@ -117,10 +112,8 @@ int BPF_PROG(socket_bind, struct socket *sock, struct sockaddr *address, · 9 unmodified lines | ||
| 117 | 112 | if (!storage) |
| 118 | 113 | return 0; |
| 119 | 114 | |
| 120 | − bpf_spin_lock(&storage->lock); | |
| 121 | 115 | if (storage->value != DUMMY_STORAGE_VALUE) |
| 122 | 116 | sk_storage_result = -1; |
| 123 | − bpf_spin_unlock(&storage->lock); | |
| 124 | 117 | |
| 125 | 118 | err = bpf_sk_storage_delete(&sk_storage_map, sock->sk); |
| 126 | 119 | if (!err) |
| @@ -129,7 +122,7 @@ int BPF_PROG(socket_bind, struct socket *sock, struct sockaddr *address, · 2 unmodified lines | ||
| 129 | 122 | return 0; |
| 130 | 123 | } |
| 131 | 124 | |
| 132 | −SEC("lsm/socket_post_create") | |
| 125 | +SEC("lsm.s/socket_post_create") | |
| 133 | 126 | int BPF_PROG(socket_post_create, struct socket *sock, int family, int type, |
| 134 | 127 | int protocol, int kern) |
| 135 | 128 | { |
| @@ -144,9 +137,7 @@ int BPF_PROG(socket_post_create, struct socket *sock, int family, int type, · 8 unmodified lines | ||
| 144 | 137 | if (!storage) |
| 145 | 138 | return 0; |
| 146 | 139 | |
| 147 | − bpf_spin_lock(&storage->lock); | |
| 148 | 140 | storage->value = DUMMY_STORAGE_VALUE; |
| 149 | − bpf_spin_unlock(&storage->lock); | |
| 150 | 141 | |
| 151 | 142 | return 0; |
| 152 | 143 | } |
| @@ -154,7 +145,7 @@ int BPF_PROG(socket_post_create, struct socket *sock, int family, int type, · 1 unmodified line | ||
| 154 | 145 | /* This uses the local storage to remember the inode of the binary that a |
| 155 | 146 | * process was originally executing. |
| 156 | 147 | */ |
| 157 | −SEC("lsm/bprm_committed_creds") | |
| 148 | +SEC("lsm.s/bprm_committed_creds") | |
| 158 | 149 | void BPF_PROG(exec, struct linux_binprm *bprm) |
| 159 | 150 | { |
| 160 | 151 | __u32 pid = bpf_get_current_pid_tgid() >> 32; |
| @@ -166,18 +157,13 @@ void BPF_PROG(exec, struct linux_binprm *bprm) · 5 unmodified lines | ||
| 166 | 157 | storage = bpf_task_storage_get(&task_storage_map, |
| 167 | 158 | bpf_get_current_task_btf(), 0, |
| 168 | 159 | BPF_LOCAL_STORAGE_GET_F_CREATE); |
| 169 | − if (storage) { | |
| 170 | − bpf_spin_lock(&storage->lock); | |
| 160 | + if (storage) | |
| 171 | 161 | storage->exec_inode = bprm->file->f_inode; |
| 172 | − bpf_spin_unlock(&storage->lock); | |
| 173 | − } | |
| 174 | 162 | |
| 175 | 163 | storage = bpf_inode_storage_get(&inode_storage_map, bprm->file->f_inode, |
| 176 | 164 | 0, BPF_LOCAL_STORAGE_GET_F_CREATE); |
| 177 | 165 | if (!storage) |
| 178 | 166 | return; |
| 179 | 167 | |
| 180 | − bpf_spin_lock(&storage->lock); | |
| 181 | 168 | storage->value = DUMMY_STORAGE_VALUE; |
| 182 | − bpf_spin_unlock(&storage->lock); | |
| 183 | 169 | } |
| @@ -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 | + | |
| @@ -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 | +} | |
| @@ -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"; | |
| @@ -7,9 +7,15 @@ · 6 unmodified lines | ||
| 7 | 7 | |
| 8 | 8 | /* do nothing, just make sure we can link successfully */ |
| 9 | 9 | |
| 10 | +static void dump_printf(void *ctx, const char *fmt, va_list args) | |
| 11 | +{ | |
| 12 | +} | |
| 13 | + | |
| 10 | 14 | int main(int argc, char *argv[]) |
| 11 | 15 | { |
| 16 | + struct btf_dump_opts opts = { }; | |
| 12 | 17 | struct test_core_extern *skel; |
| 18 | + struct btf *btf; | |
| 13 | 19 | |
| 14 | 20 | /* libbpf.h */ |
| 15 | 21 | libbpf_set_print(NULL); |
| @@ -18,7 +24,8 @@ int main(int argc, char *argv[]) · 2 unmodified lines | ||
| 18 | 24 | bpf_prog_get_fd_by_id(0); |
| 19 | 25 | |
| 20 | 26 | /* btf.h */ |
| 21 | − btf__new(NULL, 0); | |
| 27 | + btf = btf__new(NULL, 0); | |
| 28 | + btf_dump__new(btf, dump_printf, nullptr, &opts); | |
| 22 | 29 | |
| 23 | 30 | /* BPF skeleton */ |
| 24 | 31 | skel = test_core_extern__open_and_load(); |
| @@ -23,7 +23,6 @@ · 22 unmodified lines | ||
| 23 | 23 | #include <bpf/libbpf.h> |
| 24 | 24 | |
| 25 | 25 | #include "bpf_util.h" |
| 26 | −#include "bpf_rlimit.h" | |
| 27 | 26 | #include "test_maps.h" |
| 28 | 27 | #include "testing_helpers.h" |
| 29 | 28 | |
| @@ -4,7 +4,6 @@ · 3 unmodified lines | ||
| 4 | 4 | #define _GNU_SOURCE |
| 5 | 5 | #include "test_progs.h" |
| 6 | 6 | #include "cgroup_helpers.h" |
| 7 | −#include "bpf_rlimit.h" | |
| 8 | 7 | #include <argp.h> |
| 9 | 8 | #include <pthread.h> |
| 10 | 9 | #include <sched.h> |
| @@ -1342,7 +1341,6 @@ int main(int argc, char **argv) · 1331 unmodified lines | ||
| 1342 | 1341 | |
| 1343 | 1342 | /* Use libbpf 1.0 API mode */ |
| 1344 | 1343 | libbpf_set_strict_mode(LIBBPF_STRICT_ALL); |
| 1345 | − | |
| 1346 | 1344 | libbpf_set_print(libbpf_print_fn); |
| 1347 | 1345 | |
| 1348 | 1346 | srand(time(NULL)); |
| @@ -41,7 +41,6 @@ · 40 unmodified lines | ||
| 41 | 41 | # define CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS 1 |
| 42 | 42 | # endif |
| 43 | 43 | #endif |
| 44 | −#include "bpf_rlimit.h" | |
| 45 | 44 | #include "bpf_rand.h" |
| 46 | 45 | #include "bpf_util.h" |
| 47 | 46 | #include "test_btf.h" |
| @@ -701,22 +700,18 @@ static int create_sk_storage_map(void) · 653 unmodified lines | ||
| 701 | 700 | |
| 702 | 701 | static int create_map_timer(void) |
| 703 | 702 | { |
| 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, | |
| 710 | 704 | .btf_key_type_id = 1, |
| 711 | 705 | .btf_value_type_id = 5, |
| 712 | − }; | |
| 706 | + ); | |
| 713 | 707 | int fd, btf_fd; |
| 714 | 708 | |
| 715 | 709 | btf_fd = load_btf(); |
| 716 | 710 | if (btf_fd < 0) |
| 717 | 711 | 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); | |
| 720 | 715 | if (fd < 0) |
| 721 | 716 | printf("Failed to create map with timer\n"); |
| 722 | 717 | return fd; |
| @@ -1399,6 +1394,9 @@ int main(int argc, char **argv) · 676 unmodified lines | ||
| 1399 | 1394 | return EXIT_FAILURE; |
| 1400 | 1395 | } |
| 1401 | 1396 | |
| 1397 | + /* Use libbpf 1.0 API mode */ | |
| 1398 | + libbpf_set_strict_mode(LIBBPF_STRICT_ALL); | |
| 1399 | + | |
| 1402 | 1400 | bpf_semi_rand_init(); |
| 1403 | 1401 | return do_test(unpriv, from, to); |
| 1404 | 1402 | } |
| @@ -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 | +}, | |
| @@ -32,7 +32,7 @@ ROOTFS_IMAGE="root.img" · 31 unmodified lines | ||
| 32 | 32 | OUTPUT_DIR="$HOME/.bpf_selftests" |
| 33 | 33 | KCONFIG_URL="https://raw.githubusercontent.com/libbpf/libbpf/master/travis-ci/vmtest/configs/config-latest.${ARCH}" |
| 34 | 34 | 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" | |
| 36 | 36 | NUM_COMPILE_JOBS="$(nproc)" |
| 37 | 37 | LOG_FILE_BASE="$(date +"bpf_selftests.%Y-%m-%d_%H-%M-%S")" |
| 38 | 38 | LOG_FILE="${LOG_FILE_BASE}.log" |