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/testing (42 of 221 files). Show all
Unified · Split
| @@ -170,7 +170,7 @@ $(OUTPUT)/%:%.c · 169 unmodified lines | |||
| 170 | 170 | ||
| 171 | $(OUTPUT)/urandom_read: urandom_read.c | 171 | $(OUTPUT)/urandom_read: urandom_read.c |
| 172 | $(call msg,BINARY,,$@) | 172 | $(call msg,BINARY,,$@) |
| 173 | $(Q)$(CC) $(LDFLAGS) $< $(LDLIBS) -Wl,--build-id=sha1 -o $@ | 173 | $(Q)$(CC) $(CFLAGS) $(LDFLAGS) $< $(LDLIBS) -Wl,--build-id=sha1 -o $@ |
| 174 | 174 | ||
| 175 | $(OUTPUT)/bpf_testmod.ko: $(VMLINUX_BTF) $(wildcard bpf_testmod/Makefile bpf_testmod/*.[ch]) | 175 | $(OUTPUT)/bpf_testmod.ko: $(VMLINUX_BTF) $(wildcard bpf_testmod/Makefile bpf_testmod/*.[ch]) |
| 176 | $(call msg,MOD,,$@) | 176 | $(call msg,MOD,,$@) |
| @@ -217,7 +217,7 @@ BPFTOOL ?= $(DEFAULT_BPFTOOL) · 40 unmodified lines | |||
| 217 | $(DEFAULT_BPFTOOL): $(wildcard $(BPFTOOLDIR)/*.[ch] $(BPFTOOLDIR)/Makefile) \ | 217 | $(DEFAULT_BPFTOOL): $(wildcard $(BPFTOOLDIR)/*.[ch] $(BPFTOOLDIR)/Makefile) \ |
| 218 | $(HOST_BPFOBJ) | $(HOST_BUILD_DIR)/bpftool | 218 | $(HOST_BPFOBJ) | $(HOST_BUILD_DIR)/bpftool |
| 219 | $(Q)$(MAKE) $(submake_extras) -C $(BPFTOOLDIR) \ | 219 | $(Q)$(MAKE) $(submake_extras) -C $(BPFTOOLDIR) \ |
| 220 | CC=$(HOSTCC) LD=$(HOSTLD) \ | 220 | ARCH= CROSS_COMPILE= CC=$(HOSTCC) LD=$(HOSTLD) \ |
| 221 | EXTRA_CFLAGS='-g -O0' \ | 221 | EXTRA_CFLAGS='-g -O0' \ |
| 222 | OUTPUT=$(HOST_BUILD_DIR)/bpftool/ \ | 222 | OUTPUT=$(HOST_BUILD_DIR)/bpftool/ \ |
| 223 | LIBBPF_OUTPUT=$(HOST_BUILD_DIR)/libbpf/ \ | 223 | LIBBPF_OUTPUT=$(HOST_BUILD_DIR)/libbpf/ \ |
| @@ -248,7 +248,7 @@ $(HOST_BPFOBJ): $(wildcard $(BPFDIR)/*.[ch] $(BPFDIR)/Makefile) \ · 24 unmodified lines | |||
| 248 | $(APIDIR)/linux/bpf.h \ | 248 | $(APIDIR)/linux/bpf.h \ |
| 249 | | $(HOST_BUILD_DIR)/libbpf | 249 | | $(HOST_BUILD_DIR)/libbpf |
| 250 | $(Q)$(MAKE) $(submake_extras) -C $(BPFDIR) \ | 250 | $(Q)$(MAKE) $(submake_extras) -C $(BPFDIR) \ |
| 251 | EXTRA_CFLAGS='-g -O0' \ | 251 | EXTRA_CFLAGS='-g -O0' ARCH= CROSS_COMPILE= \ |
| 252 | OUTPUT=$(HOST_BUILD_DIR)/libbpf/ CC=$(HOSTCC) LD=$(HOSTLD) \ | 252 | OUTPUT=$(HOST_BUILD_DIR)/libbpf/ CC=$(HOSTCC) LD=$(HOSTLD) \ |
| 253 | DESTDIR=$(HOST_SCRATCH_DIR)/ prefix= all install_headers | 253 | DESTDIR=$(HOST_SCRATCH_DIR)/ prefix= all install_headers |
| 254 | endif | 254 | endif |
| @@ -537,6 +537,7 @@ $(OUTPUT)/bench_ringbufs.o: $(OUTPUT)/ringbuf_bench.skel.h \ · 282 unmodified lines | |||
| 537 | $(OUTPUT)/perfbuf_bench.skel.h | 537 | $(OUTPUT)/perfbuf_bench.skel.h |
| 538 | $(OUTPUT)/bench_bloom_filter_map.o: $(OUTPUT)/bloom_filter_bench.skel.h | 538 | $(OUTPUT)/bench_bloom_filter_map.o: $(OUTPUT)/bloom_filter_bench.skel.h |
| 539 | $(OUTPUT)/bench_bpf_loop.o: $(OUTPUT)/bpf_loop_bench.skel.h | 539 | $(OUTPUT)/bench_bpf_loop.o: $(OUTPUT)/bpf_loop_bench.skel.h |
| 540 | $(OUTPUT)/bench_strncmp.o: $(OUTPUT)/strncmp_bench.skel.h | ||
| 540 | $(OUTPUT)/bench.o: bench.h testing_helpers.h $(BPFOBJ) | 541 | $(OUTPUT)/bench.o: bench.h testing_helpers.h $(BPFOBJ) |
| 541 | $(OUTPUT)/bench: LDLIBS += -lm | 542 | $(OUTPUT)/bench: LDLIBS += -lm |
| 542 | $(OUTPUT)/bench: $(OUTPUT)/bench.o \ | 543 | $(OUTPUT)/bench: $(OUTPUT)/bench.o \ |
| @@ -547,9 +548,10 @@ $(OUTPUT)/bench: $(OUTPUT)/bench.o \ · 4 unmodified lines | |||
| 547 | $(OUTPUT)/bench_trigger.o \ | 548 | $(OUTPUT)/bench_trigger.o \ |
| 548 | $(OUTPUT)/bench_ringbufs.o \ | 549 | $(OUTPUT)/bench_ringbufs.o \ |
| 549 | $(OUTPUT)/bench_bloom_filter_map.o \ | 550 | $(OUTPUT)/bench_bloom_filter_map.o \ |
| 550 | $(OUTPUT)/bench_bpf_loop.o | 551 | $(OUTPUT)/bench_bpf_loop.o \ |
| 552 | $(OUTPUT)/bench_strncmp.o | ||
| 551 | $(call msg,BINARY,,$@) | 553 | $(call msg,BINARY,,$@) |
| 552 | $(Q)$(CC) $(LDFLAGS) $(filter %.a %.o,$^) $(LDLIBS) -o $@ | 554 | $(Q)$(CC) $(CFLAGS) $(LDFLAGS) $(filter %.a %.o,$^) $(LDLIBS) -o $@ |
| 553 | 555 | ||
| 554 | EXTRA_CLEAN := $(TEST_CUSTOM_PROGS) $(SCRATCH_DIR) $(HOST_SCRATCH_DIR) \ | 556 | EXTRA_CLEAN := $(TEST_CUSTOM_PROGS) $(SCRATCH_DIR) $(HOST_SCRATCH_DIR) \ |
| 555 | prog_tests/tests.h map_tests/tests.h verifier/tests.h \ | 557 | prog_tests/tests.h map_tests/tests.h verifier/tests.h \ |
| @@ -29,26 +29,10 @@ static int libbpf_print_fn(enum libbpf_print_level level, · 28 unmodified lines | |||
| 29 | return vfprintf(stderr, format, args); | 29 | return vfprintf(stderr, format, args); |
| 30 | } | 30 | } |
| 31 | 31 | ||
| 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 | libbpf_set_strict_mode(LIBBPF_STRICT_ALL); | 34 | libbpf_set_strict_mode(LIBBPF_STRICT_ALL); |
| 47 | libbpf_set_print(libbpf_print_fn); | 35 | libbpf_set_print(libbpf_print_fn); |
| 48 | |||
| 49 | err = bump_memlock_rlimit(); | ||
| 50 | if (err) | ||
| 51 | fprintf(stderr, "failed to increase RLIMIT_MEMLOCK: %d", err); | ||
| 52 | } | 36 | } |
| 53 | 37 | ||
| 54 | void false_hits_report_progress(int iter, struct bench_res *res, long delta_ns) | 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 | extern struct argp bench_ringbufs_argp; | 189 | extern struct argp bench_ringbufs_argp; |
| 206 | extern struct argp bench_bloom_map_argp; | 190 | extern struct argp bench_bloom_map_argp; |
| 207 | extern struct argp bench_bpf_loop_argp; | 191 | extern struct argp bench_bpf_loop_argp; |
| 192 | extern struct argp bench_strncmp_argp; | ||
| 208 | 193 | ||
| 209 | static const struct argp_child bench_parsers[] = { | 194 | static const struct argp_child bench_parsers[] = { |
| 210 | { &bench_ringbufs_argp, 0, "Ring buffers benchmark", 0 }, | 195 | { &bench_ringbufs_argp, 0, "Ring buffers benchmark", 0 }, |
| 211 | { &bench_bloom_map_argp, 0, "Bloom filter map benchmark", 0 }, | 196 | { &bench_bloom_map_argp, 0, "Bloom filter map benchmark", 0 }, |
| 212 | { &bench_bpf_loop_argp, 0, "bpf_loop helper benchmark", 0 }, | 197 | { &bench_bpf_loop_argp, 0, "bpf_loop helper benchmark", 0 }, |
| 198 | { &bench_strncmp_argp, 0, "bpf_strncmp helper benchmark", 0 }, | ||
| 213 | {}, | 199 | {}, |
| 214 | }; | 200 | }; |
| 215 | 201 | ||
| @@ -409,6 +395,8 @@ extern const struct bench bench_bloom_false_positive; · 193 unmodified lines | |||
| 409 | extern const struct bench bench_hashmap_without_bloom; | 395 | extern const struct bench bench_hashmap_without_bloom; |
| 410 | extern const struct bench bench_hashmap_with_bloom; | 396 | extern const struct bench bench_hashmap_with_bloom; |
| 411 | extern const struct bench bench_bpf_loop; | 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 | static const struct bench *benchs[] = { | 401 | static const struct bench *benchs[] = { |
| 414 | &bench_count_global, | 402 | &bench_count_global, |
| @@ -441,6 +429,8 @@ static const struct bench *benchs[] = { · 26 unmodified lines | |||
| 441 | &bench_hashmap_without_bloom, | 429 | &bench_hashmap_without_bloom, |
| 442 | &bench_hashmap_with_bloom, | 430 | &bench_hashmap_with_bloom, |
| 443 | &bench_bpf_loop, | 431 | &bench_bpf_loop, |
| 432 | &bench_strncmp_no_helper, | ||
| 433 | &bench_strncmp_helper, | ||
| 444 | }; | 434 | }; |
| 445 | 435 | ||
| 446 | static void setup_benchmark() | 436 | static void setup_benchmark() |
| @@ -38,8 +38,8 @@ struct bench_res { · 37 unmodified lines | |||
| 38 | 38 | ||
| 39 | struct bench { | 39 | struct bench { |
| 40 | const char *name; | 40 | const char *name; |
| 41 | void (*validate)(); | 41 | void (*validate)(void); |
| 42 | void (*setup)(); | 42 | void (*setup)(void); |
| 43 | void *(*producer_thread)(void *ctx); | 43 | void *(*producer_thread)(void *ctx); |
| 44 | void *(*consumer_thread)(void *ctx); | 44 | void *(*consumer_thread)(void *ctx); |
| 45 | void (*measure)(struct bench_res* res); | 45 | void (*measure)(struct bench_res* res); |
| @@ -54,7 +54,7 @@ struct counter { · 8 unmodified lines | |||
| 54 | extern struct env env; | 54 | extern struct env env; |
| 55 | extern const struct bench *bench; | 55 | extern const struct bench *bench; |
| 56 | 56 | ||
| 57 | void setup_libbpf(); | 57 | void setup_libbpf(void); |
| 58 | void hits_drops_report_progress(int iter, struct bench_res *res, long delta_ns); | 58 | void hits_drops_report_progress(int iter, struct bench_res *res, long delta_ns); |
| 59 | void hits_drops_report_final(struct bench_res res[], int res_cnt); | 59 | void hits_drops_report_final(struct bench_res res[], int res_cnt); |
| 60 | void false_hits_report_progress(int iter, struct bench_res *res, long delta_ns); | 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 | void ops_report_progress(int iter, struct bench_res *res, long delta_ns); | 62 | void ops_report_progress(int iter, struct bench_res *res, long delta_ns); |
| 63 | void ops_report_final(struct bench_res res[], int res_cnt); | 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 | struct timespec t; | 67 | struct timespec t; |
| 67 | 68 | ||
| 68 | clock_gettime(CLOCK_MONOTONIC, &t); | 69 | clock_gettime(CLOCK_MONOTONIC, &t); |
| @@ -36,7 +36,7 @@ static struct count_local_ctx { · 35 unmodified lines | |||
| 36 | struct counter *hits; | 36 | struct counter *hits; |
| 37 | } count_local_ctx; | 37 | } count_local_ctx; |
| 38 | 38 | ||
| 39 | static void count_local_setup() | 39 | static void count_local_setup(void) |
| 40 | { | 40 | { |
| 41 | struct count_local_ctx *ctx = &count_local_ctx; | 41 | struct count_local_ctx *ctx = &count_local_ctx; |
| 42 | 42 | ||
| @@ -11,7 +11,7 @@ static struct ctx { · 10 unmodified lines | |||
| 11 | int fd; | 11 | int fd; |
| 12 | } ctx; | 12 | } ctx; |
| 13 | 13 | ||
| 14 | static void validate() | 14 | static void validate(void) |
| 15 | { | 15 | { |
| 16 | if (env.producer_cnt != 1) { | 16 | if (env.producer_cnt != 1) { |
| 17 | fprintf(stderr, "benchmark doesn't support multi-producer!\n"); | 17 | fprintf(stderr, "benchmark doesn't support multi-producer!\n"); |
| @@ -43,7 +43,7 @@ static void measure(struct bench_res *res) · 25 unmodified lines | |||
| 43 | res->hits = atomic_swap(&ctx.hits.value, 0); | 43 | res->hits = atomic_swap(&ctx.hits.value, 0); |
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | static void setup_ctx() | 46 | static void setup_ctx(void) |
| 47 | { | 47 | { |
| 48 | setup_libbpf(); | 48 | setup_libbpf(); |
| 49 | 49 | ||
| @@ -71,36 +71,36 @@ static void attach_bpf(struct bpf_program *prog) · 21 unmodified lines | |||
| 71 | } | 71 | } |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | static void setup_base() | 74 | static void setup_base(void) |
| 75 | { | 75 | { |
| 76 | setup_ctx(); | 76 | setup_ctx(); |
| 77 | } | 77 | } |
| 78 | 78 | ||
| 79 | static void setup_kprobe() | 79 | static void setup_kprobe(void) |
| 80 | { | 80 | { |
| 81 | setup_ctx(); | 81 | setup_ctx(); |
| 82 | attach_bpf(ctx.skel->progs.prog1); | 82 | attach_bpf(ctx.skel->progs.prog1); |
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | static void setup_kretprobe() | 85 | static void setup_kretprobe(void) |
| 86 | { | 86 | { |
| 87 | setup_ctx(); | 87 | setup_ctx(); |
| 88 | attach_bpf(ctx.skel->progs.prog2); | 88 | attach_bpf(ctx.skel->progs.prog2); |
| 89 | } | 89 | } |
| 90 | 90 | ||
| 91 | static void setup_rawtp() | 91 | static void setup_rawtp(void) |
| 92 | { | 92 | { |
| 93 | setup_ctx(); | 93 | setup_ctx(); |
| 94 | attach_bpf(ctx.skel->progs.prog3); | 94 | attach_bpf(ctx.skel->progs.prog3); |
| 95 | } | 95 | } |
| 96 | 96 | ||
| 97 | static void setup_fentry() | 97 | static void setup_fentry(void) |
| 98 | { | 98 | { |
| 99 | setup_ctx(); | 99 | setup_ctx(); |
| 100 | attach_bpf(ctx.skel->progs.prog4); | 100 | attach_bpf(ctx.skel->progs.prog4); |
| 101 | } | 101 | } |
| 102 | 102 | ||
| 103 | static void setup_fexit() | 103 | static void setup_fexit(void) |
| 104 | { | 104 | { |
| 105 | setup_ctx(); | 105 | setup_ctx(); |
| 106 | attach_bpf(ctx.skel->progs.prog5); | 106 | attach_bpf(ctx.skel->progs.prog5); |
| @@ -88,12 +88,12 @@ const struct argp bench_ringbufs_argp = { · 87 unmodified lines | |||
| 88 | 88 | ||
| 89 | static struct counter buf_hits; | 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 | (void)syscall(__NR_getpgid); | 93 | (void)syscall(__NR_getpgid); |
| 94 | } | 94 | } |
| 95 | 95 | ||
| 96 | static void bufs_validate() | 96 | static void bufs_validate(void) |
| 97 | { | 97 | { |
| 98 | if (env.consumer_cnt != 1) { | 98 | if (env.consumer_cnt != 1) { |
| 99 | fprintf(stderr, "rb-libbpf benchmark doesn't support multi-consumer!\n"); | 99 | fprintf(stderr, "rb-libbpf benchmark doesn't support multi-consumer!\n"); |
| @@ -132,7 +132,7 @@ static void ringbuf_libbpf_measure(struct bench_res *res) · 32 unmodified lines | |||
| 132 | res->drops = atomic_swap(&ctx->skel->bss->dropped, 0); | 132 | res->drops = atomic_swap(&ctx->skel->bss->dropped, 0); |
| 133 | } | 133 | } |
| 134 | 134 | ||
| 135 | static struct ringbuf_bench *ringbuf_setup_skeleton() | 135 | static struct ringbuf_bench *ringbuf_setup_skeleton(void) |
| 136 | { | 136 | { |
| 137 | struct ringbuf_bench *skel; | 137 | struct ringbuf_bench *skel; |
| 138 | 138 | ||
| @@ -167,7 +167,7 @@ static int buf_process_sample(void *ctx, void *data, size_t len) · 28 unmodified lines | |||
| 167 | return 0; | 167 | return 0; |
| 168 | } | 168 | } |
| 169 | 169 | ||
| 170 | static void ringbuf_libbpf_setup() | 170 | static void ringbuf_libbpf_setup(void) |
| 171 | { | 171 | { |
| 172 | struct ringbuf_libbpf_ctx *ctx = &ringbuf_libbpf_ctx; | 172 | struct ringbuf_libbpf_ctx *ctx = &ringbuf_libbpf_ctx; |
| 173 | struct bpf_link *link; | 173 | struct bpf_link *link; |
| @@ -223,7 +223,7 @@ static void ringbuf_custom_measure(struct bench_res *res) · 49 unmodified lines | |||
| 223 | res->drops = atomic_swap(&ctx->skel->bss->dropped, 0); | 223 | res->drops = atomic_swap(&ctx->skel->bss->dropped, 0); |
| 224 | } | 224 | } |
| 225 | 225 | ||
| 226 | static void ringbuf_custom_setup() | 226 | static void ringbuf_custom_setup(void) |
| 227 | { | 227 | { |
| 228 | struct ringbuf_custom_ctx *ctx = &ringbuf_custom_ctx; | 228 | struct ringbuf_custom_ctx *ctx = &ringbuf_custom_ctx; |
| 229 | const size_t page_size = getpagesize(); | 229 | const size_t page_size = getpagesize(); |
| @@ -352,7 +352,7 @@ static void perfbuf_measure(struct bench_res *res) · 122 unmodified lines | |||
| 352 | res->drops = atomic_swap(&ctx->skel->bss->dropped, 0); | 352 | res->drops = atomic_swap(&ctx->skel->bss->dropped, 0); |
| 353 | } | 353 | } |
| 354 | 354 | ||
| 355 | static struct perfbuf_bench *perfbuf_setup_skeleton() | 355 | static struct perfbuf_bench *perfbuf_setup_skeleton(void) |
| 356 | { | 356 | { |
| 357 | struct perfbuf_bench *skel; | 357 | struct perfbuf_bench *skel; |
| 358 | 358 | ||
| @@ -390,7 +390,7 @@ perfbuf_process_sample_raw(void *input_ctx, int cpu, · 31 unmodified lines | |||
| 390 | return LIBBPF_PERF_EVENT_CONT; | 390 | return LIBBPF_PERF_EVENT_CONT; |
| 391 | } | 391 | } |
| 392 | 392 | ||
| 393 | static void perfbuf_libbpf_setup() | 393 | static void perfbuf_libbpf_setup(void) |
| 394 | { | 394 | { |
| 395 | struct perfbuf_libbpf_ctx *ctx = &perfbuf_libbpf_ctx; | 395 | struct perfbuf_libbpf_ctx *ctx = &perfbuf_libbpf_ctx; |
| 396 | struct perf_event_attr attr; | 396 | struct perf_event_attr attr; |
| @@ -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 | static struct counter base_hits; | 12 | static struct counter base_hits; |
| 13 | 13 | ||
| 14 | static void trigger_validate() | 14 | static void trigger_validate(void) |
| 15 | { | 15 | { |
| 16 | if (env.consumer_cnt != 1) { | 16 | if (env.consumer_cnt != 1) { |
| 17 | fprintf(stderr, "benchmark doesn't support multi-consumer!\n"); | 17 | fprintf(stderr, "benchmark doesn't support multi-consumer!\n"); |
| @@ -45,7 +45,7 @@ static void trigger_measure(struct bench_res *res) · 27 unmodified lines | |||
| 45 | res->hits = atomic_swap(&ctx.skel->bss->hits, 0); | 45 | res->hits = atomic_swap(&ctx.skel->bss->hits, 0); |
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | static void setup_ctx() | 48 | static void setup_ctx(void) |
| 49 | { | 49 | { |
| 50 | setup_libbpf(); | 50 | setup_libbpf(); |
| 51 | 51 | ||
| @@ -67,37 +67,37 @@ static void attach_bpf(struct bpf_program *prog) · 15 unmodified lines | |||
| 67 | } | 67 | } |
| 68 | } | 68 | } |
| 69 | 69 | ||
| 70 | static void trigger_tp_setup() | 70 | static void trigger_tp_setup(void) |
| 71 | { | 71 | { |
| 72 | setup_ctx(); | 72 | setup_ctx(); |
| 73 | attach_bpf(ctx.skel->progs.bench_trigger_tp); | 73 | attach_bpf(ctx.skel->progs.bench_trigger_tp); |
| 74 | } | 74 | } |
| 75 | 75 | ||
| 76 | static void trigger_rawtp_setup() | 76 | static void trigger_rawtp_setup(void) |
| 77 | { | 77 | { |
| 78 | setup_ctx(); | 78 | setup_ctx(); |
| 79 | attach_bpf(ctx.skel->progs.bench_trigger_raw_tp); | 79 | attach_bpf(ctx.skel->progs.bench_trigger_raw_tp); |
| 80 | } | 80 | } |
| 81 | 81 | ||
| 82 | static void trigger_kprobe_setup() | 82 | static void trigger_kprobe_setup(void) |
| 83 | { | 83 | { |
| 84 | setup_ctx(); | 84 | setup_ctx(); |
| 85 | attach_bpf(ctx.skel->progs.bench_trigger_kprobe); | 85 | attach_bpf(ctx.skel->progs.bench_trigger_kprobe); |
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | static void trigger_fentry_setup() | 88 | static void trigger_fentry_setup(void) |
| 89 | { | 89 | { |
| 90 | setup_ctx(); | 90 | setup_ctx(); |
| 91 | attach_bpf(ctx.skel->progs.bench_trigger_fentry); | 91 | attach_bpf(ctx.skel->progs.bench_trigger_fentry); |
| 92 | } | 92 | } |
| 93 | 93 | ||
| 94 | static void trigger_fentry_sleep_setup() | 94 | static void trigger_fentry_sleep_setup(void) |
| 95 | { | 95 | { |
| 96 | setup_ctx(); | 96 | setup_ctx(); |
| 97 | attach_bpf(ctx.skel->progs.bench_trigger_fentry_sleep); | 97 | attach_bpf(ctx.skel->progs.bench_trigger_fentry_sleep); |
| 98 | } | 98 | } |
| 99 | 99 | ||
| 100 | static void trigger_fmodret_setup() | 100 | static void trigger_fmodret_setup(void) |
| 101 | { | 101 | { |
| 102 | setup_ctx(); | 102 | setup_ctx(); |
| 103 | attach_bpf(ctx.skel->progs.bench_trigger_fmodret); | 103 | attach_bpf(ctx.skel->progs.bench_trigger_fmodret); |
| @@ -183,22 +183,22 @@ static void usetup(bool use_retprobe, bool use_nop) · 79 unmodified lines | |||
| 183 | ctx.skel->links.bench_trigger_uprobe = link; | 183 | ctx.skel->links.bench_trigger_uprobe = link; |
| 184 | } | 184 | } |
| 185 | 185 | ||
| 186 | static void uprobe_setup_with_nop() | 186 | static void uprobe_setup_with_nop(void) |
| 187 | { | 187 | { |
| 188 | usetup(false, true); | 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 | usetup(true, true); | 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 | usetup(false, false); | 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 | usetup(true, false); | 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 | CONFIG_BPF_JIT=y | 38 | CONFIG_BPF_JIT=y |
| 39 | CONFIG_BPF_LSM=y | 39 | CONFIG_BPF_LSM=y |
| 40 | CONFIG_SECURITY=y | 40 | CONFIG_SECURITY=y |
| 41 | CONFIG_RC_CORE=y | ||
| 41 | CONFIG_LIRC=y | 42 | CONFIG_LIRC=y |
| 43 | CONFIG_BPF_LIRC_MODE2=y | ||
| 42 | CONFIG_IMA=y | 44 | CONFIG_IMA=y |
| 43 | CONFIG_SECURITYFS=y | 45 | CONFIG_SECURITYFS=y |
| 44 | CONFIG_IMA_WRITE_POLICY=y | 46 | CONFIG_IMA_WRITE_POLICY=y |
| @@ -39,13 +39,13 @@ static struct bpf_align_test tests[] = { · 38 unmodified lines | |||
| 39 | }, | 39 | }, |
| 40 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, | 40 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, |
| 41 | .matches = { | 41 | .matches = { |
| 42 | {1, "R1=ctx(id=0,off=0,imm=0)"}, | 42 | {0, "R1=ctx(id=0,off=0,imm=0)"}, |
| 43 | {1, "R10=fp0"}, | 43 | {0, "R10=fp0"}, |
| 44 | {1, "R3_w=inv2"}, | 44 | {0, "R3_w=inv2"}, |
| 45 | {2, "R3_w=inv4"}, | 45 | {1, "R3_w=inv4"}, |
| 46 | {3, "R3_w=inv8"}, | 46 | {2, "R3_w=inv8"}, |
| 47 | {4, "R3_w=inv16"}, | 47 | {3, "R3_w=inv16"}, |
| 48 | {5, "R3_w=inv32"}, | 48 | {4, "R3_w=inv32"}, |
| 49 | }, | 49 | }, |
| 50 | }, | 50 | }, |
| 51 | { | 51 | { |
| @@ -67,19 +67,19 @@ static struct bpf_align_test tests[] = { · 15 unmodified lines | |||
| 67 | }, | 67 | }, |
| 68 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, | 68 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, |
| 69 | .matches = { | 69 | .matches = { |
| 70 | {1, "R1=ctx(id=0,off=0,imm=0)"}, | 70 | {0, "R1=ctx(id=0,off=0,imm=0)"}, |
| 71 | {1, "R10=fp0"}, | 71 | {0, "R10=fp0"}, |
| 72 | {1, "R3_w=inv1"}, | 72 | {0, "R3_w=inv1"}, |
| 73 | {2, "R3_w=inv2"}, | 73 | {1, "R3_w=inv2"}, |
| 74 | {3, "R3_w=inv4"}, | 74 | {2, "R3_w=inv4"}, |
| 75 | {4, "R3_w=inv8"}, | 75 | {3, "R3_w=inv8"}, |
| 76 | {5, "R3_w=inv16"}, | 76 | {4, "R3_w=inv16"}, |
| 77 | {6, "R3_w=inv1"}, | 77 | {5, "R3_w=inv1"}, |
| 78 | {7, "R4_w=inv32"}, | 78 | {6, "R4_w=inv32"}, |
| 79 | {8, "R4_w=inv16"}, | 79 | {7, "R4_w=inv16"}, |
| 80 | {9, "R4_w=inv8"}, | 80 | {8, "R4_w=inv8"}, |
| 81 | {10, "R4_w=inv4"}, | 81 | {9, "R4_w=inv4"}, |
| 82 | {11, "R4_w=inv2"}, | 82 | {10, "R4_w=inv2"}, |
| 83 | }, | 83 | }, |
| 84 | }, | 84 | }, |
| 85 | { | 85 | { |
| @@ -96,14 +96,14 @@ static struct bpf_align_test tests[] = { · 10 unmodified lines | |||
| 96 | }, | 96 | }, |
| 97 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, | 97 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, |
| 98 | .matches = { | 98 | .matches = { |
| 99 | {1, "R1=ctx(id=0,off=0,imm=0)"}, | 99 | {0, "R1=ctx(id=0,off=0,imm=0)"}, |
| 100 | {1, "R10=fp0"}, | 100 | {0, "R10=fp0"}, |
| 101 | {1, "R3_w=inv4"}, | 101 | {0, "R3_w=inv4"}, |
| 102 | {2, "R3_w=inv8"}, | 102 | {1, "R3_w=inv8"}, |
| 103 | {3, "R3_w=inv10"}, | 103 | {2, "R3_w=inv10"}, |
| 104 | {4, "R4_w=inv8"}, | 104 | {3, "R4_w=inv8"}, |
| 105 | {5, "R4_w=inv12"}, | 105 | {4, "R4_w=inv12"}, |
| 106 | {6, "R4_w=inv14"}, | 106 | {5, "R4_w=inv14"}, |
| 107 | }, | 107 | }, |
| 108 | }, | 108 | }, |
| 109 | { | 109 | { |
| @@ -118,12 +118,12 @@ static struct bpf_align_test tests[] = { · 8 unmodified lines | |||
| 118 | }, | 118 | }, |
| 119 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, | 119 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, |
| 120 | .matches = { | 120 | .matches = { |
| 121 | {1, "R1=ctx(id=0,off=0,imm=0)"}, | 121 | {0, "R1=ctx(id=0,off=0,imm=0)"}, |
| 122 | {1, "R10=fp0"}, | 122 | {0, "R10=fp0"}, |
| 123 | {0, "R3_w=inv7"}, | ||
| 123 | {1, "R3_w=inv7"}, | 124 | {1, "R3_w=inv7"}, |
| 124 | {2, "R3_w=inv7"}, | 125 | {2, "R3_w=inv14"}, |
| 125 | {3, "R3_w=inv14"}, | 126 | {3, "R3_w=inv56"}, |
| 126 | {4, "R3_w=inv56"}, | ||
| 127 | }, | 127 | }, |
| 128 | }, | 128 | }, |
| 129 | 129 | ||
| @@ -161,19 +161,19 @@ static struct bpf_align_test tests[] = { · 31 unmodified lines | |||
| 161 | }, | 161 | }, |
| 162 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, | 162 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, |
| 163 | .matches = { | 163 | .matches = { |
| 164 | {7, "R0_w=pkt(id=0,off=8,r=8,imm=0)"}, | 164 | {6, "R0_w=pkt(id=0,off=8,r=8,imm=0)"}, |
| 165 | {7, "R3_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"}, | 165 | {6, "R3_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"}, |
| 166 | {8, "R3_w=inv(id=0,umax_value=510,var_off=(0x0; 0x1fe))"}, | 166 | {7, "R3_w=inv(id=0,umax_value=510,var_off=(0x0; 0x1fe))"}, |
| 167 | {9, "R3_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, | 167 | {8, "R3_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, |
| 168 | {10, "R3_w=inv(id=0,umax_value=2040,var_off=(0x0; 0x7f8))"}, | 168 | {9, "R3_w=inv(id=0,umax_value=2040,var_off=(0x0; 0x7f8))"}, |
| 169 | {11, "R3_w=inv(id=0,umax_value=4080,var_off=(0x0; 0xff0))"}, | 169 | {10, "R3_w=inv(id=0,umax_value=4080,var_off=(0x0; 0xff0))"}, |
| 170 | {18, "R3=pkt_end(id=0,off=0,imm=0)"}, | 170 | {12, "R3_w=pkt_end(id=0,off=0,imm=0)"}, |
| 171 | {18, "R4_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"}, | 171 | {17, "R4_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"}, |
| 172 | {19, "R4_w=inv(id=0,umax_value=8160,var_off=(0x0; 0x1fe0))"}, | 172 | {18, "R4_w=inv(id=0,umax_value=8160,var_off=(0x0; 0x1fe0))"}, |
| 173 | {20, "R4_w=inv(id=0,umax_value=4080,var_off=(0x0; 0xff0))"}, | 173 | {19, "R4_w=inv(id=0,umax_value=4080,var_off=(0x0; 0xff0))"}, |
| 174 | {21, "R4_w=inv(id=0,umax_value=2040,var_off=(0x0; 0x7f8))"}, | 174 | {20, "R4_w=inv(id=0,umax_value=2040,var_off=(0x0; 0x7f8))"}, |
| 175 | {22, "R4_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, | 175 | {21, "R4_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, |
| 176 | {23, "R4_w=inv(id=0,umax_value=510,var_off=(0x0; 0x1fe))"}, | 176 | {22, "R4_w=inv(id=0,umax_value=510,var_off=(0x0; 0x1fe))"}, |
| 177 | }, | 177 | }, |
| 178 | }, | 178 | }, |
| 179 | { | 179 | { |
| @@ -194,16 +194,16 @@ static struct bpf_align_test tests[] = { · 14 unmodified lines | |||
| 194 | }, | 194 | }, |
| 195 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, | 195 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, |
| 196 | .matches = { | 196 | .matches = { |
| 197 | {7, "R3_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"}, | 197 | {6, "R3_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"}, |
| 198 | {8, "R4_w=inv(id=1,umax_value=255,var_off=(0x0; 0xff))"}, | 198 | {7, "R4_w=inv(id=1,umax_value=255,var_off=(0x0; 0xff))"}, |
| 199 | {9, "R4_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"}, | 199 | {8, "R4_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"}, |
| 200 | {10, "R4_w=inv(id=1,umax_value=255,var_off=(0x0; 0xff))"}, | 200 | {9, "R4_w=inv(id=1,umax_value=255,var_off=(0x0; 0xff))"}, |
| 201 | {11, "R4_w=inv(id=0,umax_value=510,var_off=(0x0; 0x1fe))"}, | 201 | {10, "R4_w=inv(id=0,umax_value=510,var_off=(0x0; 0x1fe))"}, |
| 202 | {12, "R4_w=inv(id=1,umax_value=255,var_off=(0x0; 0xff))"}, | 202 | {11, "R4_w=inv(id=1,umax_value=255,var_off=(0x0; 0xff))"}, |
| 203 | {13, "R4_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, | 203 | {12, "R4_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, |
| 204 | {14, "R4_w=inv(id=1,umax_value=255,var_off=(0x0; 0xff))"}, | 204 | {13, "R4_w=inv(id=1,umax_value=255,var_off=(0x0; 0xff))"}, |
| 205 | {15, "R4_w=inv(id=0,umax_value=2040,var_off=(0x0; 0x7f8))"}, | 205 | {14, "R4_w=inv(id=0,umax_value=2040,var_off=(0x0; 0x7f8))"}, |
| 206 | {16, "R4_w=inv(id=0,umax_value=4080,var_off=(0x0; 0xff0))"}, | 206 | {15, "R4_w=inv(id=0,umax_value=4080,var_off=(0x0; 0xff0))"}, |
| 207 | }, | 207 | }, |
| 208 | }, | 208 | }, |
| 209 | { | 209 | { |
| @@ -234,14 +234,14 @@ static struct bpf_align_test tests[] = { · 24 unmodified lines | |||
| 234 | }, | 234 | }, |
| 235 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, | 235 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, |
| 236 | .matches = { | 236 | .matches = { |
| 237 | {4, "R5_w=pkt(id=0,off=0,r=0,imm=0)"}, | 237 | {2, "R5_w=pkt(id=0,off=0,r=0,imm=0)"}, |
| 238 | {5, "R5_w=pkt(id=0,off=14,r=0,imm=0)"}, | 238 | {4, "R5_w=pkt(id=0,off=14,r=0,imm=0)"}, |
| 239 | {6, "R4_w=pkt(id=0,off=14,r=0,imm=0)"}, | 239 | {5, "R4_w=pkt(id=0,off=14,r=0,imm=0)"}, |
| 240 | {10, "R2=pkt(id=0,off=0,r=18,imm=0)"}, | 240 | {9, "R2=pkt(id=0,off=0,r=18,imm=0)"}, |
| 241 | {10, "R5=pkt(id=0,off=14,r=18,imm=0)"}, | 241 | {10, "R5=pkt(id=0,off=14,r=18,imm=0)"}, |
| 242 | {10, "R4_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"}, | 242 | {10, "R4_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"}, |
| 243 | {13, "R4_w=inv(id=0,umax_value=65535,var_off=(0x0; 0xffff))"}, | ||
| 243 | {14, "R4_w=inv(id=0,umax_value=65535,var_off=(0x0; 0xffff))"}, | 244 | {14, "R4_w=inv(id=0,umax_value=65535,var_off=(0x0; 0xffff))"}, |
| 244 | {15, "R4_w=inv(id=0,umax_value=65535,var_off=(0x0; 0xffff))"}, | ||
| 245 | }, | 245 | }, |
| 246 | }, | 246 | }, |
| 247 | { | 247 | { |
| @@ -296,8 +296,8 @@ static struct bpf_align_test tests[] = { · 48 unmodified lines | |||
| 296 | /* Calculated offset in R6 has unknown value, but known | 296 | /* Calculated offset in R6 has unknown value, but known |
| 297 | * alignment of 4. | 297 | * alignment of 4. |
| 298 | */ | 298 | */ |
| 299 | {8, "R2_w=pkt(id=0,off=0,r=8,imm=0)"}, | 299 | {6, "R2_w=pkt(id=0,off=0,r=8,imm=0)"}, |
| 300 | {8, "R6_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, | 300 | {7, "R6_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, |
| 301 | /* Offset is added to packet pointer R5, resulting in | 301 | /* Offset is added to packet pointer R5, resulting in |
| 302 | * known fixed offset, and variable offset from R6. | 302 | * known fixed offset, and variable offset from R6. |
| 303 | */ | 303 | */ |
| @@ -313,11 +313,11 @@ static struct bpf_align_test tests[] = { · 9 unmodified lines | |||
| 313 | /* Variable offset is added to R5 packet pointer, | 313 | /* Variable offset is added to R5 packet pointer, |
| 314 | * resulting in auxiliary alignment of 4. | 314 | * resulting in auxiliary alignment of 4. |
| 315 | */ | 315 | */ |
| 316 | {18, "R5_w=pkt(id=2,off=0,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, | 316 | {17, "R5_w=pkt(id=2,off=0,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, |
| 317 | /* Constant offset is added to R5, resulting in | 317 | /* Constant offset is added to R5, resulting in |
| 318 | * reg->off of 14. | 318 | * reg->off of 14. |
| 319 | */ | 319 | */ |
| 320 | {19, "R5_w=pkt(id=2,off=14,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, | 320 | {18, "R5_w=pkt(id=2,off=14,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, |
| 321 | /* At the time the word size load is performed from R5, | 321 | /* At the time the word size load is performed from R5, |
| 322 | * its total fixed offset is NET_IP_ALIGN + reg->off | 322 | * its total fixed offset is NET_IP_ALIGN + reg->off |
| 323 | * (14) which is 16. Then the variable offset is 4-byte | 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 | /* Constant offset is added to R5 packet pointer, | 329 | /* Constant offset is added to R5 packet pointer, |
| 330 | * resulting in reg->off value of 14. | 330 | * resulting in reg->off value of 14. |
| 331 | */ | 331 | */ |
| 332 | {26, "R5_w=pkt(id=0,off=14,r=8"}, | 332 | {25, "R5_w=pkt(id=0,off=14,r=8"}, |
| 333 | /* Variable offset is added to R5, resulting in a | 333 | /* Variable offset is added to R5, resulting in a |
| 334 | * variable offset of (4n). | 334 | * variable offset of (4n). |
| 335 | */ | 335 | */ |
| 336 | {27, "R5_w=pkt(id=3,off=14,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, | 336 | {26, "R5_w=pkt(id=3,off=14,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, |
| 337 | /* Constant is added to R5 again, setting reg->off to 18. */ | 337 | /* Constant is added to R5 again, setting reg->off to 18. */ |
| 338 | {28, "R5_w=pkt(id=3,off=18,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, | 338 | {27, "R5_w=pkt(id=3,off=18,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, |
| 339 | /* And once more we add a variable; resulting var_off | 339 | /* And once more we add a variable; resulting var_off |
| 340 | * is still (4n), fixed offset is not changed. | 340 | * is still (4n), fixed offset is not changed. |
| 341 | * Also, we create a new reg->id. | 341 | * Also, we create a new reg->id. |
| 342 | */ | 342 | */ |
| 343 | {29, "R5_w=pkt(id=4,off=18,r=0,umax_value=2040,var_off=(0x0; 0x7fc)"}, | 343 | {28, "R5_w=pkt(id=4,off=18,r=0,umax_value=2040,var_off=(0x0; 0x7fc)"}, |
| 344 | /* At the time the word size load is performed from R5, | 344 | /* At the time the word size load is performed from R5, |
| 345 | * its total fixed offset is NET_IP_ALIGN + reg->off (18) | 345 | * its total fixed offset is NET_IP_ALIGN + reg->off (18) |
| 346 | * which is 20. Then the variable offset is (4n), so | 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 | /* Calculated offset in R6 has unknown value, but known | 386 | /* Calculated offset in R6 has unknown value, but known |
| 387 | * alignment of 4. | 387 | * alignment of 4. |
| 388 | */ | 388 | */ |
| 389 | {8, "R2_w=pkt(id=0,off=0,r=8,imm=0)"}, | 389 | {6, "R2_w=pkt(id=0,off=0,r=8,imm=0)"}, |
| 390 | {8, "R6_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, | 390 | {7, "R6_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, |
| 391 | /* Adding 14 makes R6 be (4n+2) */ | 391 | /* Adding 14 makes R6 be (4n+2) */ |
| 392 | {9, "R6_w=inv(id=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc))"}, | 392 | {8, "R6_w=inv(id=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc))"}, |
| 393 | /* Packet pointer has (4n+2) offset */ | 393 | /* Packet pointer has (4n+2) offset */ |
| 394 | {11, "R5_w=pkt(id=1,off=0,r=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc)"}, | 394 | {11, "R5_w=pkt(id=1,off=0,r=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc)"}, |
| 395 | {13, "R4=pkt(id=1,off=4,r=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc)"}, | 395 | {12, "R4=pkt(id=1,off=4,r=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc)"}, |
| 396 | /* At the time the word size load is performed from R5, | 396 | /* At the time the word size load is performed from R5, |
| 397 | * its total fixed offset is NET_IP_ALIGN + reg->off (0) | 397 | * its total fixed offset is NET_IP_ALIGN + reg->off (0) |
| 398 | * which is 2. Then the variable offset is (4n+2), so | 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 | /* Newly read value in R6 was shifted left by 2, so has | 403 | /* Newly read value in R6 was shifted left by 2, so has |
| 404 | * known alignment of 4. | 404 | * known alignment of 4. |
| 405 | */ | 405 | */ |
| 406 | {18, "R6_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, | 406 | {17, "R6_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, |
| 407 | /* Added (4n) to packet pointer's (4n+2) var_off, giving | 407 | /* Added (4n) to packet pointer's (4n+2) var_off, giving |
| 408 | * another (4n+2). | 408 | * another (4n+2). |
| 409 | */ | 409 | */ |
| 410 | {19, "R5_w=pkt(id=2,off=0,r=0,umin_value=14,umax_value=2054,var_off=(0x2; 0xffc)"}, | 410 | {19, "R5_w=pkt(id=2,off=0,r=0,umin_value=14,umax_value=2054,var_off=(0x2; 0xffc)"}, |
| 411 | {21, "R4=pkt(id=2,off=4,r=0,umin_value=14,umax_value=2054,var_off=(0x2; 0xffc)"}, | 411 | {20, "R4=pkt(id=2,off=4,r=0,umin_value=14,umax_value=2054,var_off=(0x2; 0xffc)"}, |
| 412 | /* At the time the word size load is performed from R5, | 412 | /* At the time the word size load is performed from R5, |
| 413 | * its total fixed offset is NET_IP_ALIGN + reg->off (0) | 413 | * its total fixed offset is NET_IP_ALIGN + reg->off (0) |
| 414 | * which is 2. Then the variable offset is (4n+2), so | 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 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, | 448 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, |
| 449 | .result = REJECT, | 449 | .result = REJECT, |
| 450 | .matches = { | 450 | .matches = { |
| 451 | {4, "R5_w=pkt_end(id=0,off=0,imm=0)"}, | 451 | {3, "R5_w=pkt_end(id=0,off=0,imm=0)"}, |
| 452 | /* (ptr - ptr) << 2 == unknown, (4n) */ | 452 | /* (ptr - ptr) << 2 == unknown, (4n) */ |
| 453 | {6, "R5_w=inv(id=0,smax_value=9223372036854775804,umax_value=18446744073709551612,var_off=(0x0; 0xfffffffffffffffc)"}, | 453 | {5, "R5_w=inv(id=0,smax_value=9223372036854775804,umax_value=18446744073709551612,var_off=(0x0; 0xfffffffffffffffc)"}, |
| 454 | /* (4n) + 14 == (4n+2). We blow our bounds, because | 454 | /* (4n) + 14 == (4n+2). We blow our bounds, because |
| 455 | * the add could overflow. | 455 | * the add could overflow. |
| 456 | */ | 456 | */ |
| 457 | {7, "R5_w=inv(id=0,smin_value=-9223372036854775806,smax_value=9223372036854775806,umin_value=2,umax_value=18446744073709551614,var_off=(0x2; 0xfffffffffffffffc)"}, | 457 | {6, "R5_w=inv(id=0,smin_value=-9223372036854775806,smax_value=9223372036854775806,umin_value=2,umax_value=18446744073709551614,var_off=(0x2; 0xfffffffffffffffc)"}, |
| 458 | /* Checked s>=0 */ | 458 | /* Checked s>=0 */ |
| 459 | {9, "R5=inv(id=0,umin_value=2,umax_value=9223372036854775806,var_off=(0x2; 0x7ffffffffffffffc)"}, | 459 | {9, "R5=inv(id=0,umin_value=2,umax_value=9223372036854775806,var_off=(0x2; 0x7ffffffffffffffc)"}, |
| 460 | /* packet pointer + nonnegative (4n+2) */ | 460 | /* packet pointer + nonnegative (4n+2) */ |
| 461 | {11, "R6_w=pkt(id=1,off=0,r=0,umin_value=2,umax_value=9223372036854775806,var_off=(0x2; 0x7ffffffffffffffc)"}, | 461 | {11, "R6_w=pkt(id=1,off=0,r=0,umin_value=2,umax_value=9223372036854775806,var_off=(0x2; 0x7ffffffffffffffc)"}, |
| 462 | {13, "R4_w=pkt(id=1,off=4,r=0,umin_value=2,umax_value=9223372036854775806,var_off=(0x2; 0x7ffffffffffffffc)"}, | 462 | {12, "R4_w=pkt(id=1,off=4,r=0,umin_value=2,umax_value=9223372036854775806,var_off=(0x2; 0x7ffffffffffffffc)"}, |
| 463 | /* NET_IP_ALIGN + (4n+2) == (4n), alignment is fine. | 463 | /* NET_IP_ALIGN + (4n+2) == (4n), alignment is fine. |
| 464 | * We checked the bounds, but it might have been able | 464 | * We checked the bounds, but it might have been able |
| 465 | * to overflow if the packet pointer started in the | 465 | * to overflow if the packet pointer started in the |
| @@ -502,14 +502,14 @@ static struct bpf_align_test tests[] = { · 36 unmodified lines | |||
| 502 | /* Calculated offset in R6 has unknown value, but known | 502 | /* Calculated offset in R6 has unknown value, but known |
| 503 | * alignment of 4. | 503 | * alignment of 4. |
| 504 | */ | 504 | */ |
| 505 | {7, "R2_w=pkt(id=0,off=0,r=8,imm=0)"}, | 505 | {6, "R2_w=pkt(id=0,off=0,r=8,imm=0)"}, |
| 506 | {9, "R6_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, | 506 | {8, "R6_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, |
| 507 | /* Adding 14 makes R6 be (4n+2) */ | 507 | /* Adding 14 makes R6 be (4n+2) */ |
| 508 | {10, "R6_w=inv(id=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc))"}, | 508 | {9, "R6_w=inv(id=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc))"}, |
| 509 | /* New unknown value in R7 is (4n) */ | 509 | /* New unknown value in R7 is (4n) */ |
| 510 | {11, "R7_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, | 510 | {10, "R7_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, |
| 511 | /* Subtracting it from R6 blows our unsigned bounds */ | 511 | /* Subtracting it from R6 blows our unsigned bounds */ |
| 512 | {12, "R6=inv(id=0,smin_value=-1006,smax_value=1034,umin_value=2,umax_value=18446744073709551614,var_off=(0x2; 0xfffffffffffffffc)"}, | 512 | {11, "R6=inv(id=0,smin_value=-1006,smax_value=1034,umin_value=2,umax_value=18446744073709551614,var_off=(0x2; 0xfffffffffffffffc)"}, |
| 513 | /* Checked s>= 0 */ | 513 | /* Checked s>= 0 */ |
| 514 | {14, "R6=inv(id=0,umin_value=2,umax_value=1034,var_off=(0x2; 0x7fc))"}, | 514 | {14, "R6=inv(id=0,umin_value=2,umax_value=1034,var_off=(0x2; 0x7fc))"}, |
| 515 | /* At the time the word size load is performed from R5, | 515 | /* At the time the word size load is performed from R5, |
| @@ -556,14 +556,14 @@ static struct bpf_align_test tests[] = { · 40 unmodified lines | |||
| 556 | /* Calculated offset in R6 has unknown value, but known | 556 | /* Calculated offset in R6 has unknown value, but known |
| 557 | * alignment of 4. | 557 | * alignment of 4. |
| 558 | */ | 558 | */ |
| 559 | {7, "R2_w=pkt(id=0,off=0,r=8,imm=0)"}, | 559 | {6, "R2_w=pkt(id=0,off=0,r=8,imm=0)"}, |
| 560 | {10, "R6_w=inv(id=0,umax_value=60,var_off=(0x0; 0x3c))"}, | 560 | {9, "R6_w=inv(id=0,umax_value=60,var_off=(0x0; 0x3c))"}, |
| 561 | /* Adding 14 makes R6 be (4n+2) */ | 561 | /* Adding 14 makes R6 be (4n+2) */ |
| 562 | {11, "R6_w=inv(id=0,umin_value=14,umax_value=74,var_off=(0x2; 0x7c))"}, | 562 | {10, "R6_w=inv(id=0,umin_value=14,umax_value=74,var_off=(0x2; 0x7c))"}, |
| 563 | /* Subtracting from packet pointer overflows ubounds */ | 563 | /* Subtracting from packet pointer overflows ubounds */ |
| 564 | {13, "R5_w=pkt(id=2,off=0,r=8,umin_value=18446744073709551542,umax_value=18446744073709551602,var_off=(0xffffffffffffff82; 0x7c)"}, | 564 | {13, "R5_w=pkt(id=2,off=0,r=8,umin_value=18446744073709551542,umax_value=18446744073709551602,var_off=(0xffffffffffffff82; 0x7c)"}, |
| 565 | /* New unknown value in R7 is (4n), >= 76 */ | 565 | /* New unknown value in R7 is (4n), >= 76 */ |
| 566 | {15, "R7_w=inv(id=0,umin_value=76,umax_value=1096,var_off=(0x0; 0x7fc))"}, | 566 | {14, "R7_w=inv(id=0,umin_value=76,umax_value=1096,var_off=(0x0; 0x7fc))"}, |
| 567 | /* Adding it to packet pointer gives nice bounds again */ | 567 | /* Adding it to packet pointer gives nice bounds again */ |
| 568 | {16, "R5_w=pkt(id=3,off=0,r=0,umin_value=2,umax_value=1082,var_off=(0x2; 0xfffffffc)"}, | 568 | {16, "R5_w=pkt(id=3,off=0,r=0,umin_value=2,umax_value=1082,var_off=(0x2; 0xfffffffc)"}, |
| 569 | /* At the time the word size load is performed from R5, | 569 | /* At the time the word size load is performed from R5, |
| @@ -625,12 +625,15 @@ static int do_test_single(struct bpf_align_test *test) · 55 unmodified lines | |||
| 625 | line_ptr = strtok(bpf_vlog_copy, "\n"); | 625 | line_ptr = strtok(bpf_vlog_copy, "\n"); |
| 626 | for (i = 0; i < MAX_MATCHES; i++) { | 626 | for (i = 0; i < MAX_MATCHES; i++) { |
| 627 | struct bpf_reg_match m = test->matches[i]; | 627 | struct bpf_reg_match m = test->matches[i]; |
| 628 | int tmp; | ||
| 628 | 629 | ||
| 629 | if (!m.match) | 630 | if (!m.match) |
| 630 | break; | 631 | break; |
| 631 | while (line_ptr) { | 632 | while (line_ptr) { |
| 632 | cur_line = -1; | 633 | cur_line = -1; |
| 633 | sscanf(line_ptr, "%u: ", &cur_line); | 634 | sscanf(line_ptr, "%u: ", &cur_line); |
| 635 | if (cur_line == -1) | ||
| 636 | sscanf(line_ptr, "from %u to %u: ", &tmp, &cur_line); | ||
| 634 | if (cur_line == m.line) | 637 | if (cur_line == m.line) |
| 635 | break; | 638 | break; |
| 636 | line_ptr = strtok(NULL, "\n"); | 639 | line_ptr = strtok(NULL, "\n"); |
| @@ -642,7 +645,19 @@ static int do_test_single(struct bpf_align_test *test) · 5 unmodified lines | |||
| 642 | printf("%s", bpf_vlog); | 645 | printf("%s", bpf_vlog); |
| 643 | break; | 646 | break; |
| 644 | } | 647 | } |
| 648 | /* Check the next line as well in case the previous line | ||
| 649 | * did not have a corresponding bpf insn. Example: | ||
| 650 | * func#0 @0 | ||
| 651 | * 0: R1=ctx(id=0,off=0,imm=0) R10=fp0 | ||
| 652 | * 0: (b7) r3 = 2 ; R3_w=inv2 | ||
| 653 | */ | ||
| 645 | if (!strstr(line_ptr, m.match)) { | 654 | if (!strstr(line_ptr, m.match)) { |
| 655 | cur_line = -1; | ||
| 656 | line_ptr = strtok(NULL, "\n"); | ||
| 657 | sscanf(line_ptr, "%u: ", &cur_line); | ||
| 658 | } | ||
| 659 | if (cur_line != m.line || !line_ptr || | ||
| 660 | !strstr(line_ptr, m.match)) { | ||
| 646 | printf("Failed to find match %u: %s\n", | 661 | printf("Failed to find match %u: %s\n", |
| 647 | m.line, m.match); | 662 | m.line, m.match); |
| 648 | ret = 1; | 663 | ret = 1; |
| @@ -65,8 +65,8 @@ void serial_test_bpf_obj_id(void) · 64 unmodified lines | |||
| 65 | if (CHECK_FAIL(err)) | 65 | if (CHECK_FAIL(err)) |
| 66 | goto done; | 66 | goto done; |
| 67 | 67 | ||
| 68 | prog = bpf_object__find_program_by_title(objs[i], | 68 | prog = bpf_object__find_program_by_name(objs[i], |
| 69 | "raw_tp/sys_enter"); | 69 | "test_obj_id"); |
| 70 | if (CHECK_FAIL(!prog)) | 70 | if (CHECK_FAIL(!prog)) |
| 71 | goto done; | 71 | goto done; |
| 72 | links[i] = bpf_program__attach(prog); | 72 | links[i] = bpf_program__attach(prog); |
| @@ -217,7 +217,7 @@ static bool found; · 216 unmodified lines | |||
| 217 | static int libbpf_debug_print(enum libbpf_print_level level, | 217 | static int libbpf_debug_print(enum libbpf_print_level level, |
| 218 | const char *format, va_list args) | 218 | const char *format, va_list args) |
| 219 | { | 219 | { |
| 220 | const char *log_buf; | 220 | const char *prog_name, *log_buf; |
| 221 | 221 | ||
| 222 | if (level != LIBBPF_WARN || | 222 | if (level != LIBBPF_WARN || |
| 223 | !strstr(format, "-- BEGIN PROG LOAD LOG --")) { | 223 | !strstr(format, "-- BEGIN PROG LOAD LOG --")) { |
| @@ -225,15 +225,14 @@ static int libbpf_debug_print(enum libbpf_print_level level, · 1 unmodified line | |||
| 225 | return 0; | 225 | return 0; |
| 226 | } | 226 | } |
| 227 | 227 | ||
| 228 | /* skip prog_name */ | 228 | prog_name = va_arg(args, char *); |
| 229 | va_arg(args, char *); | ||
| 230 | log_buf = va_arg(args, char *); | 229 | log_buf = va_arg(args, char *); |
| 231 | if (!log_buf) | 230 | if (!log_buf) |
| 232 | goto out; | 231 | goto out; |
| 233 | if (err_str && strstr(log_buf, err_str) != NULL) | 232 | if (err_str && strstr(log_buf, err_str) != NULL) |
| 234 | found = true; | 233 | found = true; |
| 235 | out: | 234 | out: |
| 236 | printf(format, log_buf); | 235 | printf(format, prog_name, log_buf); |
| 237 | return 0; | 236 | return 0; |
| 238 | } | 237 | } |
| 239 | 238 | ||
| @@ -22,7 +22,6 @@ · 21 unmodified lines | |||
| 22 | #include <bpf/libbpf.h> | 22 | #include <bpf/libbpf.h> |
| 23 | #include <bpf/btf.h> | 23 | #include <bpf/btf.h> |
| 24 | 24 | ||
| 25 | #include "bpf_rlimit.h" | ||
| 26 | #include "bpf_util.h" | 25 | #include "bpf_util.h" |
| 27 | #include "../test_btf.h" | 26 | #include "../test_btf.h" |
| 28 | #include "test_progs.h" | 27 | #include "test_progs.h" |
| @@ -67,9 +67,9 @@ static int run_test(int cgroup_fd, int server_fd, int family, int type) · 66 unmodified lines | |||
| 67 | goto close_bpf_object; | 67 | goto close_bpf_object; |
| 68 | } | 68 | } |
| 69 | 69 | ||
| 70 | prog = bpf_object__find_program_by_title(obj, v4 ? | 70 | prog = bpf_object__find_program_by_name(obj, v4 ? |
| 71 | "cgroup/connect4" : | 71 | "connect4" : |
| 72 | "cgroup/connect6"); | 72 | "connect6"); |
| 73 | if (CHECK(!prog, "find_prog", "connect prog not found\n")) { | 73 | if (CHECK(!prog, "find_prog", "connect prog not found\n")) { |
| 74 | err = -EIO; | 74 | err = -EIO; |
| 75 | goto close_bpf_object; | 75 | goto close_bpf_object; |
| @@ -83,9 +83,9 @@ static int run_test(int cgroup_fd, int server_fd, int family, int type) · 7 unmodified lines | |||
| 83 | goto close_bpf_object; | 83 | goto close_bpf_object; |
| 84 | } | 84 | } |
| 85 | 85 | ||
| 86 | prog = bpf_object__find_program_by_title(obj, v4 ? | 86 | prog = bpf_object__find_program_by_name(obj, v4 ? |
| 87 | "cgroup/getpeername4" : | 87 | "getpeername4" : |
| 88 | "cgroup/getpeername6"); | 88 | "getpeername6"); |
| 89 | if (CHECK(!prog, "find_prog", "getpeername prog not found\n")) { | 89 | if (CHECK(!prog, "find_prog", "getpeername prog not found\n")) { |
| 90 | err = -EIO; | 90 | err = -EIO; |
| 91 | goto close_bpf_object; | 91 | goto close_bpf_object; |
| @@ -99,9 +99,9 @@ static int run_test(int cgroup_fd, int server_fd, int family, int type) · 7 unmodified lines | |||
| 99 | goto close_bpf_object; | 99 | goto close_bpf_object; |
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | prog = bpf_object__find_program_by_title(obj, v4 ? | 102 | prog = bpf_object__find_program_by_name(obj, v4 ? |
| 103 | "cgroup/getsockname4" : | 103 | "getsockname4" : |
| 104 | "cgroup/getsockname6"); | 104 | "getsockname6"); |
| 105 | if (CHECK(!prog, "find_prog", "getsockname prog not found\n")) { | 105 | if (CHECK(!prog, "find_prog", "getsockname prog not found\n")) { |
| 106 | err = -EIO; | 106 | err = -EIO; |
| 107 | goto close_bpf_object; | 107 | goto close_bpf_object; |
| @@ -10,7 +10,7 @@ static int duration = 0; · 9 unmodified lines | |||
| 10 | 10 | ||
| 11 | #define STRUCT_TO_CHAR_PTR(struct_name) (const char *)&(struct struct_name) | 11 | #define STRUCT_TO_CHAR_PTR(struct_name) (const char *)&(struct struct_name) |
| 12 | 12 | ||
| 13 | #define MODULES_CASE(name, sec_name, tp_name) { \ | 13 | #define MODULES_CASE(name, pg_name, tp_name) { \ |
| 14 | .case_name = name, \ | 14 | .case_name = name, \ |
| 15 | .bpf_obj_file = "test_core_reloc_module.o", \ | 15 | .bpf_obj_file = "test_core_reloc_module.o", \ |
| 16 | .btf_src_file = NULL, /* find in kernel module BTFs */ \ | 16 | .btf_src_file = NULL, /* find in kernel module BTFs */ \ |
| @@ -28,7 +28,7 @@ static int duration = 0; · 11 unmodified lines | |||
| 28 | .comm_len = sizeof("test_progs"), \ | 28 | .comm_len = sizeof("test_progs"), \ |
| 29 | }, \ | 29 | }, \ |
| 30 | .output_len = sizeof(struct core_reloc_module_output), \ | 30 | .output_len = sizeof(struct core_reloc_module_output), \ |
| 31 | .prog_sec_name = sec_name, \ | 31 | .prog_name = pg_name, \ |
| 32 | .raw_tp_name = tp_name, \ | 32 | .raw_tp_name = tp_name, \ |
| 33 | .trigger = __trigger_module_test_read, \ | 33 | .trigger = __trigger_module_test_read, \ |
| 34 | .needs_testmod = true, \ | 34 | .needs_testmod = true, \ |
| @@ -43,7 +43,9 @@ static int duration = 0; · 8 unmodified lines | |||
| 43 | #define FLAVORS_CASE_COMMON(name) \ | 43 | #define FLAVORS_CASE_COMMON(name) \ |
| 44 | .case_name = #name, \ | 44 | .case_name = #name, \ |
| 45 | .bpf_obj_file = "test_core_reloc_flavors.o", \ | 45 | .bpf_obj_file = "test_core_reloc_flavors.o", \ |
| 46 | .btf_src_file = "btf__core_reloc_" #name ".o" \ | 46 | .btf_src_file = "btf__core_reloc_" #name ".o", \ |
| 47 | .raw_tp_name = "sys_enter", \ | ||
| 48 | .prog_name = "test_core_flavors" \ | ||
| 47 | 49 | ||
| 48 | #define FLAVORS_CASE(name) { \ | 50 | #define FLAVORS_CASE(name) { \ |
| 49 | FLAVORS_CASE_COMMON(name), \ | 51 | FLAVORS_CASE_COMMON(name), \ |
| @@ -66,7 +68,9 @@ static int duration = 0; · 16 unmodified lines | |||
| 66 | #define NESTING_CASE_COMMON(name) \ | 68 | #define NESTING_CASE_COMMON(name) \ |
| 67 | .case_name = #name, \ | 69 | .case_name = #name, \ |
| 68 | .bpf_obj_file = "test_core_reloc_nesting.o", \ | 70 | .bpf_obj_file = "test_core_reloc_nesting.o", \ |
| 69 | .btf_src_file = "btf__core_reloc_" #name ".o" | 71 | .btf_src_file = "btf__core_reloc_" #name ".o", \ |
| 72 | .raw_tp_name = "sys_enter", \ | ||
| 73 | .prog_name = "test_core_nesting" \ | ||
| 70 | 74 | ||
| 71 | #define NESTING_CASE(name) { \ | 75 | #define NESTING_CASE(name) { \ |
| 72 | NESTING_CASE_COMMON(name), \ | 76 | NESTING_CASE_COMMON(name), \ |
| @@ -91,7 +95,9 @@ static int duration = 0; · 18 unmodified lines | |||
| 91 | #define ARRAYS_CASE_COMMON(name) \ | 95 | #define ARRAYS_CASE_COMMON(name) \ |
| 92 | .case_name = #name, \ | 96 | .case_name = #name, \ |
| 93 | .bpf_obj_file = "test_core_reloc_arrays.o", \ | 97 | .bpf_obj_file = "test_core_reloc_arrays.o", \ |
| 94 | .btf_src_file = "btf__core_reloc_" #name ".o" | 98 | .btf_src_file = "btf__core_reloc_" #name ".o", \ |
| 99 | .raw_tp_name = "sys_enter", \ | ||
| 100 | .prog_name = "test_core_arrays" \ | ||
| 95 | 101 | ||
| 96 | #define ARRAYS_CASE(name) { \ | 102 | #define ARRAYS_CASE(name) { \ |
| 97 | ARRAYS_CASE_COMMON(name), \ | 103 | ARRAYS_CASE_COMMON(name), \ |
| @@ -123,7 +129,9 @@ static int duration = 0; · 25 unmodified lines | |||
| 123 | #define PRIMITIVES_CASE_COMMON(name) \ | 129 | #define PRIMITIVES_CASE_COMMON(name) \ |
| 124 | .case_name = #name, \ | 130 | .case_name = #name, \ |
| 125 | .bpf_obj_file = "test_core_reloc_primitives.o", \ | 131 | .bpf_obj_file = "test_core_reloc_primitives.o", \ |
| 126 | .btf_src_file = "btf__core_reloc_" #name ".o" | 132 | .btf_src_file = "btf__core_reloc_" #name ".o", \ |
| 133 | .raw_tp_name = "sys_enter", \ | ||
| 134 | .prog_name = "test_core_primitives" \ | ||
| 127 | 135 | ||
| 128 | #define PRIMITIVES_CASE(name) { \ | 136 | #define PRIMITIVES_CASE(name) { \ |
| 129 | PRIMITIVES_CASE_COMMON(name), \ | 137 | PRIMITIVES_CASE_COMMON(name), \ |
| @@ -158,6 +166,8 @@ static int duration = 0; · 28 unmodified lines | |||
| 158 | .e = 5, .f = 6, .g = 7, .h = 8, \ | 166 | .e = 5, .f = 6, .g = 7, .h = 8, \ |
| 159 | }, \ | 167 | }, \ |
| 160 | .output_len = sizeof(struct core_reloc_mods_output), \ | 168 | .output_len = sizeof(struct core_reloc_mods_output), \ |
| 169 | .raw_tp_name = "sys_enter", \ | ||
| 170 | .prog_name = "test_core_mods", \ | ||
| 161 | } | 171 | } |
| 162 | 172 | ||
| 163 | #define PTR_AS_ARR_CASE(name) { \ | 173 | #define PTR_AS_ARR_CASE(name) { \ |
| @@ -174,6 +184,8 @@ static int duration = 0; · 10 unmodified lines | |||
| 174 | .a = 3, \ | 184 | .a = 3, \ |
| 175 | }, \ | 185 | }, \ |
| 176 | .output_len = sizeof(struct core_reloc_ptr_as_arr), \ | 186 | .output_len = sizeof(struct core_reloc_ptr_as_arr), \ |
| 187 | .raw_tp_name = "sys_enter", \ | ||
| 188 | .prog_name = "test_core_ptr_as_arr", \ | ||
| 177 | } | 189 | } |
| 178 | 190 | ||
| 179 | #define INTS_DATA(struct_name) STRUCT_TO_CHAR_PTR(struct_name) { \ | 191 | #define INTS_DATA(struct_name) STRUCT_TO_CHAR_PTR(struct_name) { \ |
| @@ -190,7 +202,9 @@ static int duration = 0; · 10 unmodified lines | |||
| 190 | #define INTS_CASE_COMMON(name) \ | 202 | #define INTS_CASE_COMMON(name) \ |
| 191 | .case_name = #name, \ | 203 | .case_name = #name, \ |
| 192 | .bpf_obj_file = "test_core_reloc_ints.o", \ | 204 | .bpf_obj_file = "test_core_reloc_ints.o", \ |
| 193 | .btf_src_file = "btf__core_reloc_" #name ".o" | 205 | .btf_src_file = "btf__core_reloc_" #name ".o", \ |
| 206 | .raw_tp_name = "sys_enter", \ | ||
| 207 | .prog_name = "test_core_ints" | ||
| 194 | 208 | ||
| 195 | #define INTS_CASE(name) { \ | 209 | #define INTS_CASE(name) { \ |
| 196 | INTS_CASE_COMMON(name), \ | 210 | INTS_CASE_COMMON(name), \ |
| @@ -208,7 +222,9 @@ static int duration = 0; · 11 unmodified lines | |||
| 208 | #define FIELD_EXISTS_CASE_COMMON(name) \ | 222 | #define FIELD_EXISTS_CASE_COMMON(name) \ |
| 209 | .case_name = #name, \ | 223 | .case_name = #name, \ |
| 210 | .bpf_obj_file = "test_core_reloc_existence.o", \ | 224 | .bpf_obj_file = "test_core_reloc_existence.o", \ |
| 211 | .btf_src_file = "btf__core_reloc_" #name ".o" \ | 225 | .btf_src_file = "btf__core_reloc_" #name ".o", \ |
| 226 | .raw_tp_name = "sys_enter", \ | ||
| 227 | .prog_name = "test_core_existence" | ||
| 212 | 228 | ||
| 213 | #define BITFIELDS_CASE_COMMON(objfile, test_name_prefix, name) \ | 229 | #define BITFIELDS_CASE_COMMON(objfile, test_name_prefix, name) \ |
| 214 | .case_name = test_name_prefix#name, \ | 230 | .case_name = test_name_prefix#name, \ |
| @@ -223,6 +239,8 @@ static int duration = 0; · 8 unmodified lines | |||
| 223 | .output = STRUCT_TO_CHAR_PTR(core_reloc_bitfields_output) \ | 239 | .output = STRUCT_TO_CHAR_PTR(core_reloc_bitfields_output) \ |
| 224 | __VA_ARGS__, \ | 240 | __VA_ARGS__, \ |
| 225 | .output_len = sizeof(struct core_reloc_bitfields_output), \ | 241 | .output_len = sizeof(struct core_reloc_bitfields_output), \ |
| 242 | .raw_tp_name = "sys_enter", \ | ||
| 243 | .prog_name = "test_core_bitfields", \ | ||
| 226 | }, { \ | 244 | }, { \ |
| 227 | BITFIELDS_CASE_COMMON("test_core_reloc_bitfields_direct.o", \ | 245 | BITFIELDS_CASE_COMMON("test_core_reloc_bitfields_direct.o", \ |
| 228 | "direct:", name), \ | 246 | "direct:", name), \ |
| @@ -231,7 +249,7 @@ static int duration = 0; · 2 unmodified lines | |||
| 231 | .output = STRUCT_TO_CHAR_PTR(core_reloc_bitfields_output) \ | 249 | .output = STRUCT_TO_CHAR_PTR(core_reloc_bitfields_output) \ |
| 232 | __VA_ARGS__, \ | 250 | __VA_ARGS__, \ |
| 233 | .output_len = sizeof(struct core_reloc_bitfields_output), \ | 251 | .output_len = sizeof(struct core_reloc_bitfields_output), \ |
| 234 | .prog_sec_name = "tp_btf/sys_enter", \ | 252 | .prog_name = "test_core_bitfields_direct", \ |
| 235 | } | 253 | } |
| 236 | 254 | ||
| 237 | 255 | ||
| @@ -239,17 +257,21 @@ static int duration = 0; · 1 unmodified line | |||
| 239 | BITFIELDS_CASE_COMMON("test_core_reloc_bitfields_probed.o", \ | 257 | BITFIELDS_CASE_COMMON("test_core_reloc_bitfields_probed.o", \ |
| 240 | "probed:", name), \ | 258 | "probed:", name), \ |
| 241 | .fails = true, \ | 259 | .fails = true, \ |
| 260 | .raw_tp_name = "sys_enter", \ | ||
| 261 | .prog_name = "test_core_bitfields", \ | ||
| 242 | }, { \ | 262 | }, { \ |
| 243 | BITFIELDS_CASE_COMMON("test_core_reloc_bitfields_direct.o", \ | 263 | BITFIELDS_CASE_COMMON("test_core_reloc_bitfields_direct.o", \ |
| 244 | "direct:", name), \ | 264 | "direct:", name), \ |
| 245 | .prog_sec_name = "tp_btf/sys_enter", \ | ||
| 246 | .fails = true, \ | 265 | .fails = true, \ |
| 266 | .prog_name = "test_core_bitfields_direct", \ | ||
| 247 | } | 267 | } |
| 248 | 268 | ||
| 249 | #define SIZE_CASE_COMMON(name) \ | 269 | #define SIZE_CASE_COMMON(name) \ |
| 250 | .case_name = #name, \ | 270 | .case_name = #name, \ |
| 251 | .bpf_obj_file = "test_core_reloc_size.o", \ | 271 | .bpf_obj_file = "test_core_reloc_size.o", \ |
| 252 | .btf_src_file = "btf__core_reloc_" #name ".o" | 272 | .btf_src_file = "btf__core_reloc_" #name ".o", \ |
| 273 | .raw_tp_name = "sys_enter", \ | ||
| 274 | .prog_name = "test_core_size" | ||
| 253 | 275 | ||
| 254 | #define SIZE_OUTPUT_DATA(type) \ | 276 | #define SIZE_OUTPUT_DATA(type) \ |
| 255 | STRUCT_TO_CHAR_PTR(core_reloc_size_output) { \ | 277 | STRUCT_TO_CHAR_PTR(core_reloc_size_output) { \ |
| @@ -277,8 +299,10 @@ static int duration = 0; · 21 unmodified lines | |||
| 277 | 299 | ||
| 278 | #define TYPE_BASED_CASE_COMMON(name) \ | 300 | #define TYPE_BASED_CASE_COMMON(name) \ |
| 279 | .case_name = #name, \ | 301 | .case_name = #name, \ |
| 280 | .bpf_obj_file = "test_core_reloc_type_based.o", \ | 302 | .bpf_obj_file = "test_core_reloc_type_based.o", \ |
| 281 | .btf_src_file = "btf__core_reloc_" #name ".o" \ | 303 | .btf_src_file = "btf__core_reloc_" #name ".o", \ |
| 304 | .raw_tp_name = "sys_enter", \ | ||
| 305 | .prog_name = "test_core_type_based" | ||
| 282 | 306 | ||
| 283 | #define TYPE_BASED_CASE(name, ...) { \ | 307 | #define TYPE_BASED_CASE(name, ...) { \ |
| 284 | TYPE_BASED_CASE_COMMON(name), \ | 308 | TYPE_BASED_CASE_COMMON(name), \ |
| @@ -295,7 +319,9 @@ static int duration = 0; · 10 unmodified lines | |||
| 295 | #define TYPE_ID_CASE_COMMON(name) \ | 319 | #define TYPE_ID_CASE_COMMON(name) \ |
| 296 | .case_name = #name, \ | 320 | .case_name = #name, \ |
| 297 | .bpf_obj_file = "test_core_reloc_type_id.o", \ | 321 | .bpf_obj_file = "test_core_reloc_type_id.o", \ |
| 298 | .btf_src_file = "btf__core_reloc_" #name ".o" \ | 322 | .btf_src_file = "btf__core_reloc_" #name ".o", \ |
| 323 | .raw_tp_name = "sys_enter", \ | ||
| 324 | .prog_name = "test_core_type_id" | ||
| 299 | 325 | ||
| 300 | #define TYPE_ID_CASE(name, setup_fn) { \ | 326 | #define TYPE_ID_CASE(name, setup_fn) { \ |
| 301 | TYPE_ID_CASE_COMMON(name), \ | 327 | TYPE_ID_CASE_COMMON(name), \ |
| @@ -312,7 +338,9 @@ static int duration = 0; · 10 unmodified lines | |||
| 312 | #define ENUMVAL_CASE_COMMON(name) \ | 338 | #define ENUMVAL_CASE_COMMON(name) \ |
| 313 | .case_name = #name, \ | 339 | .case_name = #name, \ |
| 314 | .bpf_obj_file = "test_core_reloc_enumval.o", \ | 340 | .bpf_obj_file = "test_core_reloc_enumval.o", \ |
| 315 | .btf_src_file = "btf__core_reloc_" #name ".o" \ | 341 | .btf_src_file = "btf__core_reloc_" #name ".o", \ |
| 342 | .raw_tp_name = "sys_enter", \ | ||
| 343 | .prog_name = "test_core_enumval" | ||
| 316 | 344 | ||
| 317 | #define ENUMVAL_CASE(name, ...) { \ | 345 | #define ENUMVAL_CASE(name, ...) { \ |
| 318 | ENUMVAL_CASE_COMMON(name), \ | 346 | ENUMVAL_CASE_COMMON(name), \ |
| @@ -342,7 +370,7 @@ struct core_reloc_test_case { · 23 unmodified lines | |||
| 342 | bool fails; | 370 | bool fails; |
| 343 | bool needs_testmod; | 371 | bool needs_testmod; |
| 344 | bool relaxed_core_relocs; | 372 | bool relaxed_core_relocs; |
| 345 | const char *prog_sec_name; | 373 | const char *prog_name; |
| 346 | const char *raw_tp_name; | 374 | const char *raw_tp_name; |
| 347 | setup_test_fn setup; | 375 | setup_test_fn setup; |
| 348 | trigger_test_fn trigger; | 376 | trigger_test_fn trigger; |
| @@ -497,11 +525,13 @@ static struct core_reloc_test_case test_cases[] = { · 148 unmodified lines | |||
| 497 | .comm_len = sizeof("test_progs"), | 525 | .comm_len = sizeof("test_progs"), |
| 498 | }, | 526 | }, |
| 499 | .output_len = sizeof(struct core_reloc_kernel_output), | 527 | .output_len = sizeof(struct core_reloc_kernel_output), |
| 528 | .raw_tp_name = "sys_enter", | ||
| 529 | .prog_name = "test_core_kernel", | ||
| 500 | }, | 530 | }, |
| 501 | 531 | ||
| 502 | /* validate we can find kernel module BTF types for relocs/attach */ | 532 | /* validate we can find kernel module BTF types for relocs/attach */ |
| 503 | MODULES_CASE("module_probed", "raw_tp/bpf_testmod_test_read", "bpf_testmod_test_read"), | 533 | MODULES_CASE("module_probed", "test_core_module_probed", "bpf_testmod_test_read"), |
| 504 | MODULES_CASE("module_direct", "tp_btf/bpf_testmod_test_read", NULL), | 534 | MODULES_CASE("module_direct", "test_core_module_direct", NULL), |
| 505 | 535 | ||
| 506 | /* validate BPF program can use multiple flavors to match against | 536 | /* validate BPF program can use multiple flavors to match against |
| 507 | * single target BTF type | 537 | * single target BTF type |
| @@ -580,6 +610,8 @@ static struct core_reloc_test_case test_cases[] = { · 72 unmodified lines | |||
| 580 | .c = 0, /* BUG in clang, should be 3 */ | 610 | .c = 0, /* BUG in clang, should be 3 */ |
| 581 | }, | 611 | }, |
| 582 | .output_len = sizeof(struct core_reloc_misc_output), | 612 | .output_len = sizeof(struct core_reloc_misc_output), |
| 613 | .raw_tp_name = "sys_enter", | ||
| 614 | .prog_name = "test_core_misc", | ||
| 583 | }, | 615 | }, |
| 584 | 616 | ||
| 585 | /* validate field existence checks */ | 617 | /* validate field existence checks */ |
| @@ -848,14 +880,9 @@ void test_core_reloc(void) · 262 unmodified lines | |||
| 848 | if (!ASSERT_OK_PTR(obj, "obj_open")) | 880 | if (!ASSERT_OK_PTR(obj, "obj_open")) |
| 849 | goto cleanup; | 881 | goto cleanup; |
| 850 | 882 | ||
| 851 | probe_name = "raw_tracepoint/sys_enter"; | 883 | probe_name = test_case->prog_name; |
| 852 | tp_name = "sys_enter"; | 884 | tp_name = test_case->raw_tp_name; /* NULL for tp_btf */ |
| 853 | if (test_case->prog_sec_name) { | 885 | prog = bpf_object__find_program_by_name(obj, probe_name); |
| 854 | probe_name = test_case->prog_sec_name; | ||
| 855 | tp_name = test_case->raw_tp_name; /* NULL for tp_btf */ | ||
| 856 | } | ||
| 857 | |||
| 858 | prog = bpf_object__find_program_by_title(obj, probe_name); | ||
| 859 | if (CHECK(!prog, "find_probe", | 886 | if (CHECK(!prog, "find_probe", |
| 860 | "prog '%s' not found\n", probe_name)) | 887 | "prog '%s' not found\n", probe_name)) |
| 861 | goto cleanup; | 888 | goto cleanup; |
| @@ -101,6 +101,8 @@ static void test_fexit_bpf2bpf_common(const char *obj_file, · 100 unmodified lines | |||
| 101 | 101 | ||
| 102 | for (i = 0; i < prog_cnt; i++) { | 102 | for (i = 0; i < prog_cnt; i++) { |
| 103 | struct bpf_link_info link_info; | 103 | struct bpf_link_info link_info; |
| 104 | struct bpf_program *pos; | ||
| 105 | const char *pos_sec_name; | ||
| 104 | char *tgt_name; | 106 | char *tgt_name; |
| 105 | __s32 btf_id; | 107 | __s32 btf_id; |
| 106 | 108 | ||
| @@ -109,7 +111,14 @@ static void test_fexit_bpf2bpf_common(const char *obj_file, · 2 unmodified lines | |||
| 109 | goto close_prog; | 111 | goto close_prog; |
| 110 | btf_id = btf__find_by_name_kind(btf, tgt_name + 1, BTF_KIND_FUNC); | 112 | btf_id = btf__find_by_name_kind(btf, tgt_name + 1, BTF_KIND_FUNC); |
| 111 | 113 | ||
| 112 | prog[i] = bpf_object__find_program_by_title(obj, prog_name[i]); | 114 | prog[i] = NULL; |
| 115 | bpf_object__for_each_program(pos, obj) { | ||
| 116 | pos_sec_name = bpf_program__section_name(pos); | ||
| 117 | if (pos_sec_name && !strcmp(pos_sec_name, prog_name[i])) { | ||
| 118 | prog[i] = pos; | ||
| 119 | break; | ||
| 120 | } | ||
| 121 | } | ||
| 113 | if (!ASSERT_OK_PTR(prog[i], prog_name[i])) | 122 | if (!ASSERT_OK_PTR(prog[i], prog_name[i])) |
| 114 | goto close_prog; | 123 | goto close_prog; |
| 115 | 124 | ||
| @@ -211,8 +220,8 @@ static void test_func_replace_verify(void) · 95 unmodified lines | |||
| 211 | 220 | ||
| 212 | static int test_second_attach(struct bpf_object *obj) | 221 | static int test_second_attach(struct bpf_object *obj) |
| 213 | { | 222 | { |
| 214 | const char *prog_name = "freplace/get_constant"; | 223 | const char *prog_name = "security_new_get_constant"; |
| 215 | const char *tgt_name = prog_name + 9; /* cut off freplace/ */ | 224 | const char *tgt_name = "get_constant"; |
| 216 | const char *tgt_obj_file = "./test_pkt_access.o"; | 225 | const char *tgt_obj_file = "./test_pkt_access.o"; |
| 217 | struct bpf_program *prog = NULL; | 226 | struct bpf_program *prog = NULL; |
| 218 | struct bpf_object *tgt_obj; | 227 | struct bpf_object *tgt_obj; |
| @@ -220,7 +229,7 @@ static int test_second_attach(struct bpf_object *obj) · 1 unmodified line | |||
| 220 | struct bpf_link *link; | 229 | struct bpf_link *link; |
| 221 | int err = 0, tgt_fd; | 230 | int err = 0, tgt_fd; |
| 222 | 231 | ||
| 223 | prog = bpf_object__find_program_by_title(obj, prog_name); | 232 | prog = bpf_object__find_program_by_name(obj, prog_name); |
| 224 | if (CHECK(!prog, "find_prog", "prog %s not found\n", prog_name)) | 233 | if (CHECK(!prog, "find_prog", "prog %s not found\n", prog_name)) |
| 225 | return -ENOENT; | 234 | return -ENOENT; |
| 226 | 235 | ||
| @@ -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 | const char *file = "./test_get_stack_rawtp.o"; | 90 | const char *file = "./test_get_stack_rawtp.o"; |
| 91 | const char *file_err = "./test_get_stack_rawtp_err.o"; | 91 | const char *file_err = "./test_get_stack_rawtp_err.o"; |
| 92 | const char *prog_name = "raw_tracepoint/sys_enter"; | 92 | const char *prog_name = "bpf_prog1"; |
| 93 | int i, err, prog_fd, exp_cnt = MAX_CNT_RAWTP; | 93 | int i, err, prog_fd, exp_cnt = MAX_CNT_RAWTP; |
| 94 | struct perf_buffer *pb = NULL; | 94 | struct perf_buffer *pb = NULL; |
| 95 | struct bpf_link *link = NULL; | 95 | struct bpf_link *link = NULL; |
| @@ -107,7 +107,7 @@ void test_get_stack_raw_tp(void) · 11 unmodified lines | |||
| 107 | if (CHECK(err, "prog_load raw tp", "err %d errno %d\n", err, errno)) | 107 | if (CHECK(err, "prog_load raw tp", "err %d errno %d\n", err, errno)) |
| 108 | return; | 108 | return; |
| 109 | 109 | ||
| 110 | prog = bpf_object__find_program_by_title(obj, prog_name); | 110 | prog = bpf_object__find_program_by_name(obj, prog_name); |
| 111 | if (CHECK(!prog, "find_probe", "prog '%s' not found\n", prog_name)) | 111 | if (CHECK(!prog, "find_probe", "prog '%s' not found\n", prog_name)) |
| 112 | goto close_prog; | 112 | goto close_prog; |
| 113 | 113 | ||
| @@ -8,6 +8,7 @@ · 7 unmodified lines | |||
| 8 | #include "test_ksyms_btf_null_check.skel.h" | 8 | #include "test_ksyms_btf_null_check.skel.h" |
| 9 | #include "test_ksyms_weak.skel.h" | 9 | #include "test_ksyms_weak.skel.h" |
| 10 | #include "test_ksyms_weak.lskel.h" | 10 | #include "test_ksyms_weak.lskel.h" |
| 11 | #include "test_ksyms_btf_write_check.skel.h" | ||
| 11 | 12 | ||
| 12 | static int duration; | 13 | static int duration; |
| 13 | 14 | ||
| @@ -137,6 +138,16 @@ cleanup: · 123 unmodified lines | |||
| 137 | test_ksyms_weak_lskel__destroy(skel); | 138 | test_ksyms_weak_lskel__destroy(skel); |
| 138 | } | 139 | } |
| 139 | 140 | ||
| 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 | void test_ksyms_btf(void) | 151 | void test_ksyms_btf(void) |
| 141 | { | 152 | { |
| 142 | int percpu_datasec; | 153 | int percpu_datasec; |
| @@ -167,4 +178,7 @@ void test_ksyms_btf(void) · 24 unmodified lines | |||
| 167 | 178 | ||
| 168 | if (test__start_subtest("weak_ksyms_lskel")) | 179 | if (test__start_subtest("weak_ksyms_lskel")) |
| 169 | test_weak_syms_lskel(); | 180 | test_weak_syms_lskel(); |
| 181 | |||
| 182 | if (test__start_subtest("write_check")) | ||
| 183 | test_write_check(); | ||
| 170 | } | 184 | } |
| @@ -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 | #include <netinet/in.h> | 18 | #include <netinet/in.h> |
| 19 | #include <bpf/bpf.h> | 19 | #include <bpf/bpf.h> |
| 20 | #include <bpf/libbpf.h> | 20 | #include <bpf/libbpf.h> |
| 21 | #include "bpf_rlimit.h" | ||
| 22 | #include "bpf_util.h" | 21 | #include "bpf_util.h" |
| 23 | 22 | ||
| 24 | #include "test_progs.h" | 23 | #include "test_progs.h" |
| @@ -30,7 +30,6 @@ · 29 unmodified lines | |||
| 30 | #include <bpf/bpf.h> | 30 | #include <bpf/bpf.h> |
| 31 | 31 | ||
| 32 | #include "test_progs.h" | 32 | #include "test_progs.h" |
| 33 | #include "bpf_rlimit.h" | ||
| 34 | #include "bpf_util.h" | 33 | #include "bpf_util.h" |
| 35 | #include "cgroup_helpers.h" | 34 | #include "cgroup_helpers.h" |
| 36 | #include "network_helpers.h" | 35 | #include "network_helpers.h" |
| @@ -15,7 +15,6 @@ · 14 unmodified lines | |||
| 15 | #include "network_helpers.h" | 15 | #include "network_helpers.h" |
| 16 | #include "cgroup_helpers.h" | 16 | #include "cgroup_helpers.h" |
| 17 | #include "test_progs.h" | 17 | #include "test_progs.h" |
| 18 | #include "bpf_rlimit.h" | ||
| 19 | #include "test_sock_fields.skel.h" | 18 | #include "test_sock_fields.skel.h" |
| 20 | 19 | ||
| 21 | enum bpf_linum_array_idx { | 20 | enum bpf_linum_array_idx { |
| @@ -136,7 +136,8 @@ static int start_server(void) · 135 unmodified lines | |||
| 136 | return fd; | 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 | enum bpf_attach_type attach_type; | 142 | enum bpf_attach_type attach_type; |
| 142 | enum bpf_prog_type prog_type; | 143 | enum bpf_prog_type prog_type; |
| @@ -145,20 +146,20 @@ static int prog_attach(struct bpf_object *obj, int cgroup_fd, const char *title) · 2 unmodified lines | |||
| 145 | 146 | ||
| 146 | err = libbpf_prog_type_by_name(title, &prog_type, &attach_type); | 147 | err = libbpf_prog_type_by_name(title, &prog_type, &attach_type); |
| 147 | if (err) { | 148 | if (err) { |
| 148 | log_err("Failed to deduct types for %s BPF program", title); | 149 | log_err("Failed to deduct types for %s BPF program", prog_name); |
| 149 | return -1; | 150 | return -1; |
| 150 | } | 151 | } |
| 151 | 152 | ||
| 152 | prog = bpf_object__find_program_by_title(obj, title); | 153 | prog = bpf_object__find_program_by_name(obj, prog_name); |
| 153 | if (!prog) { | 154 | if (!prog) { |
| 154 | log_err("Failed to find %s BPF program", title); | 155 | log_err("Failed to find %s BPF program", prog_name); |
| 155 | return -1; | 156 | return -1; |
| 156 | } | 157 | } |
| 157 | 158 | ||
| 158 | err = bpf_prog_attach(bpf_program__fd(prog), cgroup_fd, | 159 | err = bpf_prog_attach(bpf_program__fd(prog), cgroup_fd, |
| 159 | attach_type, 0); | 160 | attach_type, 0); |
| 160 | if (err) { | 161 | if (err) { |
| 161 | log_err("Failed to attach %s BPF program", title); | 162 | log_err("Failed to attach %s BPF program", prog_name); |
| 162 | return -1; | 163 | return -1; |
| 163 | } | 164 | } |
| 164 | 165 | ||
| @@ -181,11 +182,11 @@ static void run_test(int cgroup_fd) · 16 unmodified lines | |||
| 181 | if (!ASSERT_OK(err, "obj_load")) | 182 | if (!ASSERT_OK(err, "obj_load")) |
| 182 | goto close_bpf_object; | 183 | goto close_bpf_object; |
| 183 | 184 | ||
| 184 | err = prog_attach(obj, cgroup_fd, "cgroup/getsockopt"); | 185 | err = prog_attach(obj, cgroup_fd, "cgroup/getsockopt", "_getsockopt"); |
| 185 | if (CHECK_FAIL(err)) | 186 | if (CHECK_FAIL(err)) |
| 186 | goto close_bpf_object; | 187 | goto close_bpf_object; |
| 187 | 188 | ||
| 188 | err = prog_attach(obj, cgroup_fd, "cgroup/setsockopt"); | 189 | err = prog_attach(obj, cgroup_fd, "cgroup/setsockopt", "_setsockopt"); |
| 189 | if (CHECK_FAIL(err)) | 190 | if (CHECK_FAIL(err)) |
| 190 | goto close_bpf_object; | 191 | goto close_bpf_object; |
| 191 | 192 | ||
| @@ -4,7 +4,7 @@ · 3 unmodified lines | |||
| 4 | void test_stacktrace_map(void) | 4 | void test_stacktrace_map(void) |
| 5 | { | 5 | { |
| 6 | int control_map_fd, stackid_hmap_fd, stackmap_fd, stack_amap_fd; | 6 | int control_map_fd, stackid_hmap_fd, stackmap_fd, stack_amap_fd; |
| 7 | const char *prog_name = "tracepoint/sched/sched_switch"; | 7 | const char *prog_name = "oncpu"; |
| 8 | int err, prog_fd, stack_trace_len; | 8 | int err, prog_fd, stack_trace_len; |
| 9 | const char *file = "./test_stacktrace_map.o"; | 9 | const char *file = "./test_stacktrace_map.o"; |
| 10 | __u32 key, val, duration = 0; | 10 | __u32 key, val, duration = 0; |
| @@ -16,7 +16,7 @@ void test_stacktrace_map(void) · 5 unmodified lines | |||
| 16 | if (CHECK(err, "prog_load", "err %d errno %d\n", err, errno)) | 16 | if (CHECK(err, "prog_load", "err %d errno %d\n", err, errno)) |
| 17 | return; | 17 | return; |
| 18 | 18 | ||
| 19 | prog = bpf_object__find_program_by_title(obj, prog_name); | 19 | prog = bpf_object__find_program_by_name(obj, prog_name); |
| 20 | if (CHECK(!prog, "find_prog", "prog '%s' not found\n", prog_name)) | 20 | if (CHECK(!prog, "find_prog", "prog '%s' not found\n", prog_name)) |
| 21 | goto close_prog; | 21 | goto close_prog; |
| 22 | 22 | ||
| @@ -3,7 +3,7 @@ · 2 unmodified lines | |||
| 3 | 3 | ||
| 4 | void test_stacktrace_map_raw_tp(void) | 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 | int control_map_fd, stackid_hmap_fd, stackmap_fd; | 7 | int control_map_fd, stackid_hmap_fd, stackmap_fd; |
| 8 | const char *file = "./test_stacktrace_map.o"; | 8 | const char *file = "./test_stacktrace_map.o"; |
| 9 | __u32 key, val, duration = 0; | 9 | __u32 key, val, duration = 0; |
| @@ -16,7 +16,7 @@ void test_stacktrace_map_raw_tp(void) · 6 unmodified lines | |||
| 16 | if (CHECK(err, "prog_load raw tp", "err %d errno %d\n", err, errno)) | 16 | if (CHECK(err, "prog_load raw tp", "err %d errno %d\n", err, errno)) |
| 17 | return; | 17 | return; |
| 18 | 18 | ||
| 19 | prog = bpf_object__find_program_by_title(obj, prog_name); | 19 | prog = bpf_object__find_program_by_name(obj, prog_name); |
| 20 | if (CHECK(!prog, "find_prog", "prog '%s' not found\n", prog_name)) | 20 | if (CHECK(!prog, "find_prog", "prog '%s' not found\n", prog_name)) |
| 21 | goto close_prog; | 21 | goto close_prog; |
| 22 | 22 | ||
| @@ -28,10 +28,6 @@ static unsigned int duration; · 27 unmodified lines | |||
| 28 | struct storage { | 28 | struct storage { |
| 29 | void *inode; | 29 | void *inode; |
| 30 | unsigned int value; | 30 | unsigned int value; |
| 31 | /* Lock ensures that spin locked versions of local stoage operations | ||
| 32 | * also work, most operations in this tests are still single threaded | ||
| 33 | */ | ||
| 34 | struct bpf_spin_lock lock; | ||
| 35 | }; | 31 | }; |
| 36 | 32 | ||
| 37 | /* Fork and exec the provided rm binary and return the exit code of the | 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 | static bool check_syscall_operations(int map_fd, int obj_fd) | 63 | static bool check_syscall_operations(int map_fd, int obj_fd) |
| 68 | { | 64 | { |
| 69 | struct storage val = { .value = TEST_STORAGE_VALUE, .lock = { 0 } }, | 65 | struct storage val = { .value = TEST_STORAGE_VALUE }, |
| 70 | lookup_val = { .value = 0, .lock = { 0 } }; | 66 | lookup_val = { .value = 0 }; |
| 71 | int err; | 67 | int err; |
| 72 | 68 | ||
| 73 | /* Looking up an existing element should fail initially */ | 69 | /* Looking up an existing element should fail initially */ |
| 74 | err = bpf_map_lookup_elem_flags(map_fd, &obj_fd, &lookup_val, | 70 | err = bpf_map_lookup_elem_flags(map_fd, &obj_fd, &lookup_val, 0); |
| 75 | BPF_F_LOCK); | ||
| 76 | if (CHECK(!err || errno != ENOENT, "bpf_map_lookup_elem", | 71 | if (CHECK(!err || errno != ENOENT, "bpf_map_lookup_elem", |
| 77 | "err:%d errno:%d\n", err, errno)) | 72 | "err:%d errno:%d\n", err, errno)) |
| 78 | return false; | 73 | return false; |
| 79 | 74 | ||
| 80 | /* Create a new element */ | 75 | /* Create a new element */ |
| 81 | err = bpf_map_update_elem(map_fd, &obj_fd, &val, | 76 | err = bpf_map_update_elem(map_fd, &obj_fd, &val, BPF_NOEXIST); |
| 82 | BPF_NOEXIST | BPF_F_LOCK); | ||
| 83 | if (CHECK(err < 0, "bpf_map_update_elem", "err:%d errno:%d\n", err, | 77 | if (CHECK(err < 0, "bpf_map_update_elem", "err:%d errno:%d\n", err, |
| 84 | errno)) | 78 | errno)) |
| 85 | return false; | 79 | return false; |
| 86 | 80 | ||
| 87 | /* Lookup the newly created element */ | 81 | /* Lookup the newly created element */ |
| 88 | err = bpf_map_lookup_elem_flags(map_fd, &obj_fd, &lookup_val, | 82 | err = bpf_map_lookup_elem_flags(map_fd, &obj_fd, &lookup_val, 0); |
| 89 | BPF_F_LOCK); | ||
| 90 | if (CHECK(err < 0, "bpf_map_lookup_elem", "err:%d errno:%d", err, | 83 | if (CHECK(err < 0, "bpf_map_lookup_elem", "err:%d errno:%d", err, |
| 91 | errno)) | 84 | errno)) |
| 92 | return false; | 85 | return false; |
| @@ -102,8 +95,7 @@ static bool check_syscall_operations(int map_fd, int obj_fd) · 9 unmodified lines | |||
| 102 | return false; | 95 | return false; |
| 103 | 96 | ||
| 104 | /* The lookup should fail, now that the element has been deleted */ | 97 | /* The lookup should fail, now that the element has been deleted */ |
| 105 | err = bpf_map_lookup_elem_flags(map_fd, &obj_fd, &lookup_val, | 98 | err = bpf_map_lookup_elem_flags(map_fd, &obj_fd, &lookup_val, 0); |
| 106 | BPF_F_LOCK); | ||
| 107 | if (CHECK(!err || errno != ENOENT, "bpf_map_lookup_elem", | 99 | if (CHECK(!err || errno != ENOENT, "bpf_map_lookup_elem", |
| 108 | "err:%d errno:%d\n", err, errno)) | 100 | "err:%d errno:%d\n", err, errno)) |
| 109 | return false; | 101 | return false; |
| @@ -56,11 +56,11 @@ static void setaffinity(void) · 55 unmodified lines | |||
| 56 | 56 | ||
| 57 | void test_test_overhead(void) | 57 | void test_test_overhead(void) |
| 58 | { | 58 | { |
| 59 | const char *kprobe_name = "kprobe/__set_task_comm"; | 59 | const char *kprobe_name = "prog1"; |
| 60 | const char *kretprobe_name = "kretprobe/__set_task_comm"; | 60 | const char *kretprobe_name = "prog2"; |
| 61 | const char *raw_tp_name = "raw_tp/task_rename"; | 61 | const char *raw_tp_name = "prog3"; |
| 62 | const char *fentry_name = "fentry/__set_task_comm"; | 62 | const char *fentry_name = "prog4"; |
| 63 | const char *fexit_name = "fexit/__set_task_comm"; | 63 | const char *fexit_name = "prog5"; |
| 64 | const char *kprobe_func = "__set_task_comm"; | 64 | const char *kprobe_func = "__set_task_comm"; |
| 65 | struct bpf_program *kprobe_prog, *kretprobe_prog, *raw_tp_prog; | 65 | struct bpf_program *kprobe_prog, *kretprobe_prog, *raw_tp_prog; |
| 66 | struct bpf_program *fentry_prog, *fexit_prog; | 66 | struct bpf_program *fentry_prog, *fexit_prog; |
| @@ -76,23 +76,23 @@ void test_test_overhead(void) · 9 unmodified lines | |||
| 76 | if (!ASSERT_OK_PTR(obj, "obj_open_file")) | 76 | if (!ASSERT_OK_PTR(obj, "obj_open_file")) |
| 77 | return; | 77 | return; |
| 78 | 78 | ||
| 79 | kprobe_prog = bpf_object__find_program_by_title(obj, kprobe_name); | 79 | kprobe_prog = bpf_object__find_program_by_name(obj, kprobe_name); |
| 80 | if (CHECK(!kprobe_prog, "find_probe", | 80 | if (CHECK(!kprobe_prog, "find_probe", |
| 81 | "prog '%s' not found\n", kprobe_name)) | 81 | "prog '%s' not found\n", kprobe_name)) |
| 82 | goto cleanup; | 82 | goto cleanup; |
| 83 | kretprobe_prog = bpf_object__find_program_by_title(obj, kretprobe_name); | 83 | kretprobe_prog = bpf_object__find_program_by_name(obj, kretprobe_name); |
| 84 | if (CHECK(!kretprobe_prog, "find_probe", | 84 | if (CHECK(!kretprobe_prog, "find_probe", |
| 85 | "prog '%s' not found\n", kretprobe_name)) | 85 | "prog '%s' not found\n", kretprobe_name)) |
| 86 | goto cleanup; | 86 | goto cleanup; |
| 87 | raw_tp_prog = bpf_object__find_program_by_title(obj, raw_tp_name); | 87 | raw_tp_prog = bpf_object__find_program_by_name(obj, raw_tp_name); |
| 88 | if (CHECK(!raw_tp_prog, "find_probe", | 88 | if (CHECK(!raw_tp_prog, "find_probe", |
| 89 | "prog '%s' not found\n", raw_tp_name)) | 89 | "prog '%s' not found\n", raw_tp_name)) |
| 90 | goto cleanup; | 90 | goto cleanup; |
| 91 | fentry_prog = bpf_object__find_program_by_title(obj, fentry_name); | 91 | fentry_prog = bpf_object__find_program_by_name(obj, fentry_name); |
| 92 | if (CHECK(!fentry_prog, "find_probe", | 92 | if (CHECK(!fentry_prog, "find_probe", |
| 93 | "prog '%s' not found\n", fentry_name)) | 93 | "prog '%s' not found\n", fentry_name)) |
| 94 | goto cleanup; | 94 | goto cleanup; |
| 95 | fexit_prog = bpf_object__find_program_by_title(obj, fexit_name); | 95 | fexit_prog = bpf_object__find_program_by_name(obj, fexit_name); |
| 96 | if (CHECK(!fexit_prog, "find_probe", | 96 | if (CHECK(!fexit_prog, "find_probe", |
| 97 | "prog '%s' not found\n", fexit_name)) | 97 | "prog '%s' not found\n", fexit_name)) |
| 98 | goto cleanup; | 98 | goto cleanup; |
| @@ -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 | struct bpf_program *prog; | 35 | struct bpf_program *prog; |
| 36 | int duration = 0; | 36 | int duration = 0; |
| 37 | 37 | ||
| 38 | prog = bpf_object__find_program_by_title(obj, name); | 38 | prog = bpf_object__find_program_by_name(obj, name); |
| 39 | if (CHECK(!prog, "find_probe", "prog '%s' not found\n", name)) | 39 | if (CHECK(!prog, "find_probe", "prog '%s' not found\n", name)) |
| 40 | return ERR_PTR(-EINVAL); | 40 | return ERR_PTR(-EINVAL); |
| 41 | return bpf_program__attach_trace(prog); | 41 | return bpf_program__attach_trace(prog); |
| @@ -44,8 +44,8 @@ static struct bpf_link *load(struct bpf_object *obj, const char *name) · 2 unmodified lines | |||
| 44 | /* TODO: use different target function to run in concurrent mode */ | 44 | /* TODO: use different target function to run in concurrent mode */ |
| 45 | void serial_test_trampoline_count(void) | 45 | void serial_test_trampoline_count(void) |
| 46 | { | 46 | { |
| 47 | const char *fentry_name = "fentry/__set_task_comm"; | 47 | const char *fentry_name = "prog1"; |
| 48 | const char *fexit_name = "fexit/__set_task_comm"; | 48 | const char *fexit_name = "prog2"; |
| 49 | const char *object = "test_trampoline_count.o"; | 49 | const char *object = "test_trampoline_count.o"; |
| 50 | struct inst inst[MAX_TRAMP_PROGS] = {}; | 50 | struct inst inst[MAX_TRAMP_PROGS] = {}; |
| 51 | int err, i = 0, duration = 0; | 51 | int err, i = 0, duration = 0; |
| @@ -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 | struct local_storage { | 20 | struct local_storage { |
| 21 | struct inode *exec_inode; | 21 | struct inode *exec_inode; |
| 22 | __u32 value; | 22 | __u32 value; |
| 23 | struct bpf_spin_lock lock; | ||
| 24 | }; | 23 | }; |
| 25 | 24 | ||
| 26 | struct { | 25 | struct { |
| @@ -58,9 +57,7 @@ int BPF_PROG(unlink_hook, struct inode *dir, struct dentry *victim) · 31 unmodified lines | |||
| 58 | bpf_get_current_task_btf(), 0, 0); | 57 | bpf_get_current_task_btf(), 0, 0); |
| 59 | if (storage) { | 58 | if (storage) { |
| 60 | /* Don't let an executable delete itself */ | 59 | /* Don't let an executable delete itself */ |
| 61 | bpf_spin_lock(&storage->lock); | ||
| 62 | is_self_unlink = storage->exec_inode == victim->d_inode; | 60 | is_self_unlink = storage->exec_inode == victim->d_inode; |
| 63 | bpf_spin_unlock(&storage->lock); | ||
| 64 | if (is_self_unlink) | 61 | if (is_self_unlink) |
| 65 | return -EPERM; | 62 | return -EPERM; |
| 66 | } | 63 | } |
| @@ -68,7 +65,7 @@ int BPF_PROG(unlink_hook, struct inode *dir, struct dentry *victim) · 1 unmodified line | |||
| 68 | return 0; | 65 | return 0; |
| 69 | } | 66 | } |
| 70 | 67 | ||
| 71 | SEC("lsm/inode_rename") | 68 | SEC("lsm.s/inode_rename") |
| 72 | int BPF_PROG(inode_rename, struct inode *old_dir, struct dentry *old_dentry, | 69 | int BPF_PROG(inode_rename, struct inode *old_dir, struct dentry *old_dentry, |
| 73 | struct inode *new_dir, struct dentry *new_dentry, | 70 | struct inode *new_dir, struct dentry *new_dentry, |
| 74 | unsigned int flags) | 71 | unsigned int flags) |
| @@ -89,10 +86,8 @@ int BPF_PROG(inode_rename, struct inode *old_dir, struct dentry *old_dentry, · 14 unmodified lines | |||
| 89 | if (!storage) | 86 | if (!storage) |
| 90 | return 0; | 87 | return 0; |
| 91 | 88 | ||
| 92 | bpf_spin_lock(&storage->lock); | ||
| 93 | if (storage->value != DUMMY_STORAGE_VALUE) | 89 | if (storage->value != DUMMY_STORAGE_VALUE) |
| 94 | inode_storage_result = -1; | 90 | inode_storage_result = -1; |
| 95 | bpf_spin_unlock(&storage->lock); | ||
| 96 | 91 | ||
| 97 | err = bpf_inode_storage_delete(&inode_storage_map, old_dentry->d_inode); | 92 | err = bpf_inode_storage_delete(&inode_storage_map, old_dentry->d_inode); |
| 98 | if (!err) | 93 | if (!err) |
| @@ -101,7 +96,7 @@ int BPF_PROG(inode_rename, struct inode *old_dir, struct dentry *old_dentry, · 2 unmodified lines | |||
| 101 | return 0; | 96 | return 0; |
| 102 | } | 97 | } |
| 103 | 98 | ||
| 104 | SEC("lsm/socket_bind") | 99 | SEC("lsm.s/socket_bind") |
| 105 | int BPF_PROG(socket_bind, struct socket *sock, struct sockaddr *address, | 100 | int BPF_PROG(socket_bind, struct socket *sock, struct sockaddr *address, |
| 106 | int addrlen) | 101 | int addrlen) |
| 107 | { | 102 | { |
| @@ -117,10 +112,8 @@ int BPF_PROG(socket_bind, struct socket *sock, struct sockaddr *address, · 9 unmodified lines | |||
| 117 | if (!storage) | 112 | if (!storage) |
| 118 | return 0; | 113 | return 0; |
| 119 | 114 | ||
| 120 | bpf_spin_lock(&storage->lock); | ||
| 121 | if (storage->value != DUMMY_STORAGE_VALUE) | 115 | if (storage->value != DUMMY_STORAGE_VALUE) |
| 122 | sk_storage_result = -1; | 116 | sk_storage_result = -1; |
| 123 | bpf_spin_unlock(&storage->lock); | ||
| 124 | 117 | ||
| 125 | err = bpf_sk_storage_delete(&sk_storage_map, sock->sk); | 118 | err = bpf_sk_storage_delete(&sk_storage_map, sock->sk); |
| 126 | if (!err) | 119 | if (!err) |
| @@ -129,7 +122,7 @@ int BPF_PROG(socket_bind, struct socket *sock, struct sockaddr *address, · 2 unmodified lines | |||
| 129 | return 0; | 122 | return 0; |
| 130 | } | 123 | } |
| 131 | 124 | ||
| 132 | SEC("lsm/socket_post_create") | 125 | SEC("lsm.s/socket_post_create") |
| 133 | int BPF_PROG(socket_post_create, struct socket *sock, int family, int type, | 126 | int BPF_PROG(socket_post_create, struct socket *sock, int family, int type, |
| 134 | int protocol, int kern) | 127 | int protocol, int kern) |
| 135 | { | 128 | { |
| @@ -144,9 +137,7 @@ int BPF_PROG(socket_post_create, struct socket *sock, int family, int type, · 8 unmodified lines | |||
| 144 | if (!storage) | 137 | if (!storage) |
| 145 | return 0; | 138 | return 0; |
| 146 | 139 | ||
| 147 | bpf_spin_lock(&storage->lock); | ||
| 148 | storage->value = DUMMY_STORAGE_VALUE; | 140 | storage->value = DUMMY_STORAGE_VALUE; |
| 149 | bpf_spin_unlock(&storage->lock); | ||
| 150 | 141 | ||
| 151 | return 0; | 142 | return 0; |
| 152 | } | 143 | } |
| @@ -154,7 +145,7 @@ int BPF_PROG(socket_post_create, struct socket *sock, int family, int type, · 1 unmodified line | |||
| 154 | /* This uses the local storage to remember the inode of the binary that a | 145 | /* This uses the local storage to remember the inode of the binary that a |
| 155 | * process was originally executing. | 146 | * process was originally executing. |
| 156 | */ | 147 | */ |
| 157 | SEC("lsm/bprm_committed_creds") | 148 | SEC("lsm.s/bprm_committed_creds") |
| 158 | void BPF_PROG(exec, struct linux_binprm *bprm) | 149 | void BPF_PROG(exec, struct linux_binprm *bprm) |
| 159 | { | 150 | { |
| 160 | __u32 pid = bpf_get_current_pid_tgid() >> 32; | 151 | __u32 pid = bpf_get_current_pid_tgid() >> 32; |
| @@ -166,18 +157,13 @@ void BPF_PROG(exec, struct linux_binprm *bprm) · 5 unmodified lines | |||
| 166 | storage = bpf_task_storage_get(&task_storage_map, | 157 | storage = bpf_task_storage_get(&task_storage_map, |
| 167 | bpf_get_current_task_btf(), 0, | 158 | bpf_get_current_task_btf(), 0, |
| 168 | BPF_LOCAL_STORAGE_GET_F_CREATE); | 159 | BPF_LOCAL_STORAGE_GET_F_CREATE); |
| 169 | if (storage) { | 160 | if (storage) |
| 170 | bpf_spin_lock(&storage->lock); | ||
| 171 | storage->exec_inode = bprm->file->f_inode; | 161 | storage->exec_inode = bprm->file->f_inode; |
| 172 | bpf_spin_unlock(&storage->lock); | ||
| 173 | } | ||
| 174 | 162 | ||
| 175 | storage = bpf_inode_storage_get(&inode_storage_map, bprm->file->f_inode, | 163 | storage = bpf_inode_storage_get(&inode_storage_map, bprm->file->f_inode, |
| 176 | 0, BPF_LOCAL_STORAGE_GET_F_CREATE); | 164 | 0, BPF_LOCAL_STORAGE_GET_F_CREATE); |
| 177 | if (!storage) | 165 | if (!storage) |
| 178 | return; | 166 | return; |
| 179 | 167 | ||
| 180 | bpf_spin_lock(&storage->lock); | ||
| 181 | storage->value = DUMMY_STORAGE_VALUE; | 168 | storage->value = DUMMY_STORAGE_VALUE; |
| 182 | bpf_spin_unlock(&storage->lock); | ||
| 183 | } | 169 | } |
| @@ -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 | /* do nothing, just make sure we can link successfully */ | 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 | int main(int argc, char *argv[]) | 14 | int main(int argc, char *argv[]) |
| 11 | { | 15 | { |
| 16 | struct btf_dump_opts opts = { }; | ||
| 12 | struct test_core_extern *skel; | 17 | struct test_core_extern *skel; |
| 18 | struct btf *btf; | ||
| 13 | 19 | ||
| 14 | /* libbpf.h */ | 20 | /* libbpf.h */ |
| 15 | libbpf_set_print(NULL); | 21 | libbpf_set_print(NULL); |
| @@ -18,7 +24,8 @@ int main(int argc, char *argv[]) · 2 unmodified lines | |||
| 18 | bpf_prog_get_fd_by_id(0); | 24 | bpf_prog_get_fd_by_id(0); |
| 19 | 25 | ||
| 20 | /* btf.h */ | 26 | /* btf.h */ |
| 21 | btf__new(NULL, 0); | 27 | btf = btf__new(NULL, 0); |
| 28 | btf_dump__new(btf, dump_printf, nullptr, &opts); | ||
| 22 | 29 | ||
| 23 | /* BPF skeleton */ | 30 | /* BPF skeleton */ |
| 24 | skel = test_core_extern__open_and_load(); | 31 | skel = test_core_extern__open_and_load(); |
| @@ -23,7 +23,6 @@ · 22 unmodified lines | |||
| 23 | #include <bpf/libbpf.h> | 23 | #include <bpf/libbpf.h> |
| 24 | 24 | ||
| 25 | #include "bpf_util.h" | 25 | #include "bpf_util.h" |
| 26 | #include "bpf_rlimit.h" | ||
| 27 | #include "test_maps.h" | 26 | #include "test_maps.h" |
| 28 | #include "testing_helpers.h" | 27 | #include "testing_helpers.h" |
| 29 | 28 | ||
| @@ -4,7 +4,6 @@ · 3 unmodified lines | |||
| 4 | #define _GNU_SOURCE | 4 | #define _GNU_SOURCE |
| 5 | #include "test_progs.h" | 5 | #include "test_progs.h" |
| 6 | #include "cgroup_helpers.h" | 6 | #include "cgroup_helpers.h" |
| 7 | #include "bpf_rlimit.h" | ||
| 8 | #include <argp.h> | 7 | #include <argp.h> |
| 9 | #include <pthread.h> | 8 | #include <pthread.h> |
| 10 | #include <sched.h> | 9 | #include <sched.h> |
| @@ -1342,7 +1341,6 @@ int main(int argc, char **argv) · 1331 unmodified lines | |||
| 1342 | 1341 | ||
| 1343 | /* Use libbpf 1.0 API mode */ | 1342 | /* Use libbpf 1.0 API mode */ |
| 1344 | libbpf_set_strict_mode(LIBBPF_STRICT_ALL); | 1343 | libbpf_set_strict_mode(LIBBPF_STRICT_ALL); |
| 1345 | |||
| 1346 | libbpf_set_print(libbpf_print_fn); | 1344 | libbpf_set_print(libbpf_print_fn); |
| 1347 | 1345 | ||
| 1348 | srand(time(NULL)); | 1346 | srand(time(NULL)); |
| @@ -41,7 +41,6 @@ · 40 unmodified lines | |||
| 41 | # define CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS 1 | 41 | # define CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS 1 |
| 42 | # endif | 42 | # endif |
| 43 | #endif | 43 | #endif |
| 44 | #include "bpf_rlimit.h" | ||
| 45 | #include "bpf_rand.h" | 44 | #include "bpf_rand.h" |
| 46 | #include "bpf_util.h" | 45 | #include "bpf_util.h" |
| 47 | #include "test_btf.h" | 46 | #include "test_btf.h" |
| @@ -701,22 +700,18 @@ static int create_sk_storage_map(void) · 653 unmodified lines | |||
| 701 | 700 | ||
| 702 | static int create_map_timer(void) | 701 | static int create_map_timer(void) |
| 703 | { | 702 | { |
| 704 | struct bpf_create_map_attr attr = { | 703 | LIBBPF_OPTS(bpf_map_create_opts, opts, |
| 705 | .name = "test_map", | ||
| 706 | .map_type = BPF_MAP_TYPE_ARRAY, | ||
| 707 | .key_size = 4, | ||
| 708 | .value_size = 16, | ||
| 709 | .max_entries = 1, | ||
| 710 | .btf_key_type_id = 1, | 704 | .btf_key_type_id = 1, |
| 711 | .btf_value_type_id = 5, | 705 | .btf_value_type_id = 5, |
| 712 | }; | 706 | ); |
| 713 | int fd, btf_fd; | 707 | int fd, btf_fd; |
| 714 | 708 | ||
| 715 | btf_fd = load_btf(); | 709 | btf_fd = load_btf(); |
| 716 | if (btf_fd < 0) | 710 | if (btf_fd < 0) |
| 717 | return -1; | 711 | return -1; |
| 718 | attr.btf_fd = btf_fd; | 712 | |
| 719 | fd = bpf_create_map_xattr(&attr); | 713 | opts.btf_fd = btf_fd; |
| 714 | fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, "test_map", 4, 16, 1, &opts); | ||
| 720 | if (fd < 0) | 715 | if (fd < 0) |
| 721 | printf("Failed to create map with timer\n"); | 716 | printf("Failed to create map with timer\n"); |
| 722 | return fd; | 717 | return fd; |
| @@ -1399,6 +1394,9 @@ int main(int argc, char **argv) · 676 unmodified lines | |||
| 1399 | return EXIT_FAILURE; | 1394 | return EXIT_FAILURE; |
| 1400 | } | 1395 | } |
| 1401 | 1396 | ||
| 1397 | /* Use libbpf 1.0 API mode */ | ||
| 1398 | libbpf_set_strict_mode(LIBBPF_STRICT_ALL); | ||
| 1399 | |||
| 1402 | bpf_semi_rand_init(); | 1400 | bpf_semi_rand_init(); |
| 1403 | return do_test(unpriv, from, to); | 1401 | return do_test(unpriv, from, to); |
| 1404 | } | 1402 | } |
| @@ -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 | OUTPUT_DIR="$HOME/.bpf_selftests" | 32 | OUTPUT_DIR="$HOME/.bpf_selftests" |
| 33 | KCONFIG_URL="https://raw.githubusercontent.com/libbpf/libbpf/master/travis-ci/vmtest/configs/config-latest.${ARCH}" | 33 | KCONFIG_URL="https://raw.githubusercontent.com/libbpf/libbpf/master/travis-ci/vmtest/configs/config-latest.${ARCH}" |
| 34 | KCONFIG_API_URL="https://api.github.com/repos/libbpf/libbpf/contents/travis-ci/vmtest/configs/config-latest.${ARCH}" | 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 | NUM_COMPILE_JOBS="$(nproc)" | 36 | NUM_COMPILE_JOBS="$(nproc)" |
| 37 | LOG_FILE_BASE="$(date +"bpf_selftests.%Y-%m-%d_%H-%M-%S")" | 37 | LOG_FILE_BASE="$(date +"bpf_selftests.%Y-%m-%d_%H-%M-%S")" |
| 38 | LOG_FILE="${LOG_FILE_BASE}.log" | 38 | LOG_FILE="${LOG_FILE_BASE}.log" |