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

Alexei Starovoitov says:

====================
pull-request: bpf-next 2021-12-30

The following pull-request contains BPF updates for your *net-next* tree.

We've added 72 non-merge commits during the last 20 day(s) which contain
a total of 223 files changed, 3510 insertions(+), 1591 deletions(-).

The main changes are:

1) Automatic setrlimit in libbpf when bpf is memcg's in the kernel, from Andrii.

2) Beautify and de-verbose verifier logs, from Christy.

3) Composable verifier types, from Hao.

4) bpf_strncmp helper, from Hou.

5) bpf.h header dependency cleanup, from Jakub.

6) get_func_[arg|ret|arg_cnt] helpers, from Jiri.

7) Sleepable local storage, from KP.

8) Extend kfunc with PTR_TO_CTX, PTR_TO_MEM argument support, from Kumar.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller
2021-12-31 14:35:40 +00:00
221 changed files with 3501 additions and 1586 deletions

View File

@@ -170,7 +170,7 @@ $(OUTPUT)/%:%.c
$(OUTPUT)/urandom_read: urandom_read.c
$(call msg,BINARY,,$@)
$(Q)$(CC) $(LDFLAGS) $< $(LDLIBS) -Wl,--build-id=sha1 -o $@
$(Q)$(CC) $(CFLAGS) $(LDFLAGS) $< $(LDLIBS) -Wl,--build-id=sha1 -o $@
$(OUTPUT)/bpf_testmod.ko: $(VMLINUX_BTF) $(wildcard bpf_testmod/Makefile bpf_testmod/*.[ch])
$(call msg,MOD,,$@)
@@ -217,7 +217,7 @@ BPFTOOL ?= $(DEFAULT_BPFTOOL)
$(DEFAULT_BPFTOOL): $(wildcard $(BPFTOOLDIR)/*.[ch] $(BPFTOOLDIR)/Makefile) \
$(HOST_BPFOBJ) | $(HOST_BUILD_DIR)/bpftool
$(Q)$(MAKE) $(submake_extras) -C $(BPFTOOLDIR) \
CC=$(HOSTCC) LD=$(HOSTLD) \
ARCH= CROSS_COMPILE= CC=$(HOSTCC) LD=$(HOSTLD) \
EXTRA_CFLAGS='-g -O0' \
OUTPUT=$(HOST_BUILD_DIR)/bpftool/ \
LIBBPF_OUTPUT=$(HOST_BUILD_DIR)/libbpf/ \
@@ -248,7 +248,7 @@ $(HOST_BPFOBJ): $(wildcard $(BPFDIR)/*.[ch] $(BPFDIR)/Makefile) \
$(APIDIR)/linux/bpf.h \
| $(HOST_BUILD_DIR)/libbpf
$(Q)$(MAKE) $(submake_extras) -C $(BPFDIR) \
EXTRA_CFLAGS='-g -O0' \
EXTRA_CFLAGS='-g -O0' ARCH= CROSS_COMPILE= \
OUTPUT=$(HOST_BUILD_DIR)/libbpf/ CC=$(HOSTCC) LD=$(HOSTLD) \
DESTDIR=$(HOST_SCRATCH_DIR)/ prefix= all install_headers
endif
@@ -537,6 +537,7 @@ $(OUTPUT)/bench_ringbufs.o: $(OUTPUT)/ringbuf_bench.skel.h \
$(OUTPUT)/perfbuf_bench.skel.h
$(OUTPUT)/bench_bloom_filter_map.o: $(OUTPUT)/bloom_filter_bench.skel.h
$(OUTPUT)/bench_bpf_loop.o: $(OUTPUT)/bpf_loop_bench.skel.h
$(OUTPUT)/bench_strncmp.o: $(OUTPUT)/strncmp_bench.skel.h
$(OUTPUT)/bench.o: bench.h testing_helpers.h $(BPFOBJ)
$(OUTPUT)/bench: LDLIBS += -lm
$(OUTPUT)/bench: $(OUTPUT)/bench.o \
@@ -547,9 +548,10 @@ $(OUTPUT)/bench: $(OUTPUT)/bench.o \
$(OUTPUT)/bench_trigger.o \
$(OUTPUT)/bench_ringbufs.o \
$(OUTPUT)/bench_bloom_filter_map.o \
$(OUTPUT)/bench_bpf_loop.o
$(OUTPUT)/bench_bpf_loop.o \
$(OUTPUT)/bench_strncmp.o
$(call msg,BINARY,,$@)
$(Q)$(CC) $(LDFLAGS) $(filter %.a %.o,$^) $(LDLIBS) -o $@
$(Q)$(CC) $(CFLAGS) $(LDFLAGS) $(filter %.a %.o,$^) $(LDLIBS) -o $@
EXTRA_CLEAN := $(TEST_CUSTOM_PROGS) $(SCRATCH_DIR) $(HOST_SCRATCH_DIR) \
prog_tests/tests.h map_tests/tests.h verifier/tests.h \

View File

@@ -29,26 +29,10 @@ static int libbpf_print_fn(enum libbpf_print_level level,
return vfprintf(stderr, format, args);
}
static int bump_memlock_rlimit(void)
void setup_libbpf(void)
{
struct rlimit rlim_new = {
.rlim_cur = RLIM_INFINITY,
.rlim_max = RLIM_INFINITY,
};
return setrlimit(RLIMIT_MEMLOCK, &rlim_new);
}
void setup_libbpf()
{
int err;
libbpf_set_strict_mode(LIBBPF_STRICT_ALL);
libbpf_set_print(libbpf_print_fn);
err = bump_memlock_rlimit();
if (err)
fprintf(stderr, "failed to increase RLIMIT_MEMLOCK: %d", err);
}
void false_hits_report_progress(int iter, struct bench_res *res, long delta_ns)
@@ -205,11 +189,13 @@ static const struct argp_option opts[] = {
extern struct argp bench_ringbufs_argp;
extern struct argp bench_bloom_map_argp;
extern struct argp bench_bpf_loop_argp;
extern struct argp bench_strncmp_argp;
static const struct argp_child bench_parsers[] = {
{ &bench_ringbufs_argp, 0, "Ring buffers benchmark", 0 },
{ &bench_bloom_map_argp, 0, "Bloom filter map benchmark", 0 },
{ &bench_bpf_loop_argp, 0, "bpf_loop helper benchmark", 0 },
{ &bench_strncmp_argp, 0, "bpf_strncmp helper benchmark", 0 },
{},
};
@@ -409,6 +395,8 @@ extern const struct bench bench_bloom_false_positive;
extern const struct bench bench_hashmap_without_bloom;
extern const struct bench bench_hashmap_with_bloom;
extern const struct bench bench_bpf_loop;
extern const struct bench bench_strncmp_no_helper;
extern const struct bench bench_strncmp_helper;
static const struct bench *benchs[] = {
&bench_count_global,
@@ -441,6 +429,8 @@ static const struct bench *benchs[] = {
&bench_hashmap_without_bloom,
&bench_hashmap_with_bloom,
&bench_bpf_loop,
&bench_strncmp_no_helper,
&bench_strncmp_helper,
};
static void setup_benchmark()

View File

@@ -38,8 +38,8 @@ struct bench_res {
struct bench {
const char *name;
void (*validate)();
void (*setup)();
void (*validate)(void);
void (*setup)(void);
void *(*producer_thread)(void *ctx);
void *(*consumer_thread)(void *ctx);
void (*measure)(struct bench_res* res);
@@ -54,7 +54,7 @@ struct counter {
extern struct env env;
extern const struct bench *bench;
void setup_libbpf();
void setup_libbpf(void);
void hits_drops_report_progress(int iter, struct bench_res *res, long delta_ns);
void hits_drops_report_final(struct bench_res res[], int res_cnt);
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);
void ops_report_progress(int iter, struct bench_res *res, long delta_ns);
void ops_report_final(struct bench_res res[], int res_cnt);
static inline __u64 get_time_ns() {
static inline __u64 get_time_ns(void)
{
struct timespec t;
clock_gettime(CLOCK_MONOTONIC, &t);

View File

@@ -36,7 +36,7 @@ static struct count_local_ctx {
struct counter *hits;
} count_local_ctx;
static void count_local_setup()
static void count_local_setup(void)
{
struct count_local_ctx *ctx = &count_local_ctx;

View File

@@ -11,7 +11,7 @@ static struct ctx {
int fd;
} ctx;
static void validate()
static void validate(void)
{
if (env.producer_cnt != 1) {
fprintf(stderr, "benchmark doesn't support multi-producer!\n");
@@ -43,7 +43,7 @@ static void measure(struct bench_res *res)
res->hits = atomic_swap(&ctx.hits.value, 0);
}
static void setup_ctx()
static void setup_ctx(void)
{
setup_libbpf();
@@ -71,36 +71,36 @@ static void attach_bpf(struct bpf_program *prog)
}
}
static void setup_base()
static void setup_base(void)
{
setup_ctx();
}
static void setup_kprobe()
static void setup_kprobe(void)
{
setup_ctx();
attach_bpf(ctx.skel->progs.prog1);
}
static void setup_kretprobe()
static void setup_kretprobe(void)
{
setup_ctx();
attach_bpf(ctx.skel->progs.prog2);
}
static void setup_rawtp()
static void setup_rawtp(void)
{
setup_ctx();
attach_bpf(ctx.skel->progs.prog3);
}
static void setup_fentry()
static void setup_fentry(void)
{
setup_ctx();
attach_bpf(ctx.skel->progs.prog4);
}
static void setup_fexit()
static void setup_fexit(void)
{
setup_ctx();
attach_bpf(ctx.skel->progs.prog5);

View File

@@ -88,12 +88,12 @@ const struct argp bench_ringbufs_argp = {
static struct counter buf_hits;
static inline void bufs_trigger_batch()
static inline void bufs_trigger_batch(void)
{
(void)syscall(__NR_getpgid);
}
static void bufs_validate()
static void bufs_validate(void)
{
if (env.consumer_cnt != 1) {
fprintf(stderr, "rb-libbpf benchmark doesn't support multi-consumer!\n");
@@ -132,7 +132,7 @@ static void ringbuf_libbpf_measure(struct bench_res *res)
res->drops = atomic_swap(&ctx->skel->bss->dropped, 0);
}
static struct ringbuf_bench *ringbuf_setup_skeleton()
static struct ringbuf_bench *ringbuf_setup_skeleton(void)
{
struct ringbuf_bench *skel;
@@ -167,7 +167,7 @@ static int buf_process_sample(void *ctx, void *data, size_t len)
return 0;
}
static void ringbuf_libbpf_setup()
static void ringbuf_libbpf_setup(void)
{
struct ringbuf_libbpf_ctx *ctx = &ringbuf_libbpf_ctx;
struct bpf_link *link;
@@ -223,7 +223,7 @@ static void ringbuf_custom_measure(struct bench_res *res)
res->drops = atomic_swap(&ctx->skel->bss->dropped, 0);
}
static void ringbuf_custom_setup()
static void ringbuf_custom_setup(void)
{
struct ringbuf_custom_ctx *ctx = &ringbuf_custom_ctx;
const size_t page_size = getpagesize();
@@ -352,7 +352,7 @@ static void perfbuf_measure(struct bench_res *res)
res->drops = atomic_swap(&ctx->skel->bss->dropped, 0);
}
static struct perfbuf_bench *perfbuf_setup_skeleton()
static struct perfbuf_bench *perfbuf_setup_skeleton(void)
{
struct perfbuf_bench *skel;
@@ -390,7 +390,7 @@ perfbuf_process_sample_raw(void *input_ctx, int cpu,
return LIBBPF_PERF_EVENT_CONT;
}
static void perfbuf_libbpf_setup()
static void perfbuf_libbpf_setup(void)
{
struct perfbuf_libbpf_ctx *ctx = &perfbuf_libbpf_ctx;
struct perf_event_attr attr;

View File

@@ -0,0 +1,161 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (C) 2021. Huawei Technologies Co., Ltd */
#include <argp.h>
#include "bench.h"
#include "strncmp_bench.skel.h"
static struct strncmp_ctx {
struct strncmp_bench *skel;
} ctx;
static struct strncmp_args {
u32 cmp_str_len;
} args = {
.cmp_str_len = 32,
};
enum {
ARG_CMP_STR_LEN = 5000,
};
static const struct argp_option opts[] = {
{ "cmp-str-len", ARG_CMP_STR_LEN, "CMP_STR_LEN", 0,
"Set the length of compared string" },
{},
};
static error_t strncmp_parse_arg(int key, char *arg, struct argp_state *state)
{
switch (key) {
case ARG_CMP_STR_LEN:
args.cmp_str_len = strtoul(arg, NULL, 10);
if (!args.cmp_str_len ||
args.cmp_str_len >= sizeof(ctx.skel->bss->str)) {
fprintf(stderr, "Invalid cmp str len (limit %zu)\n",
sizeof(ctx.skel->bss->str));
argp_usage(state);
}
break;
default:
return ARGP_ERR_UNKNOWN;
}
return 0;
}
const struct argp bench_strncmp_argp = {
.options = opts,
.parser = strncmp_parse_arg,
};
static void strncmp_validate(void)
{
if (env.consumer_cnt != 1) {
fprintf(stderr, "strncmp benchmark doesn't support multi-consumer!\n");
exit(1);
}
}
static void strncmp_setup(void)
{
int err;
char *target;
size_t i, sz;
sz = sizeof(ctx.skel->rodata->target);
if (!sz || sz < sizeof(ctx.skel->bss->str)) {
fprintf(stderr, "invalid string size (target %zu, src %zu)\n",
sz, sizeof(ctx.skel->bss->str));
exit(1);
}
setup_libbpf();
ctx.skel = strncmp_bench__open();
if (!ctx.skel) {
fprintf(stderr, "failed to open skeleton\n");
exit(1);
}
srandom(time(NULL));
target = ctx.skel->rodata->target;
for (i = 0; i < sz - 1; i++)
target[i] = '1' + random() % 9;
target[sz - 1] = '\0';
ctx.skel->rodata->cmp_str_len = args.cmp_str_len;
memcpy(ctx.skel->bss->str, target, args.cmp_str_len);
ctx.skel->bss->str[args.cmp_str_len] = '\0';
/* Make bss->str < rodata->target */
ctx.skel->bss->str[args.cmp_str_len - 1] -= 1;
err = strncmp_bench__load(ctx.skel);
if (err) {
fprintf(stderr, "failed to load skeleton\n");
strncmp_bench__destroy(ctx.skel);
exit(1);
}
}
static void strncmp_attach_prog(struct bpf_program *prog)
{
struct bpf_link *link;
link = bpf_program__attach(prog);
if (!link) {
fprintf(stderr, "failed to attach program!\n");
exit(1);
}
}
static void strncmp_no_helper_setup(void)
{
strncmp_setup();
strncmp_attach_prog(ctx.skel->progs.strncmp_no_helper);
}
static void strncmp_helper_setup(void)
{
strncmp_setup();
strncmp_attach_prog(ctx.skel->progs.strncmp_helper);
}
static void *strncmp_producer(void *ctx)
{
while (true)
(void)syscall(__NR_getpgid);
return NULL;
}
static void *strncmp_consumer(void *ctx)
{
return NULL;
}
static void strncmp_measure(struct bench_res *res)
{
res->hits = atomic_swap(&ctx.skel->bss->hits, 0);
}
const struct bench bench_strncmp_no_helper = {
.name = "strncmp-no-helper",
.validate = strncmp_validate,
.setup = strncmp_no_helper_setup,
.producer_thread = strncmp_producer,
.consumer_thread = strncmp_consumer,
.measure = strncmp_measure,
.report_progress = hits_drops_report_progress,
.report_final = hits_drops_report_final,
};
const struct bench bench_strncmp_helper = {
.name = "strncmp-helper",
.validate = strncmp_validate,
.setup = strncmp_helper_setup,
.producer_thread = strncmp_producer,
.consumer_thread = strncmp_consumer,
.measure = strncmp_measure,
.report_progress = hits_drops_report_progress,
.report_final = hits_drops_report_final,
};

View File

@@ -11,7 +11,7 @@ static struct trigger_ctx {
static struct counter base_hits;
static void trigger_validate()
static void trigger_validate(void)
{
if (env.consumer_cnt != 1) {
fprintf(stderr, "benchmark doesn't support multi-consumer!\n");
@@ -45,7 +45,7 @@ static void trigger_measure(struct bench_res *res)
res->hits = atomic_swap(&ctx.skel->bss->hits, 0);
}
static void setup_ctx()
static void setup_ctx(void)
{
setup_libbpf();
@@ -67,37 +67,37 @@ static void attach_bpf(struct bpf_program *prog)
}
}
static void trigger_tp_setup()
static void trigger_tp_setup(void)
{
setup_ctx();
attach_bpf(ctx.skel->progs.bench_trigger_tp);
}
static void trigger_rawtp_setup()
static void trigger_rawtp_setup(void)
{
setup_ctx();
attach_bpf(ctx.skel->progs.bench_trigger_raw_tp);
}
static void trigger_kprobe_setup()
static void trigger_kprobe_setup(void)
{
setup_ctx();
attach_bpf(ctx.skel->progs.bench_trigger_kprobe);
}
static void trigger_fentry_setup()
static void trigger_fentry_setup(void)
{
setup_ctx();
attach_bpf(ctx.skel->progs.bench_trigger_fentry);
}
static void trigger_fentry_sleep_setup()
static void trigger_fentry_sleep_setup(void)
{
setup_ctx();
attach_bpf(ctx.skel->progs.bench_trigger_fentry_sleep);
}
static void trigger_fmodret_setup()
static void trigger_fmodret_setup(void)
{
setup_ctx();
attach_bpf(ctx.skel->progs.bench_trigger_fmodret);
@@ -183,22 +183,22 @@ static void usetup(bool use_retprobe, bool use_nop)
ctx.skel->links.bench_trigger_uprobe = link;
}
static void uprobe_setup_with_nop()
static void uprobe_setup_with_nop(void)
{
usetup(false, true);
}
static void uretprobe_setup_with_nop()
static void uretprobe_setup_with_nop(void)
{
usetup(true, true);
}
static void uprobe_setup_without_nop()
static void uprobe_setup_without_nop(void)
{
usetup(false, false);
}
static void uretprobe_setup_without_nop()
static void uretprobe_setup_without_nop(void)
{
usetup(true, false);
}

View File

@@ -0,0 +1,12 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
source ./benchs/run_common.sh
set -eufo pipefail
for s in 1 8 64 512 2048 4095; do
for b in no-helper helper; do
summarize ${b}-${s} "$($RUN_BENCH --cmp-str-len=$s strncmp-${b})"
done
done

View File

@@ -38,7 +38,9 @@ CONFIG_IPV6_SIT=m
CONFIG_BPF_JIT=y
CONFIG_BPF_LSM=y
CONFIG_SECURITY=y
CONFIG_RC_CORE=y
CONFIG_LIRC=y
CONFIG_BPF_LIRC_MODE2=y
CONFIG_IMA=y
CONFIG_SECURITYFS=y
CONFIG_IMA_WRITE_POLICY=y

View File

@@ -39,13 +39,13 @@ static struct bpf_align_test tests[] = {
},
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
.matches = {
{1, "R1=ctx(id=0,off=0,imm=0)"},
{1, "R10=fp0"},
{1, "R3_w=inv2"},
{2, "R3_w=inv4"},
{3, "R3_w=inv8"},
{4, "R3_w=inv16"},
{5, "R3_w=inv32"},
{0, "R1=ctx(id=0,off=0,imm=0)"},
{0, "R10=fp0"},
{0, "R3_w=inv2"},
{1, "R3_w=inv4"},
{2, "R3_w=inv8"},
{3, "R3_w=inv16"},
{4, "R3_w=inv32"},
},
},
{
@@ -67,19 +67,19 @@ static struct bpf_align_test tests[] = {
},
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
.matches = {
{1, "R1=ctx(id=0,off=0,imm=0)"},
{1, "R10=fp0"},
{1, "R3_w=inv1"},
{2, "R3_w=inv2"},
{3, "R3_w=inv4"},
{4, "R3_w=inv8"},
{5, "R3_w=inv16"},
{6, "R3_w=inv1"},
{7, "R4_w=inv32"},
{8, "R4_w=inv16"},
{9, "R4_w=inv8"},
{10, "R4_w=inv4"},
{11, "R4_w=inv2"},
{0, "R1=ctx(id=0,off=0,imm=0)"},
{0, "R10=fp0"},
{0, "R3_w=inv1"},
{1, "R3_w=inv2"},
{2, "R3_w=inv4"},
{3, "R3_w=inv8"},
{4, "R3_w=inv16"},
{5, "R3_w=inv1"},
{6, "R4_w=inv32"},
{7, "R4_w=inv16"},
{8, "R4_w=inv8"},
{9, "R4_w=inv4"},
{10, "R4_w=inv2"},
},
},
{
@@ -96,14 +96,14 @@ static struct bpf_align_test tests[] = {
},
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
.matches = {
{1, "R1=ctx(id=0,off=0,imm=0)"},
{1, "R10=fp0"},
{1, "R3_w=inv4"},
{2, "R3_w=inv8"},
{3, "R3_w=inv10"},
{4, "R4_w=inv8"},
{5, "R4_w=inv12"},
{6, "R4_w=inv14"},
{0, "R1=ctx(id=0,off=0,imm=0)"},
{0, "R10=fp0"},
{0, "R3_w=inv4"},
{1, "R3_w=inv8"},
{2, "R3_w=inv10"},
{3, "R4_w=inv8"},
{4, "R4_w=inv12"},
{5, "R4_w=inv14"},
},
},
{
@@ -118,12 +118,12 @@ static struct bpf_align_test tests[] = {
},
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
.matches = {
{1, "R1=ctx(id=0,off=0,imm=0)"},
{1, "R10=fp0"},
{0, "R1=ctx(id=0,off=0,imm=0)"},
{0, "R10=fp0"},
{0, "R3_w=inv7"},
{1, "R3_w=inv7"},
{2, "R3_w=inv7"},
{3, "R3_w=inv14"},
{4, "R3_w=inv56"},
{2, "R3_w=inv14"},
{3, "R3_w=inv56"},
},
},
@@ -161,19 +161,19 @@ static struct bpf_align_test tests[] = {
},
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
.matches = {
{7, "R0_w=pkt(id=0,off=8,r=8,imm=0)"},
{7, "R3_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},
{8, "R3_w=inv(id=0,umax_value=510,var_off=(0x0; 0x1fe))"},
{9, "R3_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
{10, "R3_w=inv(id=0,umax_value=2040,var_off=(0x0; 0x7f8))"},
{11, "R3_w=inv(id=0,umax_value=4080,var_off=(0x0; 0xff0))"},
{18, "R3=pkt_end(id=0,off=0,imm=0)"},
{18, "R4_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},
{19, "R4_w=inv(id=0,umax_value=8160,var_off=(0x0; 0x1fe0))"},
{20, "R4_w=inv(id=0,umax_value=4080,var_off=(0x0; 0xff0))"},
{21, "R4_w=inv(id=0,umax_value=2040,var_off=(0x0; 0x7f8))"},
{22, "R4_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
{23, "R4_w=inv(id=0,umax_value=510,var_off=(0x0; 0x1fe))"},
{6, "R0_w=pkt(id=0,off=8,r=8,imm=0)"},
{6, "R3_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},
{7, "R3_w=inv(id=0,umax_value=510,var_off=(0x0; 0x1fe))"},
{8, "R3_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
{9, "R3_w=inv(id=0,umax_value=2040,var_off=(0x0; 0x7f8))"},
{10, "R3_w=inv(id=0,umax_value=4080,var_off=(0x0; 0xff0))"},
{12, "R3_w=pkt_end(id=0,off=0,imm=0)"},
{17, "R4_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},
{18, "R4_w=inv(id=0,umax_value=8160,var_off=(0x0; 0x1fe0))"},
{19, "R4_w=inv(id=0,umax_value=4080,var_off=(0x0; 0xff0))"},
{20, "R4_w=inv(id=0,umax_value=2040,var_off=(0x0; 0x7f8))"},
{21, "R4_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
{22, "R4_w=inv(id=0,umax_value=510,var_off=(0x0; 0x1fe))"},
},
},
{
@@ -194,16 +194,16 @@ static struct bpf_align_test tests[] = {
},
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
.matches = {
{7, "R3_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},
{8, "R4_w=inv(id=1,umax_value=255,var_off=(0x0; 0xff))"},
{9, "R4_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},
{10, "R4_w=inv(id=1,umax_value=255,var_off=(0x0; 0xff))"},
{11, "R4_w=inv(id=0,umax_value=510,var_off=(0x0; 0x1fe))"},
{12, "R4_w=inv(id=1,umax_value=255,var_off=(0x0; 0xff))"},
{13, "R4_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
{14, "R4_w=inv(id=1,umax_value=255,var_off=(0x0; 0xff))"},
{15, "R4_w=inv(id=0,umax_value=2040,var_off=(0x0; 0x7f8))"},
{16, "R4_w=inv(id=0,umax_value=4080,var_off=(0x0; 0xff0))"},
{6, "R3_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},
{7, "R4_w=inv(id=1,umax_value=255,var_off=(0x0; 0xff))"},
{8, "R4_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},
{9, "R4_w=inv(id=1,umax_value=255,var_off=(0x0; 0xff))"},
{10, "R4_w=inv(id=0,umax_value=510,var_off=(0x0; 0x1fe))"},
{11, "R4_w=inv(id=1,umax_value=255,var_off=(0x0; 0xff))"},
{12, "R4_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
{13, "R4_w=inv(id=1,umax_value=255,var_off=(0x0; 0xff))"},
{14, "R4_w=inv(id=0,umax_value=2040,var_off=(0x0; 0x7f8))"},
{15, "R4_w=inv(id=0,umax_value=4080,var_off=(0x0; 0xff0))"},
},
},
{
@@ -234,14 +234,14 @@ static struct bpf_align_test tests[] = {
},
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
.matches = {
{4, "R5_w=pkt(id=0,off=0,r=0,imm=0)"},
{5, "R5_w=pkt(id=0,off=14,r=0,imm=0)"},
{6, "R4_w=pkt(id=0,off=14,r=0,imm=0)"},
{10, "R2=pkt(id=0,off=0,r=18,imm=0)"},
{2, "R5_w=pkt(id=0,off=0,r=0,imm=0)"},
{4, "R5_w=pkt(id=0,off=14,r=0,imm=0)"},
{5, "R4_w=pkt(id=0,off=14,r=0,imm=0)"},
{9, "R2=pkt(id=0,off=0,r=18,imm=0)"},
{10, "R5=pkt(id=0,off=14,r=18,imm=0)"},
{10, "R4_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},
{13, "R4_w=inv(id=0,umax_value=65535,var_off=(0x0; 0xffff))"},
{14, "R4_w=inv(id=0,umax_value=65535,var_off=(0x0; 0xffff))"},
{15, "R4_w=inv(id=0,umax_value=65535,var_off=(0x0; 0xffff))"},
},
},
{
@@ -296,8 +296,8 @@ static struct bpf_align_test tests[] = {
/* Calculated offset in R6 has unknown value, but known
* alignment of 4.
*/
{8, "R2_w=pkt(id=0,off=0,r=8,imm=0)"},
{8, "R6_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
{6, "R2_w=pkt(id=0,off=0,r=8,imm=0)"},
{7, "R6_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
/* Offset is added to packet pointer R5, resulting in
* known fixed offset, and variable offset from R6.
*/
@@ -313,11 +313,11 @@ static struct bpf_align_test tests[] = {
/* Variable offset is added to R5 packet pointer,
* resulting in auxiliary alignment of 4.
*/
{18, "R5_w=pkt(id=2,off=0,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
{17, "R5_w=pkt(id=2,off=0,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
/* Constant offset is added to R5, resulting in
* reg->off of 14.
*/
{19, "R5_w=pkt(id=2,off=14,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
{18, "R5_w=pkt(id=2,off=14,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
/* At the time the word size load is performed from R5,
* its total fixed offset is NET_IP_ALIGN + reg->off
* (14) which is 16. Then the variable offset is 4-byte
@@ -329,18 +329,18 @@ static struct bpf_align_test tests[] = {
/* Constant offset is added to R5 packet pointer,
* resulting in reg->off value of 14.
*/
{26, "R5_w=pkt(id=0,off=14,r=8"},
{25, "R5_w=pkt(id=0,off=14,r=8"},
/* Variable offset is added to R5, resulting in a
* variable offset of (4n).
*/
{27, "R5_w=pkt(id=3,off=14,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
{26, "R5_w=pkt(id=3,off=14,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
/* Constant is added to R5 again, setting reg->off to 18. */
{28, "R5_w=pkt(id=3,off=18,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
{27, "R5_w=pkt(id=3,off=18,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
/* And once more we add a variable; resulting var_off
* is still (4n), fixed offset is not changed.
* Also, we create a new reg->id.
*/
{29, "R5_w=pkt(id=4,off=18,r=0,umax_value=2040,var_off=(0x0; 0x7fc)"},
{28, "R5_w=pkt(id=4,off=18,r=0,umax_value=2040,var_off=(0x0; 0x7fc)"},
/* At the time the word size load is performed from R5,
* its total fixed offset is NET_IP_ALIGN + reg->off (18)
* which is 20. Then the variable offset is (4n), so
@@ -386,13 +386,13 @@ static struct bpf_align_test tests[] = {
/* Calculated offset in R6 has unknown value, but known
* alignment of 4.
*/
{8, "R2_w=pkt(id=0,off=0,r=8,imm=0)"},
{8, "R6_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
{6, "R2_w=pkt(id=0,off=0,r=8,imm=0)"},
{7, "R6_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
/* Adding 14 makes R6 be (4n+2) */
{9, "R6_w=inv(id=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc))"},
{8, "R6_w=inv(id=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc))"},
/* Packet pointer has (4n+2) offset */
{11, "R5_w=pkt(id=1,off=0,r=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc)"},
{13, "R4=pkt(id=1,off=4,r=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc)"},
{12, "R4=pkt(id=1,off=4,r=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc)"},
/* At the time the word size load is performed from R5,
* its total fixed offset is NET_IP_ALIGN + reg->off (0)
* which is 2. Then the variable offset is (4n+2), so
@@ -403,12 +403,12 @@ static struct bpf_align_test tests[] = {
/* Newly read value in R6 was shifted left by 2, so has
* known alignment of 4.
*/
{18, "R6_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
{17, "R6_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
/* Added (4n) to packet pointer's (4n+2) var_off, giving
* another (4n+2).
*/
{19, "R5_w=pkt(id=2,off=0,r=0,umin_value=14,umax_value=2054,var_off=(0x2; 0xffc)"},
{21, "R4=pkt(id=2,off=4,r=0,umin_value=14,umax_value=2054,var_off=(0x2; 0xffc)"},
{20, "R4=pkt(id=2,off=4,r=0,umin_value=14,umax_value=2054,var_off=(0x2; 0xffc)"},
/* At the time the word size load is performed from R5,
* its total fixed offset is NET_IP_ALIGN + reg->off (0)
* which is 2. Then the variable offset is (4n+2), so
@@ -448,18 +448,18 @@ static struct bpf_align_test tests[] = {
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
.result = REJECT,
.matches = {
{4, "R5_w=pkt_end(id=0,off=0,imm=0)"},
{3, "R5_w=pkt_end(id=0,off=0,imm=0)"},
/* (ptr - ptr) << 2 == unknown, (4n) */
{6, "R5_w=inv(id=0,smax_value=9223372036854775804,umax_value=18446744073709551612,var_off=(0x0; 0xfffffffffffffffc)"},
{5, "R5_w=inv(id=0,smax_value=9223372036854775804,umax_value=18446744073709551612,var_off=(0x0; 0xfffffffffffffffc)"},
/* (4n) + 14 == (4n+2). We blow our bounds, because
* the add could overflow.
*/
{7, "R5_w=inv(id=0,smin_value=-9223372036854775806,smax_value=9223372036854775806,umin_value=2,umax_value=18446744073709551614,var_off=(0x2; 0xfffffffffffffffc)"},
{6, "R5_w=inv(id=0,smin_value=-9223372036854775806,smax_value=9223372036854775806,umin_value=2,umax_value=18446744073709551614,var_off=(0x2; 0xfffffffffffffffc)"},
/* Checked s>=0 */
{9, "R5=inv(id=0,umin_value=2,umax_value=9223372036854775806,var_off=(0x2; 0x7ffffffffffffffc)"},
/* packet pointer + nonnegative (4n+2) */
{11, "R6_w=pkt(id=1,off=0,r=0,umin_value=2,umax_value=9223372036854775806,var_off=(0x2; 0x7ffffffffffffffc)"},
{13, "R4_w=pkt(id=1,off=4,r=0,umin_value=2,umax_value=9223372036854775806,var_off=(0x2; 0x7ffffffffffffffc)"},
{12, "R4_w=pkt(id=1,off=4,r=0,umin_value=2,umax_value=9223372036854775806,var_off=(0x2; 0x7ffffffffffffffc)"},
/* NET_IP_ALIGN + (4n+2) == (4n), alignment is fine.
* We checked the bounds, but it might have been able
* to overflow if the packet pointer started in the
@@ -502,14 +502,14 @@ static struct bpf_align_test tests[] = {
/* Calculated offset in R6 has unknown value, but known
* alignment of 4.
*/
{7, "R2_w=pkt(id=0,off=0,r=8,imm=0)"},
{9, "R6_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
{6, "R2_w=pkt(id=0,off=0,r=8,imm=0)"},
{8, "R6_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
/* Adding 14 makes R6 be (4n+2) */
{10, "R6_w=inv(id=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc))"},
{9, "R6_w=inv(id=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc))"},
/* New unknown value in R7 is (4n) */
{11, "R7_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
{10, "R7_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
/* Subtracting it from R6 blows our unsigned bounds */
{12, "R6=inv(id=0,smin_value=-1006,smax_value=1034,umin_value=2,umax_value=18446744073709551614,var_off=(0x2; 0xfffffffffffffffc)"},
{11, "R6=inv(id=0,smin_value=-1006,smax_value=1034,umin_value=2,umax_value=18446744073709551614,var_off=(0x2; 0xfffffffffffffffc)"},
/* Checked s>= 0 */
{14, "R6=inv(id=0,umin_value=2,umax_value=1034,var_off=(0x2; 0x7fc))"},
/* At the time the word size load is performed from R5,
@@ -556,14 +556,14 @@ static struct bpf_align_test tests[] = {
/* Calculated offset in R6 has unknown value, but known
* alignment of 4.
*/
{7, "R2_w=pkt(id=0,off=0,r=8,imm=0)"},
{10, "R6_w=inv(id=0,umax_value=60,var_off=(0x0; 0x3c))"},
{6, "R2_w=pkt(id=0,off=0,r=8,imm=0)"},
{9, "R6_w=inv(id=0,umax_value=60,var_off=(0x0; 0x3c))"},
/* Adding 14 makes R6 be (4n+2) */
{11, "R6_w=inv(id=0,umin_value=14,umax_value=74,var_off=(0x2; 0x7c))"},
{10, "R6_w=inv(id=0,umin_value=14,umax_value=74,var_off=(0x2; 0x7c))"},
/* Subtracting from packet pointer overflows ubounds */
{13, "R5_w=pkt(id=2,off=0,r=8,umin_value=18446744073709551542,umax_value=18446744073709551602,var_off=(0xffffffffffffff82; 0x7c)"},
/* New unknown value in R7 is (4n), >= 76 */
{15, "R7_w=inv(id=0,umin_value=76,umax_value=1096,var_off=(0x0; 0x7fc))"},
{14, "R7_w=inv(id=0,umin_value=76,umax_value=1096,var_off=(0x0; 0x7fc))"},
/* Adding it to packet pointer gives nice bounds again */
{16, "R5_w=pkt(id=3,off=0,r=0,umin_value=2,umax_value=1082,var_off=(0x2; 0xfffffffc)"},
/* 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)
line_ptr = strtok(bpf_vlog_copy, "\n");
for (i = 0; i < MAX_MATCHES; i++) {
struct bpf_reg_match m = test->matches[i];
int tmp;
if (!m.match)
break;
while (line_ptr) {
cur_line = -1;
sscanf(line_ptr, "%u: ", &cur_line);
if (cur_line == -1)
sscanf(line_ptr, "from %u to %u: ", &tmp, &cur_line);
if (cur_line == m.line)
break;
line_ptr = strtok(NULL, "\n");
@@ -642,7 +645,19 @@ static int do_test_single(struct bpf_align_test *test)
printf("%s", bpf_vlog);
break;
}
/* Check the next line as well in case the previous line
* did not have a corresponding bpf insn. Example:
* func#0 @0
* 0: R1=ctx(id=0,off=0,imm=0) R10=fp0
* 0: (b7) r3 = 2 ; R3_w=inv2
*/
if (!strstr(line_ptr, m.match)) {
cur_line = -1;
line_ptr = strtok(NULL, "\n");
sscanf(line_ptr, "%u: ", &cur_line);
}
if (cur_line != m.line || !line_ptr ||
!strstr(line_ptr, m.match)) {
printf("Failed to find match %u: %s\n",
m.line, m.match);
ret = 1;

View File

@@ -65,8 +65,8 @@ void serial_test_bpf_obj_id(void)
if (CHECK_FAIL(err))
goto done;
prog = bpf_object__find_program_by_title(objs[i],
"raw_tp/sys_enter");
prog = bpf_object__find_program_by_name(objs[i],
"test_obj_id");
if (CHECK_FAIL(!prog))
goto done;
links[i] = bpf_program__attach(prog);

View File

@@ -217,7 +217,7 @@ static bool found;
static int libbpf_debug_print(enum libbpf_print_level level,
const char *format, va_list args)
{
const char *log_buf;
const char *prog_name, *log_buf;
if (level != LIBBPF_WARN ||
!strstr(format, "-- BEGIN PROG LOAD LOG --")) {
@@ -225,15 +225,14 @@ static int libbpf_debug_print(enum libbpf_print_level level,
return 0;
}
/* skip prog_name */
va_arg(args, char *);
prog_name = va_arg(args, char *);
log_buf = va_arg(args, char *);
if (!log_buf)
goto out;
if (err_str && strstr(log_buf, err_str) != NULL)
found = true;
out:
printf(format, log_buf);
printf(format, prog_name, log_buf);
return 0;
}

View File

@@ -22,7 +22,6 @@
#include <bpf/libbpf.h>
#include <bpf/btf.h>
#include "bpf_rlimit.h"
#include "bpf_util.h"
#include "../test_btf.h"
#include "test_progs.h"

View File

@@ -67,9 +67,9 @@ static int run_test(int cgroup_fd, int server_fd, int family, int type)
goto close_bpf_object;
}
prog = bpf_object__find_program_by_title(obj, v4 ?
"cgroup/connect4" :
"cgroup/connect6");
prog = bpf_object__find_program_by_name(obj, v4 ?
"connect4" :
"connect6");
if (CHECK(!prog, "find_prog", "connect prog not found\n")) {
err = -EIO;
goto close_bpf_object;
@@ -83,9 +83,9 @@ static int run_test(int cgroup_fd, int server_fd, int family, int type)
goto close_bpf_object;
}
prog = bpf_object__find_program_by_title(obj, v4 ?
"cgroup/getpeername4" :
"cgroup/getpeername6");
prog = bpf_object__find_program_by_name(obj, v4 ?
"getpeername4" :
"getpeername6");
if (CHECK(!prog, "find_prog", "getpeername prog not found\n")) {
err = -EIO;
goto close_bpf_object;
@@ -99,9 +99,9 @@ static int run_test(int cgroup_fd, int server_fd, int family, int type)
goto close_bpf_object;
}
prog = bpf_object__find_program_by_title(obj, v4 ?
"cgroup/getsockname4" :
"cgroup/getsockname6");
prog = bpf_object__find_program_by_name(obj, v4 ?
"getsockname4" :
"getsockname6");
if (CHECK(!prog, "find_prog", "getsockname prog not found\n")) {
err = -EIO;
goto close_bpf_object;

View File

@@ -10,7 +10,7 @@ static int duration = 0;
#define STRUCT_TO_CHAR_PTR(struct_name) (const char *)&(struct struct_name)
#define MODULES_CASE(name, sec_name, tp_name) { \
#define MODULES_CASE(name, pg_name, tp_name) { \
.case_name = name, \
.bpf_obj_file = "test_core_reloc_module.o", \
.btf_src_file = NULL, /* find in kernel module BTFs */ \
@@ -28,7 +28,7 @@ static int duration = 0;
.comm_len = sizeof("test_progs"), \
}, \
.output_len = sizeof(struct core_reloc_module_output), \
.prog_sec_name = sec_name, \
.prog_name = pg_name, \
.raw_tp_name = tp_name, \
.trigger = __trigger_module_test_read, \
.needs_testmod = true, \
@@ -43,7 +43,9 @@ static int duration = 0;
#define FLAVORS_CASE_COMMON(name) \
.case_name = #name, \
.bpf_obj_file = "test_core_reloc_flavors.o", \
.btf_src_file = "btf__core_reloc_" #name ".o" \
.btf_src_file = "btf__core_reloc_" #name ".o", \
.raw_tp_name = "sys_enter", \
.prog_name = "test_core_flavors" \
#define FLAVORS_CASE(name) { \
FLAVORS_CASE_COMMON(name), \
@@ -66,7 +68,9 @@ static int duration = 0;
#define NESTING_CASE_COMMON(name) \
.case_name = #name, \
.bpf_obj_file = "test_core_reloc_nesting.o", \
.btf_src_file = "btf__core_reloc_" #name ".o"
.btf_src_file = "btf__core_reloc_" #name ".o", \
.raw_tp_name = "sys_enter", \
.prog_name = "test_core_nesting" \
#define NESTING_CASE(name) { \
NESTING_CASE_COMMON(name), \
@@ -91,7 +95,9 @@ static int duration = 0;
#define ARRAYS_CASE_COMMON(name) \
.case_name = #name, \
.bpf_obj_file = "test_core_reloc_arrays.o", \
.btf_src_file = "btf__core_reloc_" #name ".o"
.btf_src_file = "btf__core_reloc_" #name ".o", \
.raw_tp_name = "sys_enter", \
.prog_name = "test_core_arrays" \
#define ARRAYS_CASE(name) { \
ARRAYS_CASE_COMMON(name), \
@@ -123,7 +129,9 @@ static int duration = 0;
#define PRIMITIVES_CASE_COMMON(name) \
.case_name = #name, \
.bpf_obj_file = "test_core_reloc_primitives.o", \
.btf_src_file = "btf__core_reloc_" #name ".o"
.btf_src_file = "btf__core_reloc_" #name ".o", \
.raw_tp_name = "sys_enter", \
.prog_name = "test_core_primitives" \
#define PRIMITIVES_CASE(name) { \
PRIMITIVES_CASE_COMMON(name), \
@@ -158,6 +166,8 @@ static int duration = 0;
.e = 5, .f = 6, .g = 7, .h = 8, \
}, \
.output_len = sizeof(struct core_reloc_mods_output), \
.raw_tp_name = "sys_enter", \
.prog_name = "test_core_mods", \
}
#define PTR_AS_ARR_CASE(name) { \
@@ -174,6 +184,8 @@ static int duration = 0;
.a = 3, \
}, \
.output_len = sizeof(struct core_reloc_ptr_as_arr), \
.raw_tp_name = "sys_enter", \
.prog_name = "test_core_ptr_as_arr", \
}
#define INTS_DATA(struct_name) STRUCT_TO_CHAR_PTR(struct_name) { \
@@ -190,7 +202,9 @@ static int duration = 0;
#define INTS_CASE_COMMON(name) \
.case_name = #name, \
.bpf_obj_file = "test_core_reloc_ints.o", \
.btf_src_file = "btf__core_reloc_" #name ".o"
.btf_src_file = "btf__core_reloc_" #name ".o", \
.raw_tp_name = "sys_enter", \
.prog_name = "test_core_ints"
#define INTS_CASE(name) { \
INTS_CASE_COMMON(name), \
@@ -208,7 +222,9 @@ static int duration = 0;
#define FIELD_EXISTS_CASE_COMMON(name) \
.case_name = #name, \
.bpf_obj_file = "test_core_reloc_existence.o", \
.btf_src_file = "btf__core_reloc_" #name ".o" \
.btf_src_file = "btf__core_reloc_" #name ".o", \
.raw_tp_name = "sys_enter", \
.prog_name = "test_core_existence"
#define BITFIELDS_CASE_COMMON(objfile, test_name_prefix, name) \
.case_name = test_name_prefix#name, \
@@ -223,6 +239,8 @@ static int duration = 0;
.output = STRUCT_TO_CHAR_PTR(core_reloc_bitfields_output) \
__VA_ARGS__, \
.output_len = sizeof(struct core_reloc_bitfields_output), \
.raw_tp_name = "sys_enter", \
.prog_name = "test_core_bitfields", \
}, { \
BITFIELDS_CASE_COMMON("test_core_reloc_bitfields_direct.o", \
"direct:", name), \
@@ -231,7 +249,7 @@ static int duration = 0;
.output = STRUCT_TO_CHAR_PTR(core_reloc_bitfields_output) \
__VA_ARGS__, \
.output_len = sizeof(struct core_reloc_bitfields_output), \
.prog_sec_name = "tp_btf/sys_enter", \
.prog_name = "test_core_bitfields_direct", \
}
@@ -239,17 +257,21 @@ static int duration = 0;
BITFIELDS_CASE_COMMON("test_core_reloc_bitfields_probed.o", \
"probed:", name), \
.fails = true, \
.raw_tp_name = "sys_enter", \
.prog_name = "test_core_bitfields", \
}, { \
BITFIELDS_CASE_COMMON("test_core_reloc_bitfields_direct.o", \
"direct:", name), \
.prog_sec_name = "tp_btf/sys_enter", \
.fails = true, \
.prog_name = "test_core_bitfields_direct", \
}
#define SIZE_CASE_COMMON(name) \
.case_name = #name, \
.bpf_obj_file = "test_core_reloc_size.o", \
.btf_src_file = "btf__core_reloc_" #name ".o"
.btf_src_file = "btf__core_reloc_" #name ".o", \
.raw_tp_name = "sys_enter", \
.prog_name = "test_core_size"
#define SIZE_OUTPUT_DATA(type) \
STRUCT_TO_CHAR_PTR(core_reloc_size_output) { \
@@ -277,8 +299,10 @@ static int duration = 0;
#define TYPE_BASED_CASE_COMMON(name) \
.case_name = #name, \
.bpf_obj_file = "test_core_reloc_type_based.o", \
.btf_src_file = "btf__core_reloc_" #name ".o" \
.bpf_obj_file = "test_core_reloc_type_based.o", \
.btf_src_file = "btf__core_reloc_" #name ".o", \
.raw_tp_name = "sys_enter", \
.prog_name = "test_core_type_based"
#define TYPE_BASED_CASE(name, ...) { \
TYPE_BASED_CASE_COMMON(name), \
@@ -295,7 +319,9 @@ static int duration = 0;
#define TYPE_ID_CASE_COMMON(name) \
.case_name = #name, \
.bpf_obj_file = "test_core_reloc_type_id.o", \
.btf_src_file = "btf__core_reloc_" #name ".o" \
.btf_src_file = "btf__core_reloc_" #name ".o", \
.raw_tp_name = "sys_enter", \
.prog_name = "test_core_type_id"
#define TYPE_ID_CASE(name, setup_fn) { \
TYPE_ID_CASE_COMMON(name), \
@@ -312,7 +338,9 @@ static int duration = 0;
#define ENUMVAL_CASE_COMMON(name) \
.case_name = #name, \
.bpf_obj_file = "test_core_reloc_enumval.o", \
.btf_src_file = "btf__core_reloc_" #name ".o" \
.btf_src_file = "btf__core_reloc_" #name ".o", \
.raw_tp_name = "sys_enter", \
.prog_name = "test_core_enumval"
#define ENUMVAL_CASE(name, ...) { \
ENUMVAL_CASE_COMMON(name), \
@@ -342,7 +370,7 @@ struct core_reloc_test_case {
bool fails;
bool needs_testmod;
bool relaxed_core_relocs;
const char *prog_sec_name;
const char *prog_name;
const char *raw_tp_name;
setup_test_fn setup;
trigger_test_fn trigger;
@@ -497,11 +525,13 @@ static struct core_reloc_test_case test_cases[] = {
.comm_len = sizeof("test_progs"),
},
.output_len = sizeof(struct core_reloc_kernel_output),
.raw_tp_name = "sys_enter",
.prog_name = "test_core_kernel",
},
/* validate we can find kernel module BTF types for relocs/attach */
MODULES_CASE("module_probed", "raw_tp/bpf_testmod_test_read", "bpf_testmod_test_read"),
MODULES_CASE("module_direct", "tp_btf/bpf_testmod_test_read", NULL),
MODULES_CASE("module_probed", "test_core_module_probed", "bpf_testmod_test_read"),
MODULES_CASE("module_direct", "test_core_module_direct", NULL),
/* validate BPF program can use multiple flavors to match against
* single target BTF type
@@ -580,6 +610,8 @@ static struct core_reloc_test_case test_cases[] = {
.c = 0, /* BUG in clang, should be 3 */
},
.output_len = sizeof(struct core_reloc_misc_output),
.raw_tp_name = "sys_enter",
.prog_name = "test_core_misc",
},
/* validate field existence checks */
@@ -848,14 +880,9 @@ void test_core_reloc(void)
if (!ASSERT_OK_PTR(obj, "obj_open"))
goto cleanup;
probe_name = "raw_tracepoint/sys_enter";
tp_name = "sys_enter";
if (test_case->prog_sec_name) {
probe_name = test_case->prog_sec_name;
tp_name = test_case->raw_tp_name; /* NULL for tp_btf */
}
prog = bpf_object__find_program_by_title(obj, probe_name);
probe_name = test_case->prog_name;
tp_name = test_case->raw_tp_name; /* NULL for tp_btf */
prog = bpf_object__find_program_by_name(obj, probe_name);
if (CHECK(!prog, "find_probe",
"prog '%s' not found\n", probe_name))
goto cleanup;

View File

@@ -101,6 +101,8 @@ static void test_fexit_bpf2bpf_common(const char *obj_file,
for (i = 0; i < prog_cnt; i++) {
struct bpf_link_info link_info;
struct bpf_program *pos;
const char *pos_sec_name;
char *tgt_name;
__s32 btf_id;
@@ -109,7 +111,14 @@ static void test_fexit_bpf2bpf_common(const char *obj_file,
goto close_prog;
btf_id = btf__find_by_name_kind(btf, tgt_name + 1, BTF_KIND_FUNC);
prog[i] = bpf_object__find_program_by_title(obj, prog_name[i]);
prog[i] = NULL;
bpf_object__for_each_program(pos, obj) {
pos_sec_name = bpf_program__section_name(pos);
if (pos_sec_name && !strcmp(pos_sec_name, prog_name[i])) {
prog[i] = pos;
break;
}
}
if (!ASSERT_OK_PTR(prog[i], prog_name[i]))
goto close_prog;
@@ -211,8 +220,8 @@ static void test_func_replace_verify(void)
static int test_second_attach(struct bpf_object *obj)
{
const char *prog_name = "freplace/get_constant";
const char *tgt_name = prog_name + 9; /* cut off freplace/ */
const char *prog_name = "security_new_get_constant";
const char *tgt_name = "get_constant";
const char *tgt_obj_file = "./test_pkt_access.o";
struct bpf_program *prog = NULL;
struct bpf_object *tgt_obj;
@@ -220,7 +229,7 @@ static int test_second_attach(struct bpf_object *obj)
struct bpf_link *link;
int err = 0, tgt_fd;
prog = bpf_object__find_program_by_title(obj, prog_name);
prog = bpf_object__find_program_by_name(obj, prog_name);
if (CHECK(!prog, "find_prog", "prog %s not found\n", prog_name))
return -ENOENT;

View File

@@ -0,0 +1,44 @@
// SPDX-License-Identifier: GPL-2.0
#include <test_progs.h>
#include "get_func_args_test.skel.h"
void test_get_func_args_test(void)
{
struct get_func_args_test *skel = NULL;
__u32 duration = 0, retval;
int err, prog_fd;
skel = get_func_args_test__open_and_load();
if (!ASSERT_OK_PTR(skel, "get_func_args_test__open_and_load"))
return;
err = get_func_args_test__attach(skel);
if (!ASSERT_OK(err, "get_func_args_test__attach"))
goto cleanup;
/* This runs bpf_fentry_test* functions and triggers
* fentry/fexit programs.
*/
prog_fd = bpf_program__fd(skel->progs.test1);
err = bpf_prog_test_run(prog_fd, 1, NULL, 0,
NULL, NULL, &retval, &duration);
ASSERT_OK(err, "test_run");
ASSERT_EQ(retval, 0, "test_run");
/* This runs bpf_modify_return_test function and triggers
* fmod_ret_test and fexit_test programs.
*/
prog_fd = bpf_program__fd(skel->progs.fmod_ret_test);
err = bpf_prog_test_run(prog_fd, 1, NULL, 0,
NULL, NULL, &retval, &duration);
ASSERT_OK(err, "test_run");
ASSERT_EQ(retval, 1234, "test_run");
ASSERT_EQ(skel->bss->test1_result, 1, "test1_result");
ASSERT_EQ(skel->bss->test2_result, 1, "test2_result");
ASSERT_EQ(skel->bss->test3_result, 1, "test3_result");
ASSERT_EQ(skel->bss->test4_result, 1, "test4_result");
cleanup:
get_func_args_test__destroy(skel);
}

View File

@@ -89,7 +89,7 @@ void test_get_stack_raw_tp(void)
{
const char *file = "./test_get_stack_rawtp.o";
const char *file_err = "./test_get_stack_rawtp_err.o";
const char *prog_name = "raw_tracepoint/sys_enter";
const char *prog_name = "bpf_prog1";
int i, err, prog_fd, exp_cnt = MAX_CNT_RAWTP;
struct perf_buffer *pb = NULL;
struct bpf_link *link = NULL;
@@ -107,7 +107,7 @@ void test_get_stack_raw_tp(void)
if (CHECK(err, "prog_load raw tp", "err %d errno %d\n", err, errno))
return;
prog = bpf_object__find_program_by_title(obj, prog_name);
prog = bpf_object__find_program_by_name(obj, prog_name);
if (CHECK(!prog, "find_probe", "prog '%s' not found\n", prog_name))
goto close_prog;

View File

@@ -8,6 +8,7 @@
#include "test_ksyms_btf_null_check.skel.h"
#include "test_ksyms_weak.skel.h"
#include "test_ksyms_weak.lskel.h"
#include "test_ksyms_btf_write_check.skel.h"
static int duration;
@@ -137,6 +138,16 @@ cleanup:
test_ksyms_weak_lskel__destroy(skel);
}
static void test_write_check(void)
{
struct test_ksyms_btf_write_check *skel;
skel = test_ksyms_btf_write_check__open_and_load();
ASSERT_ERR_PTR(skel, "unexpected load of a prog writing to ksym memory\n");
test_ksyms_btf_write_check__destroy(skel);
}
void test_ksyms_btf(void)
{
int percpu_datasec;
@@ -167,4 +178,7 @@ void test_ksyms_btf(void)
if (test__start_subtest("weak_ksyms_lskel"))
test_weak_syms_lskel();
if (test__start_subtest("write_check"))
test_write_check();
}

View File

@@ -0,0 +1,124 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2021 Facebook */
#include <test_progs.h>
#include <bpf/btf.h>
void test_libbpf_probe_prog_types(void)
{
struct btf *btf;
const struct btf_type *t;
const struct btf_enum *e;
int i, n, id;
btf = btf__parse("/sys/kernel/btf/vmlinux", NULL);
if (!ASSERT_OK_PTR(btf, "btf_parse"))
return;
/* find enum bpf_prog_type and enumerate each value */
id = btf__find_by_name_kind(btf, "bpf_prog_type", BTF_KIND_ENUM);
if (!ASSERT_GT(id, 0, "bpf_prog_type_id"))
goto cleanup;
t = btf__type_by_id(btf, id);
if (!ASSERT_OK_PTR(t, "bpf_prog_type_enum"))
goto cleanup;
for (e = btf_enum(t), i = 0, n = btf_vlen(t); i < n; e++, i++) {
const char *prog_type_name = btf__str_by_offset(btf, e->name_off);
enum bpf_prog_type prog_type = (enum bpf_prog_type)e->val;
int res;
if (prog_type == BPF_PROG_TYPE_UNSPEC)
continue;
if (!test__start_subtest(prog_type_name))
continue;
res = libbpf_probe_bpf_prog_type(prog_type, NULL);
ASSERT_EQ(res, 1, prog_type_name);
}
cleanup:
btf__free(btf);
}
void test_libbpf_probe_map_types(void)
{
struct btf *btf;
const struct btf_type *t;
const struct btf_enum *e;
int i, n, id;
btf = btf__parse("/sys/kernel/btf/vmlinux", NULL);
if (!ASSERT_OK_PTR(btf, "btf_parse"))
return;
/* find enum bpf_map_type and enumerate each value */
id = btf__find_by_name_kind(btf, "bpf_map_type", BTF_KIND_ENUM);
if (!ASSERT_GT(id, 0, "bpf_map_type_id"))
goto cleanup;
t = btf__type_by_id(btf, id);
if (!ASSERT_OK_PTR(t, "bpf_map_type_enum"))
goto cleanup;
for (e = btf_enum(t), i = 0, n = btf_vlen(t); i < n; e++, i++) {
const char *map_type_name = btf__str_by_offset(btf, e->name_off);
enum bpf_map_type map_type = (enum bpf_map_type)e->val;
int res;
if (map_type == BPF_MAP_TYPE_UNSPEC)
continue;
if (!test__start_subtest(map_type_name))
continue;
res = libbpf_probe_bpf_map_type(map_type, NULL);
ASSERT_EQ(res, 1, map_type_name);
}
cleanup:
btf__free(btf);
}
void test_libbpf_probe_helpers(void)
{
#define CASE(prog, helper, supp) { \
.prog_type_name = "BPF_PROG_TYPE_" # prog, \
.helper_name = "bpf_" # helper, \
.prog_type = BPF_PROG_TYPE_ ## prog, \
.helper_id = BPF_FUNC_ ## helper, \
.supported = supp, \
}
const struct case_def {
const char *prog_type_name;
const char *helper_name;
enum bpf_prog_type prog_type;
enum bpf_func_id helper_id;
bool supported;
} cases[] = {
CASE(KPROBE, unspec, false),
CASE(KPROBE, map_lookup_elem, true),
CASE(KPROBE, loop, true),
CASE(KPROBE, ktime_get_coarse_ns, false),
CASE(SOCKET_FILTER, ktime_get_coarse_ns, true),
CASE(KPROBE, sys_bpf, false),
CASE(SYSCALL, sys_bpf, true),
};
size_t case_cnt = ARRAY_SIZE(cases), i;
char buf[128];
for (i = 0; i < case_cnt; i++) {
const struct case_def *d = &cases[i];
int res;
snprintf(buf, sizeof(buf), "%s+%s", d->prog_type_name, d->helper_name);
if (!test__start_subtest(buf))
continue;
res = libbpf_probe_bpf_helper(d->prog_type, d->helper_id, NULL);
ASSERT_EQ(res, d->supported, buf);
}
}

View File

@@ -18,7 +18,6 @@
#include <netinet/in.h>
#include <bpf/bpf.h>
#include <bpf/libbpf.h>
#include "bpf_rlimit.h"
#include "bpf_util.h"
#include "test_progs.h"

View File

@@ -30,7 +30,6 @@
#include <bpf/bpf.h>
#include "test_progs.h"
#include "bpf_rlimit.h"
#include "bpf_util.h"
#include "cgroup_helpers.h"
#include "network_helpers.h"

View File

@@ -15,7 +15,6 @@
#include "network_helpers.h"
#include "cgroup_helpers.h"
#include "test_progs.h"
#include "bpf_rlimit.h"
#include "test_sock_fields.skel.h"
enum bpf_linum_array_idx {

View File

@@ -136,7 +136,8 @@ static int start_server(void)
return fd;
}
static int prog_attach(struct bpf_object *obj, int cgroup_fd, const char *title)
static int prog_attach(struct bpf_object *obj, int cgroup_fd, const char *title,
const char *prog_name)
{
enum bpf_attach_type attach_type;
enum bpf_prog_type prog_type;
@@ -145,20 +146,20 @@ static int prog_attach(struct bpf_object *obj, int cgroup_fd, const char *title)
err = libbpf_prog_type_by_name(title, &prog_type, &attach_type);
if (err) {
log_err("Failed to deduct types for %s BPF program", title);
log_err("Failed to deduct types for %s BPF program", prog_name);
return -1;
}
prog = bpf_object__find_program_by_title(obj, title);
prog = bpf_object__find_program_by_name(obj, prog_name);
if (!prog) {
log_err("Failed to find %s BPF program", title);
log_err("Failed to find %s BPF program", prog_name);
return -1;
}
err = bpf_prog_attach(bpf_program__fd(prog), cgroup_fd,
attach_type, 0);
if (err) {
log_err("Failed to attach %s BPF program", title);
log_err("Failed to attach %s BPF program", prog_name);
return -1;
}
@@ -181,11 +182,11 @@ static void run_test(int cgroup_fd)
if (!ASSERT_OK(err, "obj_load"))
goto close_bpf_object;
err = prog_attach(obj, cgroup_fd, "cgroup/getsockopt");
err = prog_attach(obj, cgroup_fd, "cgroup/getsockopt", "_getsockopt");
if (CHECK_FAIL(err))
goto close_bpf_object;
err = prog_attach(obj, cgroup_fd, "cgroup/setsockopt");
err = prog_attach(obj, cgroup_fd, "cgroup/setsockopt", "_setsockopt");
if (CHECK_FAIL(err))
goto close_bpf_object;

View File

@@ -4,7 +4,7 @@
void test_stacktrace_map(void)
{
int control_map_fd, stackid_hmap_fd, stackmap_fd, stack_amap_fd;
const char *prog_name = "tracepoint/sched/sched_switch";
const char *prog_name = "oncpu";
int err, prog_fd, stack_trace_len;
const char *file = "./test_stacktrace_map.o";
__u32 key, val, duration = 0;
@@ -16,7 +16,7 @@ void test_stacktrace_map(void)
if (CHECK(err, "prog_load", "err %d errno %d\n", err, errno))
return;
prog = bpf_object__find_program_by_title(obj, prog_name);
prog = bpf_object__find_program_by_name(obj, prog_name);
if (CHECK(!prog, "find_prog", "prog '%s' not found\n", prog_name))
goto close_prog;

View File

@@ -3,7 +3,7 @@
void test_stacktrace_map_raw_tp(void)
{
const char *prog_name = "tracepoint/sched/sched_switch";
const char *prog_name = "oncpu";
int control_map_fd, stackid_hmap_fd, stackmap_fd;
const char *file = "./test_stacktrace_map.o";
__u32 key, val, duration = 0;
@@ -16,7 +16,7 @@ void test_stacktrace_map_raw_tp(void)
if (CHECK(err, "prog_load raw tp", "err %d errno %d\n", err, errno))
return;
prog = bpf_object__find_program_by_title(obj, prog_name);
prog = bpf_object__find_program_by_name(obj, prog_name);
if (CHECK(!prog, "find_prog", "prog '%s' not found\n", prog_name))
goto close_prog;

View File

@@ -28,10 +28,6 @@ static unsigned int duration;
struct storage {
void *inode;
unsigned int value;
/* Lock ensures that spin locked versions of local stoage operations
* also work, most operations in this tests are still single threaded
*/
struct bpf_spin_lock lock;
};
/* 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)
static bool check_syscall_operations(int map_fd, int obj_fd)
{
struct storage val = { .value = TEST_STORAGE_VALUE, .lock = { 0 } },
lookup_val = { .value = 0, .lock = { 0 } };
struct storage val = { .value = TEST_STORAGE_VALUE },
lookup_val = { .value = 0 };
int err;
/* Looking up an existing element should fail initially */
err = bpf_map_lookup_elem_flags(map_fd, &obj_fd, &lookup_val,
BPF_F_LOCK);
err = bpf_map_lookup_elem_flags(map_fd, &obj_fd, &lookup_val, 0);
if (CHECK(!err || errno != ENOENT, "bpf_map_lookup_elem",
"err:%d errno:%d\n", err, errno))
return false;
/* Create a new element */
err = bpf_map_update_elem(map_fd, &obj_fd, &val,
BPF_NOEXIST | BPF_F_LOCK);
err = bpf_map_update_elem(map_fd, &obj_fd, &val, BPF_NOEXIST);
if (CHECK(err < 0, "bpf_map_update_elem", "err:%d errno:%d\n", err,
errno))
return false;
/* Lookup the newly created element */
err = bpf_map_lookup_elem_flags(map_fd, &obj_fd, &lookup_val,
BPF_F_LOCK);
err = bpf_map_lookup_elem_flags(map_fd, &obj_fd, &lookup_val, 0);
if (CHECK(err < 0, "bpf_map_lookup_elem", "err:%d errno:%d", err,
errno))
return false;
@@ -102,8 +95,7 @@ static bool check_syscall_operations(int map_fd, int obj_fd)
return false;
/* The lookup should fail, now that the element has been deleted */
err = bpf_map_lookup_elem_flags(map_fd, &obj_fd, &lookup_val,
BPF_F_LOCK);
err = bpf_map_lookup_elem_flags(map_fd, &obj_fd, &lookup_val, 0);
if (CHECK(!err || errno != ENOENT, "bpf_map_lookup_elem",
"err:%d errno:%d\n", err, errno))
return false;

View File

@@ -56,11 +56,11 @@ static void setaffinity(void)
void test_test_overhead(void)
{
const char *kprobe_name = "kprobe/__set_task_comm";
const char *kretprobe_name = "kretprobe/__set_task_comm";
const char *raw_tp_name = "raw_tp/task_rename";
const char *fentry_name = "fentry/__set_task_comm";
const char *fexit_name = "fexit/__set_task_comm";
const char *kprobe_name = "prog1";
const char *kretprobe_name = "prog2";
const char *raw_tp_name = "prog3";
const char *fentry_name = "prog4";
const char *fexit_name = "prog5";
const char *kprobe_func = "__set_task_comm";
struct bpf_program *kprobe_prog, *kretprobe_prog, *raw_tp_prog;
struct bpf_program *fentry_prog, *fexit_prog;
@@ -76,23 +76,23 @@ void test_test_overhead(void)
if (!ASSERT_OK_PTR(obj, "obj_open_file"))
return;
kprobe_prog = bpf_object__find_program_by_title(obj, kprobe_name);
kprobe_prog = bpf_object__find_program_by_name(obj, kprobe_name);
if (CHECK(!kprobe_prog, "find_probe",
"prog '%s' not found\n", kprobe_name))
goto cleanup;
kretprobe_prog = bpf_object__find_program_by_title(obj, kretprobe_name);
kretprobe_prog = bpf_object__find_program_by_name(obj, kretprobe_name);
if (CHECK(!kretprobe_prog, "find_probe",
"prog '%s' not found\n", kretprobe_name))
goto cleanup;
raw_tp_prog = bpf_object__find_program_by_title(obj, raw_tp_name);
raw_tp_prog = bpf_object__find_program_by_name(obj, raw_tp_name);
if (CHECK(!raw_tp_prog, "find_probe",
"prog '%s' not found\n", raw_tp_name))
goto cleanup;
fentry_prog = bpf_object__find_program_by_title(obj, fentry_name);
fentry_prog = bpf_object__find_program_by_name(obj, fentry_name);
if (CHECK(!fentry_prog, "find_probe",
"prog '%s' not found\n", fentry_name))
goto cleanup;
fexit_prog = bpf_object__find_program_by_title(obj, fexit_name);
fexit_prog = bpf_object__find_program_by_name(obj, fexit_name);
if (CHECK(!fexit_prog, "find_probe",
"prog '%s' not found\n", fexit_name))
goto cleanup;

View File

@@ -0,0 +1,167 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (C) 2021. Huawei Technologies Co., Ltd */
#include <test_progs.h>
#include "strncmp_test.skel.h"
static int trigger_strncmp(const struct strncmp_test *skel)
{
int cmp;
usleep(1);
cmp = skel->bss->cmp_ret;
if (cmp > 0)
return 1;
if (cmp < 0)
return -1;
return 0;
}
/*
* Compare str and target after making str[i] != target[i].
* When exp is -1, make str[i] < target[i] and delta = -1.
*/
static void strncmp_full_str_cmp(struct strncmp_test *skel, const char *name,
int exp)
{
size_t nr = sizeof(skel->bss->str);
char *str = skel->bss->str;
int delta = exp;
int got;
size_t i;
memcpy(str, skel->rodata->target, nr);
for (i = 0; i < nr - 1; i++) {
str[i] += delta;
got = trigger_strncmp(skel);
ASSERT_EQ(got, exp, name);
str[i] -= delta;
}
}
static void test_strncmp_ret(void)
{
struct strncmp_test *skel;
struct bpf_program *prog;
int err, got;
skel = strncmp_test__open();
if (!ASSERT_OK_PTR(skel, "strncmp_test open"))
return;
bpf_object__for_each_program(prog, skel->obj)
bpf_program__set_autoload(prog, false);
bpf_program__set_autoload(skel->progs.do_strncmp, true);
err = strncmp_test__load(skel);
if (!ASSERT_EQ(err, 0, "strncmp_test load"))
goto out;
err = strncmp_test__attach(skel);
if (!ASSERT_EQ(err, 0, "strncmp_test attach"))
goto out;
skel->bss->target_pid = getpid();
/* Empty str */
skel->bss->str[0] = '\0';
got = trigger_strncmp(skel);
ASSERT_EQ(got, -1, "strncmp: empty str");
/* Same string */
memcpy(skel->bss->str, skel->rodata->target, sizeof(skel->bss->str));
got = trigger_strncmp(skel);
ASSERT_EQ(got, 0, "strncmp: same str");
/* Not-null-termainted string */
memcpy(skel->bss->str, skel->rodata->target, sizeof(skel->bss->str));
skel->bss->str[sizeof(skel->bss->str) - 1] = 'A';
got = trigger_strncmp(skel);
ASSERT_EQ(got, 1, "strncmp: not-null-term str");
strncmp_full_str_cmp(skel, "strncmp: less than", -1);
strncmp_full_str_cmp(skel, "strncmp: greater than", 1);
out:
strncmp_test__destroy(skel);
}
static void test_strncmp_bad_not_const_str_size(void)
{
struct strncmp_test *skel;
struct bpf_program *prog;
int err;
skel = strncmp_test__open();
if (!ASSERT_OK_PTR(skel, "strncmp_test open"))
return;
bpf_object__for_each_program(prog, skel->obj)
bpf_program__set_autoload(prog, false);
bpf_program__set_autoload(skel->progs.strncmp_bad_not_const_str_size,
true);
err = strncmp_test__load(skel);
ASSERT_ERR(err, "strncmp_test load bad_not_const_str_size");
strncmp_test__destroy(skel);
}
static void test_strncmp_bad_writable_target(void)
{
struct strncmp_test *skel;
struct bpf_program *prog;
int err;
skel = strncmp_test__open();
if (!ASSERT_OK_PTR(skel, "strncmp_test open"))
return;
bpf_object__for_each_program(prog, skel->obj)
bpf_program__set_autoload(prog, false);
bpf_program__set_autoload(skel->progs.strncmp_bad_writable_target,
true);
err = strncmp_test__load(skel);
ASSERT_ERR(err, "strncmp_test load bad_writable_target");
strncmp_test__destroy(skel);
}
static void test_strncmp_bad_not_null_term_target(void)
{
struct strncmp_test *skel;
struct bpf_program *prog;
int err;
skel = strncmp_test__open();
if (!ASSERT_OK_PTR(skel, "strncmp_test open"))
return;
bpf_object__for_each_program(prog, skel->obj)
bpf_program__set_autoload(prog, false);
bpf_program__set_autoload(skel->progs.strncmp_bad_not_null_term_target,
true);
err = strncmp_test__load(skel);
ASSERT_ERR(err, "strncmp_test load bad_not_null_term_target");
strncmp_test__destroy(skel);
}
void test_test_strncmp(void)
{
if (test__start_subtest("strncmp_ret"))
test_strncmp_ret();
if (test__start_subtest("strncmp_bad_not_const_str_size"))
test_strncmp_bad_not_const_str_size();
if (test__start_subtest("strncmp_bad_writable_target"))
test_strncmp_bad_writable_target();
if (test__start_subtest("strncmp_bad_not_null_term_target"))
test_strncmp_bad_not_null_term_target();
}

View File

@@ -35,7 +35,7 @@ static struct bpf_link *load(struct bpf_object *obj, const char *name)
struct bpf_program *prog;
int duration = 0;
prog = bpf_object__find_program_by_title(obj, name);
prog = bpf_object__find_program_by_name(obj, name);
if (CHECK(!prog, "find_probe", "prog '%s' not found\n", name))
return ERR_PTR(-EINVAL);
return bpf_program__attach_trace(prog);
@@ -44,8 +44,8 @@ static struct bpf_link *load(struct bpf_object *obj, const char *name)
/* TODO: use different target function to run in concurrent mode */
void serial_test_trampoline_count(void)
{
const char *fentry_name = "fentry/__set_task_comm";
const char *fexit_name = "fexit/__set_task_comm";
const char *fentry_name = "prog1";
const char *fexit_name = "prog2";
const char *object = "test_trampoline_count.o";
struct inst inst[MAX_TRAMP_PROGS] = {};
int err, i = 0, duration = 0;

View File

@@ -0,0 +1,123 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include <errno.h>
char _license[] SEC("license") = "GPL";
__u64 test1_result = 0;
SEC("fentry/bpf_fentry_test1")
int BPF_PROG(test1)
{
__u64 cnt = bpf_get_func_arg_cnt(ctx);
__u64 a = 0, z = 0, ret = 0;
__s64 err;
test1_result = cnt == 1;
/* valid arguments */
err = bpf_get_func_arg(ctx, 0, &a);
/* We need to cast access to traced function argument values with
* proper type cast, because trampoline uses type specific instruction
* to save it, like for 'int a' with 32-bit mov like:
*
* mov %edi,-0x8(%rbp)
*
* so the upper 4 bytes are not zeroed.
*/
test1_result &= err == 0 && ((int) a == 1);
/* not valid argument */
err = bpf_get_func_arg(ctx, 1, &z);
test1_result &= err == -EINVAL;
/* return value fails in fentry */
err = bpf_get_func_ret(ctx, &ret);
test1_result &= err == -EOPNOTSUPP;
return 0;
}
__u64 test2_result = 0;
SEC("fexit/bpf_fentry_test2")
int BPF_PROG(test2)
{
__u64 cnt = bpf_get_func_arg_cnt(ctx);
__u64 a = 0, b = 0, z = 0, ret = 0;
__s64 err;
test2_result = cnt == 2;
/* valid arguments */
err = bpf_get_func_arg(ctx, 0, &a);
test2_result &= err == 0 && (int) a == 2;
err = bpf_get_func_arg(ctx, 1, &b);
test2_result &= err == 0 && b == 3;
/* not valid argument */
err = bpf_get_func_arg(ctx, 2, &z);
test2_result &= err == -EINVAL;
/* return value */
err = bpf_get_func_ret(ctx, &ret);
test2_result &= err == 0 && ret == 5;
return 0;
}
__u64 test3_result = 0;
SEC("fmod_ret/bpf_modify_return_test")
int BPF_PROG(fmod_ret_test, int _a, int *_b, int _ret)
{
__u64 cnt = bpf_get_func_arg_cnt(ctx);
__u64 a = 0, b = 0, z = 0, ret = 0;
__s64 err;
test3_result = cnt == 2;
/* valid arguments */
err = bpf_get_func_arg(ctx, 0, &a);
test3_result &= err == 0 && ((int) a == 1);
err = bpf_get_func_arg(ctx, 1, &b);
test3_result &= err == 0 && ((int *) b == _b);
/* not valid argument */
err = bpf_get_func_arg(ctx, 2, &z);
test3_result &= err == -EINVAL;
/* return value */
err = bpf_get_func_ret(ctx, &ret);
test3_result &= err == 0 && ret == 0;
/* change return value, it's checked in fexit_test program */
return 1234;
}
__u64 test4_result = 0;
SEC("fexit/bpf_modify_return_test")
int BPF_PROG(fexit_test, int _a, int *_b, int _ret)
{
__u64 cnt = bpf_get_func_arg_cnt(ctx);
__u64 a = 0, b = 0, z = 0, ret = 0;
__s64 err;
test4_result = cnt == 2;
/* valid arguments */
err = bpf_get_func_arg(ctx, 0, &a);
test4_result &= err == 0 && ((int) a == 1);
err = bpf_get_func_arg(ctx, 1, &b);
test4_result &= err == 0 && ((int *) b == _b);
/* not valid argument */
err = bpf_get_func_arg(ctx, 2, &z);
test4_result &= err == -EINVAL;
/* return value */
err = bpf_get_func_ret(ctx, &ret);
test4_result &= err == 0 && ret == 1234;
return 0;
}

View File

@@ -20,7 +20,6 @@ int sk_storage_result = -1;
struct local_storage {
struct inode *exec_inode;
__u32 value;
struct bpf_spin_lock lock;
};
struct {
@@ -58,9 +57,7 @@ int BPF_PROG(unlink_hook, struct inode *dir, struct dentry *victim)
bpf_get_current_task_btf(), 0, 0);
if (storage) {
/* Don't let an executable delete itself */
bpf_spin_lock(&storage->lock);
is_self_unlink = storage->exec_inode == victim->d_inode;
bpf_spin_unlock(&storage->lock);
if (is_self_unlink)
return -EPERM;
}
@@ -68,7 +65,7 @@ int BPF_PROG(unlink_hook, struct inode *dir, struct dentry *victim)
return 0;
}
SEC("lsm/inode_rename")
SEC("lsm.s/inode_rename")
int BPF_PROG(inode_rename, struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry,
unsigned int flags)
@@ -89,10 +86,8 @@ int BPF_PROG(inode_rename, struct inode *old_dir, struct dentry *old_dentry,
if (!storage)
return 0;
bpf_spin_lock(&storage->lock);
if (storage->value != DUMMY_STORAGE_VALUE)
inode_storage_result = -1;
bpf_spin_unlock(&storage->lock);
err = bpf_inode_storage_delete(&inode_storage_map, old_dentry->d_inode);
if (!err)
@@ -101,7 +96,7 @@ int BPF_PROG(inode_rename, struct inode *old_dir, struct dentry *old_dentry,
return 0;
}
SEC("lsm/socket_bind")
SEC("lsm.s/socket_bind")
int BPF_PROG(socket_bind, struct socket *sock, struct sockaddr *address,
int addrlen)
{
@@ -117,10 +112,8 @@ int BPF_PROG(socket_bind, struct socket *sock, struct sockaddr *address,
if (!storage)
return 0;
bpf_spin_lock(&storage->lock);
if (storage->value != DUMMY_STORAGE_VALUE)
sk_storage_result = -1;
bpf_spin_unlock(&storage->lock);
err = bpf_sk_storage_delete(&sk_storage_map, sock->sk);
if (!err)
@@ -129,7 +122,7 @@ int BPF_PROG(socket_bind, struct socket *sock, struct sockaddr *address,
return 0;
}
SEC("lsm/socket_post_create")
SEC("lsm.s/socket_post_create")
int BPF_PROG(socket_post_create, struct socket *sock, int family, int type,
int protocol, int kern)
{
@@ -144,9 +137,7 @@ int BPF_PROG(socket_post_create, struct socket *sock, int family, int type,
if (!storage)
return 0;
bpf_spin_lock(&storage->lock);
storage->value = DUMMY_STORAGE_VALUE;
bpf_spin_unlock(&storage->lock);
return 0;
}
@@ -154,7 +145,7 @@ int BPF_PROG(socket_post_create, struct socket *sock, int family, int type,
/* This uses the local storage to remember the inode of the binary that a
* process was originally executing.
*/
SEC("lsm/bprm_committed_creds")
SEC("lsm.s/bprm_committed_creds")
void BPF_PROG(exec, struct linux_binprm *bprm)
{
__u32 pid = bpf_get_current_pid_tgid() >> 32;
@@ -166,18 +157,13 @@ void BPF_PROG(exec, struct linux_binprm *bprm)
storage = bpf_task_storage_get(&task_storage_map,
bpf_get_current_task_btf(), 0,
BPF_LOCAL_STORAGE_GET_F_CREATE);
if (storage) {
bpf_spin_lock(&storage->lock);
if (storage)
storage->exec_inode = bprm->file->f_inode;
bpf_spin_unlock(&storage->lock);
}
storage = bpf_inode_storage_get(&inode_storage_map, bprm->file->f_inode,
0, BPF_LOCAL_STORAGE_GET_F_CREATE);
if (!storage)
return;
bpf_spin_lock(&storage->lock);
storage->value = DUMMY_STORAGE_VALUE;
bpf_spin_unlock(&storage->lock);
}

View File

@@ -0,0 +1,50 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (C) 2021. Huawei Technologies Co., Ltd */
#include <linux/types.h>
#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#define STRNCMP_STR_SZ 4096
/* Will be updated by benchmark before program loading */
const volatile unsigned int cmp_str_len = 1;
const char target[STRNCMP_STR_SZ];
long hits = 0;
char str[STRNCMP_STR_SZ];
char _license[] SEC("license") = "GPL";
static __always_inline int local_strncmp(const char *s1, unsigned int sz,
const char *s2)
{
int ret = 0;
unsigned int i;
for (i = 0; i < sz; i++) {
/* E.g. 0xff > 0x31 */
ret = (unsigned char)s1[i] - (unsigned char)s2[i];
if (ret || !s1[i])
break;
}
return ret;
}
SEC("tp/syscalls/sys_enter_getpgid")
int strncmp_no_helper(void *ctx)
{
if (local_strncmp(str, cmp_str_len + 1, target) < 0)
__sync_add_and_fetch(&hits, 1);
return 0;
}
SEC("tp/syscalls/sys_enter_getpgid")
int strncmp_helper(void *ctx)
{
if (bpf_strncmp(str, cmp_str_len + 1, target) < 0)
__sync_add_and_fetch(&hits, 1);
return 0;
}

View File

@@ -0,0 +1,54 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (C) 2021. Huawei Technologies Co., Ltd */
#include <stdbool.h>
#include <linux/types.h>
#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#define STRNCMP_STR_SZ 8
const char target[STRNCMP_STR_SZ] = "EEEEEEE";
char str[STRNCMP_STR_SZ];
int cmp_ret = 0;
int target_pid = 0;
const char no_str_target[STRNCMP_STR_SZ] = "12345678";
char writable_target[STRNCMP_STR_SZ];
unsigned int no_const_str_size = STRNCMP_STR_SZ;
char _license[] SEC("license") = "GPL";
SEC("tp/syscalls/sys_enter_nanosleep")
int do_strncmp(void *ctx)
{
if ((bpf_get_current_pid_tgid() >> 32) != target_pid)
return 0;
cmp_ret = bpf_strncmp(str, STRNCMP_STR_SZ, target);
return 0;
}
SEC("tp/syscalls/sys_enter_nanosleep")
int strncmp_bad_not_const_str_size(void *ctx)
{
/* The value of string size is not const, so will fail */
cmp_ret = bpf_strncmp(str, no_const_str_size, target);
return 0;
}
SEC("tp/syscalls/sys_enter_nanosleep")
int strncmp_bad_writable_target(void *ctx)
{
/* Compared target is not read-only, so will fail */
cmp_ret = bpf_strncmp(str, STRNCMP_STR_SZ, writable_target);
return 0;
}
SEC("tp/syscalls/sys_enter_nanosleep")
int strncmp_bad_not_null_term_target(void *ctx)
{
/* Compared target is not null-terminated, so will fail */
cmp_ret = bpf_strncmp(str, STRNCMP_STR_SZ, no_str_target);
return 0;
}

View File

@@ -0,0 +1,29 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2021 Google */
#include "vmlinux.h"
#include <bpf/bpf_helpers.h>
extern const int bpf_prog_active __ksym; /* int type global var. */
SEC("raw_tp/sys_enter")
int handler(const void *ctx)
{
int *active;
__u32 cpu;
cpu = bpf_get_smp_processor_id();
active = (int *)bpf_per_cpu_ptr(&bpf_prog_active, cpu);
if (active) {
/* Kernel memory obtained from bpf_{per,this}_cpu_ptr
* is read-only, should _not_ pass verification.
*/
/* WRITE_ONCE */
*(volatile int *)active = -1;
}
return 0;
}
char _license[] SEC("license") = "GPL";

View File

@@ -7,9 +7,15 @@
/* do nothing, just make sure we can link successfully */
static void dump_printf(void *ctx, const char *fmt, va_list args)
{
}
int main(int argc, char *argv[])
{
struct btf_dump_opts opts = { };
struct test_core_extern *skel;
struct btf *btf;
/* libbpf.h */
libbpf_set_print(NULL);
@@ -18,7 +24,8 @@ int main(int argc, char *argv[])
bpf_prog_get_fd_by_id(0);
/* btf.h */
btf__new(NULL, 0);
btf = btf__new(NULL, 0);
btf_dump__new(btf, dump_printf, nullptr, &opts);
/* BPF skeleton */
skel = test_core_extern__open_and_load();

View File

@@ -23,7 +23,6 @@
#include <bpf/libbpf.h>
#include "bpf_util.h"
#include "bpf_rlimit.h"
#include "test_maps.h"
#include "testing_helpers.h"

View File

@@ -4,7 +4,6 @@
#define _GNU_SOURCE
#include "test_progs.h"
#include "cgroup_helpers.h"
#include "bpf_rlimit.h"
#include <argp.h>
#include <pthread.h>
#include <sched.h>
@@ -1342,7 +1341,6 @@ int main(int argc, char **argv)
/* Use libbpf 1.0 API mode */
libbpf_set_strict_mode(LIBBPF_STRICT_ALL);
libbpf_set_print(libbpf_print_fn);
srand(time(NULL));

View File

@@ -41,7 +41,6 @@
# define CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS 1
# endif
#endif
#include "bpf_rlimit.h"
#include "bpf_rand.h"
#include "bpf_util.h"
#include "test_btf.h"
@@ -701,22 +700,18 @@ static int create_sk_storage_map(void)
static int create_map_timer(void)
{
struct bpf_create_map_attr attr = {
.name = "test_map",
.map_type = BPF_MAP_TYPE_ARRAY,
.key_size = 4,
.value_size = 16,
.max_entries = 1,
LIBBPF_OPTS(bpf_map_create_opts, opts,
.btf_key_type_id = 1,
.btf_value_type_id = 5,
};
);
int fd, btf_fd;
btf_fd = load_btf();
if (btf_fd < 0)
return -1;
attr.btf_fd = btf_fd;
fd = bpf_create_map_xattr(&attr);
opts.btf_fd = btf_fd;
fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, "test_map", 4, 16, 1, &opts);
if (fd < 0)
printf("Failed to create map with timer\n");
return fd;
@@ -1399,6 +1394,9 @@ int main(int argc, char **argv)
return EXIT_FAILURE;
}
/* Use libbpf 1.0 API mode */
libbpf_set_strict_mode(LIBBPF_STRICT_ALL);
bpf_semi_rand_init();
return do_test(unpriv, from, to);
}

View File

@@ -0,0 +1,12 @@
{
"btf_ctx_access accept",
.insns = {
BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 8), /* load 2nd argument value (int pointer) */
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
.result = ACCEPT,
.prog_type = BPF_PROG_TYPE_TRACING,
.expected_attach_type = BPF_TRACE_FENTRY,
.kfunc = "bpf_modify_return_test",
},

View File

@@ -32,7 +32,7 @@ ROOTFS_IMAGE="root.img"
OUTPUT_DIR="$HOME/.bpf_selftests"
KCONFIG_URL="https://raw.githubusercontent.com/libbpf/libbpf/master/travis-ci/vmtest/configs/config-latest.${ARCH}"
KCONFIG_API_URL="https://api.github.com/repos/libbpf/libbpf/contents/travis-ci/vmtest/configs/config-latest.${ARCH}"
INDEX_URL="https://raw.githubusercontent.com/libbpf/libbpf/master/travis-ci/vmtest/configs/INDEX"
INDEX_URL="https://raw.githubusercontent.com/libbpf/ci/master/INDEX"
NUM_COMPILE_JOBS="$(nproc)"
LOG_FILE_BASE="$(date +"bpf_selftests.%Y-%m-%d_%H-%M-%S")"
LOG_FILE="${LOG_FILE_BASE}.log"