Merge branch 'bpf-add-cookies-retrieval-for-perf-kprobe-multi-links'
Jiri Olsa says: ==================== bpf: Add cookies retrieval for perf/kprobe multi links hi, this patchset adds support to retrieve cookies from existing tracing links that still did not support it plus changes to bpftool to display them. It's leftover we discussed some time ago [1]. thanks, jirka v2 changes: - added review/ack tags - fixed memory leak [Quentin] - align the uapi fields properly [Yafang Shao] [1] https://lore.kernel.org/bpf/CALOAHbAZ6=A9j3VFCLoAC_WhgQKU7injMf06=cM2sU4Hi4Sx+Q@mail.gmail.com/ Reviewed-by: Quentin Monnet <quentin@isovalent.com> --- ==================== Reviewed-by: Quentin Monnet <quentin@isovalent.com> Link: https://lore.kernel.org/r/20240119110505.400573-1-jolsa@kernel.org Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
commit
b7d1af3791
@ -6563,6 +6563,7 @@ struct bpf_link_info {
|
||||
__u32 count; /* in/out: kprobe_multi function count */
|
||||
__u32 flags;
|
||||
__u64 missed;
|
||||
__aligned_u64 cookies;
|
||||
} kprobe_multi;
|
||||
struct {
|
||||
__aligned_u64 path;
|
||||
@ -6582,6 +6583,7 @@ struct bpf_link_info {
|
||||
__aligned_u64 file_name; /* in/out */
|
||||
__u32 name_len;
|
||||
__u32 offset; /* offset from file_name */
|
||||
__u64 cookie;
|
||||
} uprobe; /* BPF_PERF_EVENT_UPROBE, BPF_PERF_EVENT_URETPROBE */
|
||||
struct {
|
||||
__aligned_u64 func_name; /* in/out */
|
||||
@ -6589,14 +6591,19 @@ struct bpf_link_info {
|
||||
__u32 offset; /* offset from func_name */
|
||||
__u64 addr;
|
||||
__u64 missed;
|
||||
__u64 cookie;
|
||||
} kprobe; /* BPF_PERF_EVENT_KPROBE, BPF_PERF_EVENT_KRETPROBE */
|
||||
struct {
|
||||
__aligned_u64 tp_name; /* in/out */
|
||||
__u32 name_len;
|
||||
__u32 :32;
|
||||
__u64 cookie;
|
||||
} tracepoint; /* BPF_PERF_EVENT_TRACEPOINT */
|
||||
struct {
|
||||
__u64 config;
|
||||
__u32 type;
|
||||
__u32 :32;
|
||||
__u64 cookie;
|
||||
} event; /* BPF_PERF_EVENT_EVENT */
|
||||
};
|
||||
} perf_event;
|
||||
|
@ -3501,6 +3501,7 @@ static int bpf_perf_link_fill_kprobe(const struct perf_event *event,
|
||||
if (!kallsyms_show_value(current_cred()))
|
||||
addr = 0;
|
||||
info->perf_event.kprobe.addr = addr;
|
||||
info->perf_event.kprobe.cookie = event->bpf_cookie;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@ -3526,6 +3527,7 @@ static int bpf_perf_link_fill_uprobe(const struct perf_event *event,
|
||||
else
|
||||
info->perf_event.type = BPF_PERF_EVENT_UPROBE;
|
||||
info->perf_event.uprobe.offset = offset;
|
||||
info->perf_event.uprobe.cookie = event->bpf_cookie;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@ -3553,6 +3555,7 @@ static int bpf_perf_link_fill_tracepoint(const struct perf_event *event,
|
||||
uname = u64_to_user_ptr(info->perf_event.tracepoint.tp_name);
|
||||
ulen = info->perf_event.tracepoint.name_len;
|
||||
info->perf_event.type = BPF_PERF_EVENT_TRACEPOINT;
|
||||
info->perf_event.tracepoint.cookie = event->bpf_cookie;
|
||||
return bpf_perf_link_fill_common(event, uname, ulen, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
@ -3561,6 +3564,7 @@ static int bpf_perf_link_fill_perf_event(const struct perf_event *event,
|
||||
{
|
||||
info->perf_event.event.type = event->attr.type;
|
||||
info->perf_event.event.config = event->attr.config;
|
||||
info->perf_event.event.cookie = event->bpf_cookie;
|
||||
info->perf_event.type = BPF_PERF_EVENT_EVENT;
|
||||
return 0;
|
||||
}
|
||||
|
@ -2679,6 +2679,7 @@ static void bpf_kprobe_multi_link_dealloc(struct bpf_link *link)
|
||||
static int bpf_kprobe_multi_link_fill_link_info(const struct bpf_link *link,
|
||||
struct bpf_link_info *info)
|
||||
{
|
||||
u64 __user *ucookies = u64_to_user_ptr(info->kprobe_multi.cookies);
|
||||
u64 __user *uaddrs = u64_to_user_ptr(info->kprobe_multi.addrs);
|
||||
struct bpf_kprobe_multi_link *kmulti_link;
|
||||
u32 ucount = info->kprobe_multi.count;
|
||||
@ -2686,6 +2687,8 @@ static int bpf_kprobe_multi_link_fill_link_info(const struct bpf_link *link,
|
||||
|
||||
if (!uaddrs ^ !ucount)
|
||||
return -EINVAL;
|
||||
if (ucookies && !ucount)
|
||||
return -EINVAL;
|
||||
|
||||
kmulti_link = container_of(link, struct bpf_kprobe_multi_link, link);
|
||||
info->kprobe_multi.count = kmulti_link->cnt;
|
||||
@ -2699,6 +2702,18 @@ static int bpf_kprobe_multi_link_fill_link_info(const struct bpf_link *link,
|
||||
else
|
||||
ucount = kmulti_link->cnt;
|
||||
|
||||
if (ucookies) {
|
||||
if (kmulti_link->cookies) {
|
||||
if (copy_to_user(ucookies, kmulti_link->cookies, ucount * sizeof(u64)))
|
||||
return -EFAULT;
|
||||
} else {
|
||||
for (i = 0; i < ucount; i++) {
|
||||
if (put_user(0, ucookies + i))
|
||||
return -EFAULT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (kallsyms_show_value(current_cred())) {
|
||||
if (copy_to_user(uaddrs, kmulti_link->addrs, ucount * sizeof(u64)))
|
||||
return -EFAULT;
|
||||
|
@ -249,18 +249,44 @@ static int get_prog_info(int prog_id, struct bpf_prog_info *info)
|
||||
return err;
|
||||
}
|
||||
|
||||
static int cmp_u64(const void *A, const void *B)
|
||||
{
|
||||
const __u64 *a = A, *b = B;
|
||||
struct addr_cookie {
|
||||
__u64 addr;
|
||||
__u64 cookie;
|
||||
};
|
||||
|
||||
return *a - *b;
|
||||
static int cmp_addr_cookie(const void *A, const void *B)
|
||||
{
|
||||
const struct addr_cookie *a = A, *b = B;
|
||||
|
||||
if (a->addr == b->addr)
|
||||
return 0;
|
||||
return a->addr < b->addr ? -1 : 1;
|
||||
}
|
||||
|
||||
static struct addr_cookie *
|
||||
get_addr_cookie_array(__u64 *addrs, __u64 *cookies, __u32 count)
|
||||
{
|
||||
struct addr_cookie *data;
|
||||
__u32 i;
|
||||
|
||||
data = calloc(count, sizeof(data[0]));
|
||||
if (!data) {
|
||||
p_err("mem alloc failed");
|
||||
return NULL;
|
||||
}
|
||||
for (i = 0; i < count; i++) {
|
||||
data[i].addr = addrs[i];
|
||||
data[i].cookie = cookies[i];
|
||||
}
|
||||
qsort(data, count, sizeof(data[0]), cmp_addr_cookie);
|
||||
return data;
|
||||
}
|
||||
|
||||
static void
|
||||
show_kprobe_multi_json(struct bpf_link_info *info, json_writer_t *wtr)
|
||||
{
|
||||
struct addr_cookie *data;
|
||||
__u32 i, j = 0;
|
||||
__u64 *addrs;
|
||||
|
||||
jsonw_bool_field(json_wtr, "retprobe",
|
||||
info->kprobe_multi.flags & BPF_F_KPROBE_MULTI_RETURN);
|
||||
@ -268,14 +294,20 @@ show_kprobe_multi_json(struct bpf_link_info *info, json_writer_t *wtr)
|
||||
jsonw_uint_field(json_wtr, "missed", info->kprobe_multi.missed);
|
||||
jsonw_name(json_wtr, "funcs");
|
||||
jsonw_start_array(json_wtr);
|
||||
addrs = u64_to_ptr(info->kprobe_multi.addrs);
|
||||
qsort(addrs, info->kprobe_multi.count, sizeof(addrs[0]), cmp_u64);
|
||||
data = get_addr_cookie_array(u64_to_ptr(info->kprobe_multi.addrs),
|
||||
u64_to_ptr(info->kprobe_multi.cookies),
|
||||
info->kprobe_multi.count);
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
/* Load it once for all. */
|
||||
if (!dd.sym_count)
|
||||
kernel_syms_load(&dd);
|
||||
if (!dd.sym_count)
|
||||
goto error;
|
||||
|
||||
for (i = 0; i < dd.sym_count; i++) {
|
||||
if (dd.sym_mapping[i].address != addrs[j])
|
||||
if (dd.sym_mapping[i].address != data[j].addr)
|
||||
continue;
|
||||
jsonw_start_object(json_wtr);
|
||||
jsonw_uint_field(json_wtr, "addr", dd.sym_mapping[i].address);
|
||||
@ -287,11 +319,14 @@ show_kprobe_multi_json(struct bpf_link_info *info, json_writer_t *wtr)
|
||||
} else {
|
||||
jsonw_string_field(json_wtr, "module", dd.sym_mapping[i].module);
|
||||
}
|
||||
jsonw_uint_field(json_wtr, "cookie", data[j].cookie);
|
||||
jsonw_end_object(json_wtr);
|
||||
if (j++ == info->kprobe_multi.count)
|
||||
break;
|
||||
}
|
||||
jsonw_end_array(json_wtr);
|
||||
error:
|
||||
free(data);
|
||||
}
|
||||
|
||||
static __u64 *u64_to_arr(__u64 val)
|
||||
@ -334,6 +369,7 @@ show_perf_event_kprobe_json(struct bpf_link_info *info, json_writer_t *wtr)
|
||||
u64_to_ptr(info->perf_event.kprobe.func_name));
|
||||
jsonw_uint_field(wtr, "offset", info->perf_event.kprobe.offset);
|
||||
jsonw_uint_field(wtr, "missed", info->perf_event.kprobe.missed);
|
||||
jsonw_uint_field(wtr, "cookie", info->perf_event.kprobe.cookie);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -343,6 +379,7 @@ show_perf_event_uprobe_json(struct bpf_link_info *info, json_writer_t *wtr)
|
||||
jsonw_string_field(wtr, "file",
|
||||
u64_to_ptr(info->perf_event.uprobe.file_name));
|
||||
jsonw_uint_field(wtr, "offset", info->perf_event.uprobe.offset);
|
||||
jsonw_uint_field(wtr, "cookie", info->perf_event.uprobe.cookie);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -350,6 +387,7 @@ show_perf_event_tracepoint_json(struct bpf_link_info *info, json_writer_t *wtr)
|
||||
{
|
||||
jsonw_string_field(wtr, "tracepoint",
|
||||
u64_to_ptr(info->perf_event.tracepoint.tp_name));
|
||||
jsonw_uint_field(wtr, "cookie", info->perf_event.tracepoint.cookie);
|
||||
}
|
||||
|
||||
static char *perf_config_hw_cache_str(__u64 config)
|
||||
@ -426,6 +464,8 @@ show_perf_event_event_json(struct bpf_link_info *info, json_writer_t *wtr)
|
||||
else
|
||||
jsonw_uint_field(wtr, "event_config", config);
|
||||
|
||||
jsonw_uint_field(wtr, "cookie", info->perf_event.event.cookie);
|
||||
|
||||
if (type == PERF_TYPE_HW_CACHE && perf_config)
|
||||
free((void *)perf_config);
|
||||
}
|
||||
@ -670,8 +710,8 @@ void netfilter_dump_plain(const struct bpf_link_info *info)
|
||||
|
||||
static void show_kprobe_multi_plain(struct bpf_link_info *info)
|
||||
{
|
||||
struct addr_cookie *data;
|
||||
__u32 i, j = 0;
|
||||
__u64 *addrs;
|
||||
|
||||
if (!info->kprobe_multi.count)
|
||||
return;
|
||||
@ -683,21 +723,24 @@ static void show_kprobe_multi_plain(struct bpf_link_info *info)
|
||||
printf("func_cnt %u ", info->kprobe_multi.count);
|
||||
if (info->kprobe_multi.missed)
|
||||
printf("missed %llu ", info->kprobe_multi.missed);
|
||||
addrs = (__u64 *)u64_to_ptr(info->kprobe_multi.addrs);
|
||||
qsort(addrs, info->kprobe_multi.count, sizeof(__u64), cmp_u64);
|
||||
data = get_addr_cookie_array(u64_to_ptr(info->kprobe_multi.addrs),
|
||||
u64_to_ptr(info->kprobe_multi.cookies),
|
||||
info->kprobe_multi.count);
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
/* Load it once for all. */
|
||||
if (!dd.sym_count)
|
||||
kernel_syms_load(&dd);
|
||||
if (!dd.sym_count)
|
||||
return;
|
||||
goto error;
|
||||
|
||||
printf("\n\t%-16s %s", "addr", "func [module]");
|
||||
printf("\n\t%-16s %-16s %s", "addr", "cookie", "func [module]");
|
||||
for (i = 0; i < dd.sym_count; i++) {
|
||||
if (dd.sym_mapping[i].address != addrs[j])
|
||||
if (dd.sym_mapping[i].address != data[j].addr)
|
||||
continue;
|
||||
printf("\n\t%016lx %s",
|
||||
dd.sym_mapping[i].address, dd.sym_mapping[i].name);
|
||||
printf("\n\t%016lx %-16llx %s",
|
||||
dd.sym_mapping[i].address, data[j].cookie, dd.sym_mapping[i].name);
|
||||
if (dd.sym_mapping[i].module[0] != '\0')
|
||||
printf(" [%s] ", dd.sym_mapping[i].module);
|
||||
else
|
||||
@ -706,6 +749,8 @@ static void show_kprobe_multi_plain(struct bpf_link_info *info)
|
||||
if (j++ == info->kprobe_multi.count)
|
||||
break;
|
||||
}
|
||||
error:
|
||||
free(data);
|
||||
}
|
||||
|
||||
static void show_uprobe_multi_plain(struct bpf_link_info *info)
|
||||
@ -754,6 +799,8 @@ static void show_perf_event_kprobe_plain(struct bpf_link_info *info)
|
||||
printf("+%#x", info->perf_event.kprobe.offset);
|
||||
if (info->perf_event.kprobe.missed)
|
||||
printf(" missed %llu", info->perf_event.kprobe.missed);
|
||||
if (info->perf_event.kprobe.cookie)
|
||||
printf(" cookie %llu", info->perf_event.kprobe.cookie);
|
||||
printf(" ");
|
||||
}
|
||||
|
||||
@ -770,6 +817,8 @@ static void show_perf_event_uprobe_plain(struct bpf_link_info *info)
|
||||
else
|
||||
printf("\n\tuprobe ");
|
||||
printf("%s+%#x ", buf, info->perf_event.uprobe.offset);
|
||||
if (info->perf_event.uprobe.cookie)
|
||||
printf("cookie %llu ", info->perf_event.uprobe.cookie);
|
||||
}
|
||||
|
||||
static void show_perf_event_tracepoint_plain(struct bpf_link_info *info)
|
||||
@ -781,6 +830,8 @@ static void show_perf_event_tracepoint_plain(struct bpf_link_info *info)
|
||||
return;
|
||||
|
||||
printf("\n\ttracepoint %s ", buf);
|
||||
if (info->perf_event.tracepoint.cookie)
|
||||
printf("cookie %llu ", info->perf_event.tracepoint.cookie);
|
||||
}
|
||||
|
||||
static void show_perf_event_event_plain(struct bpf_link_info *info)
|
||||
@ -802,6 +853,9 @@ static void show_perf_event_event_plain(struct bpf_link_info *info)
|
||||
else
|
||||
printf("%llu ", config);
|
||||
|
||||
if (info->perf_event.event.cookie)
|
||||
printf("cookie %llu ", info->perf_event.event.cookie);
|
||||
|
||||
if (type == PERF_TYPE_HW_CACHE && perf_config)
|
||||
free((void *)perf_config);
|
||||
}
|
||||
@ -952,6 +1006,14 @@ again:
|
||||
return -ENOMEM;
|
||||
}
|
||||
info.kprobe_multi.addrs = ptr_to_u64(addrs);
|
||||
cookies = calloc(count, sizeof(__u64));
|
||||
if (!cookies) {
|
||||
p_err("mem alloc failed");
|
||||
free(addrs);
|
||||
close(fd);
|
||||
return -ENOMEM;
|
||||
}
|
||||
info.kprobe_multi.cookies = ptr_to_u64(cookies);
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
@ -977,7 +1039,7 @@ again:
|
||||
cookies = calloc(count, sizeof(__u64));
|
||||
if (!cookies) {
|
||||
p_err("mem alloc failed");
|
||||
free(cookies);
|
||||
free(ref_ctr_offsets);
|
||||
free(offsets);
|
||||
close(fd);
|
||||
return -ENOMEM;
|
||||
|
@ -6563,6 +6563,7 @@ struct bpf_link_info {
|
||||
__u32 count; /* in/out: kprobe_multi function count */
|
||||
__u32 flags;
|
||||
__u64 missed;
|
||||
__aligned_u64 cookies;
|
||||
} kprobe_multi;
|
||||
struct {
|
||||
__aligned_u64 path;
|
||||
@ -6582,6 +6583,7 @@ struct bpf_link_info {
|
||||
__aligned_u64 file_name; /* in/out */
|
||||
__u32 name_len;
|
||||
__u32 offset; /* offset from file_name */
|
||||
__u64 cookie;
|
||||
} uprobe; /* BPF_PERF_EVENT_UPROBE, BPF_PERF_EVENT_URETPROBE */
|
||||
struct {
|
||||
__aligned_u64 func_name; /* in/out */
|
||||
@ -6589,14 +6591,19 @@ struct bpf_link_info {
|
||||
__u32 offset; /* offset from func_name */
|
||||
__u64 addr;
|
||||
__u64 missed;
|
||||
__u64 cookie;
|
||||
} kprobe; /* BPF_PERF_EVENT_KPROBE, BPF_PERF_EVENT_KRETPROBE */
|
||||
struct {
|
||||
__aligned_u64 tp_name; /* in/out */
|
||||
__u32 name_len;
|
||||
__u32 :32;
|
||||
__u64 cookie;
|
||||
} tracepoint; /* BPF_PERF_EVENT_TRACEPOINT */
|
||||
struct {
|
||||
__u64 config;
|
||||
__u32 type;
|
||||
__u32 :32;
|
||||
__u64 cookie;
|
||||
} event; /* BPF_PERF_EVENT_EVENT */
|
||||
};
|
||||
} perf_event;
|
||||
|
@ -19,6 +19,7 @@ static const char *kmulti_syms[] = {
|
||||
};
|
||||
#define KMULTI_CNT ARRAY_SIZE(kmulti_syms)
|
||||
static __u64 kmulti_addrs[KMULTI_CNT];
|
||||
static __u64 kmulti_cookies[] = { 3, 1, 2 };
|
||||
|
||||
#define KPROBE_FUNC "bpf_fentry_test1"
|
||||
static __u64 kprobe_addr;
|
||||
@ -31,6 +32,8 @@ static noinline void uprobe_func(void)
|
||||
asm volatile ("");
|
||||
}
|
||||
|
||||
#define PERF_EVENT_COOKIE 0xdeadbeef
|
||||
|
||||
static int verify_perf_link_info(int fd, enum bpf_perf_event_type type, long addr,
|
||||
ssize_t offset, ssize_t entry_offset)
|
||||
{
|
||||
@ -62,6 +65,8 @@ again:
|
||||
ASSERT_EQ(info.perf_event.kprobe.addr, addr + entry_offset,
|
||||
"kprobe_addr");
|
||||
|
||||
ASSERT_EQ(info.perf_event.kprobe.cookie, PERF_EVENT_COOKIE, "kprobe_cookie");
|
||||
|
||||
if (!info.perf_event.kprobe.func_name) {
|
||||
ASSERT_EQ(info.perf_event.kprobe.name_len, 0, "name_len");
|
||||
info.perf_event.kprobe.func_name = ptr_to_u64(&buf);
|
||||
@ -81,6 +86,8 @@ again:
|
||||
goto again;
|
||||
}
|
||||
|
||||
ASSERT_EQ(info.perf_event.tracepoint.cookie, PERF_EVENT_COOKIE, "tracepoint_cookie");
|
||||
|
||||
err = strncmp(u64_to_ptr(info.perf_event.tracepoint.tp_name), TP_NAME,
|
||||
strlen(TP_NAME));
|
||||
ASSERT_EQ(err, 0, "cmp_tp_name");
|
||||
@ -96,10 +103,17 @@ again:
|
||||
goto again;
|
||||
}
|
||||
|
||||
ASSERT_EQ(info.perf_event.uprobe.cookie, PERF_EVENT_COOKIE, "uprobe_cookie");
|
||||
|
||||
err = strncmp(u64_to_ptr(info.perf_event.uprobe.file_name), UPROBE_FILE,
|
||||
strlen(UPROBE_FILE));
|
||||
ASSERT_EQ(err, 0, "cmp_file_name");
|
||||
break;
|
||||
case BPF_PERF_EVENT_EVENT:
|
||||
ASSERT_EQ(info.perf_event.event.type, PERF_TYPE_SOFTWARE, "event_type");
|
||||
ASSERT_EQ(info.perf_event.event.config, PERF_COUNT_SW_PAGE_FAULTS, "event_config");
|
||||
ASSERT_EQ(info.perf_event.event.cookie, PERF_EVENT_COOKIE, "event_cookie");
|
||||
break;
|
||||
default:
|
||||
err = -1;
|
||||
break;
|
||||
@ -139,6 +153,7 @@ static void test_kprobe_fill_link_info(struct test_fill_link_info *skel,
|
||||
DECLARE_LIBBPF_OPTS(bpf_kprobe_opts, opts,
|
||||
.attach_mode = PROBE_ATTACH_MODE_LINK,
|
||||
.retprobe = type == BPF_PERF_EVENT_KRETPROBE,
|
||||
.bpf_cookie = PERF_EVENT_COOKIE,
|
||||
);
|
||||
ssize_t entry_offset = 0;
|
||||
struct bpf_link *link;
|
||||
@ -163,10 +178,13 @@ static void test_kprobe_fill_link_info(struct test_fill_link_info *skel,
|
||||
|
||||
static void test_tp_fill_link_info(struct test_fill_link_info *skel)
|
||||
{
|
||||
DECLARE_LIBBPF_OPTS(bpf_tracepoint_opts, opts,
|
||||
.bpf_cookie = PERF_EVENT_COOKIE,
|
||||
);
|
||||
struct bpf_link *link;
|
||||
int link_fd, err;
|
||||
|
||||
link = bpf_program__attach_tracepoint(skel->progs.tp_run, TP_CAT, TP_NAME);
|
||||
link = bpf_program__attach_tracepoint_opts(skel->progs.tp_run, TP_CAT, TP_NAME, &opts);
|
||||
if (!ASSERT_OK_PTR(link, "attach_tp"))
|
||||
return;
|
||||
|
||||
@ -176,16 +194,53 @@ static void test_tp_fill_link_info(struct test_fill_link_info *skel)
|
||||
bpf_link__destroy(link);
|
||||
}
|
||||
|
||||
static void test_event_fill_link_info(struct test_fill_link_info *skel)
|
||||
{
|
||||
DECLARE_LIBBPF_OPTS(bpf_perf_event_opts, opts,
|
||||
.bpf_cookie = PERF_EVENT_COOKIE,
|
||||
);
|
||||
struct bpf_link *link;
|
||||
int link_fd, err, pfd;
|
||||
struct perf_event_attr attr = {
|
||||
.type = PERF_TYPE_SOFTWARE,
|
||||
.config = PERF_COUNT_SW_PAGE_FAULTS,
|
||||
.freq = 1,
|
||||
.sample_freq = 1,
|
||||
.size = sizeof(struct perf_event_attr),
|
||||
};
|
||||
|
||||
pfd = syscall(__NR_perf_event_open, &attr, -1 /* pid */, 0 /* cpu 0 */,
|
||||
-1 /* group id */, 0 /* flags */);
|
||||
if (!ASSERT_GE(pfd, 0, "perf_event_open"))
|
||||
return;
|
||||
|
||||
link = bpf_program__attach_perf_event_opts(skel->progs.event_run, pfd, &opts);
|
||||
if (!ASSERT_OK_PTR(link, "attach_event"))
|
||||
goto error;
|
||||
|
||||
link_fd = bpf_link__fd(link);
|
||||
err = verify_perf_link_info(link_fd, BPF_PERF_EVENT_EVENT, 0, 0, 0);
|
||||
ASSERT_OK(err, "verify_perf_link_info");
|
||||
bpf_link__destroy(link);
|
||||
|
||||
error:
|
||||
close(pfd);
|
||||
}
|
||||
|
||||
static void test_uprobe_fill_link_info(struct test_fill_link_info *skel,
|
||||
enum bpf_perf_event_type type)
|
||||
{
|
||||
DECLARE_LIBBPF_OPTS(bpf_uprobe_opts, opts,
|
||||
.retprobe = type == BPF_PERF_EVENT_URETPROBE,
|
||||
.bpf_cookie = PERF_EVENT_COOKIE,
|
||||
);
|
||||
struct bpf_link *link;
|
||||
int link_fd, err;
|
||||
|
||||
link = bpf_program__attach_uprobe(skel->progs.uprobe_run,
|
||||
type == BPF_PERF_EVENT_URETPROBE,
|
||||
0, /* self pid */
|
||||
UPROBE_FILE, uprobe_offset);
|
||||
link = bpf_program__attach_uprobe_opts(skel->progs.uprobe_run,
|
||||
0, /* self pid */
|
||||
UPROBE_FILE, uprobe_offset,
|
||||
&opts);
|
||||
if (!ASSERT_OK_PTR(link, "attach_uprobe"))
|
||||
return;
|
||||
|
||||
@ -195,11 +250,11 @@ static void test_uprobe_fill_link_info(struct test_fill_link_info *skel,
|
||||
bpf_link__destroy(link);
|
||||
}
|
||||
|
||||
static int verify_kmulti_link_info(int fd, bool retprobe)
|
||||
static int verify_kmulti_link_info(int fd, bool retprobe, bool has_cookies)
|
||||
{
|
||||
__u64 addrs[KMULTI_CNT], cookies[KMULTI_CNT];
|
||||
struct bpf_link_info info;
|
||||
__u32 len = sizeof(info);
|
||||
__u64 addrs[KMULTI_CNT];
|
||||
int flags, i, err;
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
@ -221,18 +276,22 @@ again:
|
||||
|
||||
if (!info.kprobe_multi.addrs) {
|
||||
info.kprobe_multi.addrs = ptr_to_u64(addrs);
|
||||
info.kprobe_multi.cookies = ptr_to_u64(cookies);
|
||||
goto again;
|
||||
}
|
||||
for (i = 0; i < KMULTI_CNT; i++)
|
||||
for (i = 0; i < KMULTI_CNT; i++) {
|
||||
ASSERT_EQ(addrs[i], kmulti_addrs[i], "kmulti_addrs");
|
||||
ASSERT_EQ(cookies[i], has_cookies ? kmulti_cookies[i] : 0,
|
||||
"kmulti_cookies_value");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void verify_kmulti_invalid_user_buffer(int fd)
|
||||
{
|
||||
__u64 addrs[KMULTI_CNT], cookies[KMULTI_CNT];
|
||||
struct bpf_link_info info;
|
||||
__u32 len = sizeof(info);
|
||||
__u64 addrs[KMULTI_CNT];
|
||||
int err, i;
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
@ -266,7 +325,20 @@ static void verify_kmulti_invalid_user_buffer(int fd)
|
||||
info.kprobe_multi.count = KMULTI_CNT;
|
||||
info.kprobe_multi.addrs = 0x1; /* invalid addr */
|
||||
err = bpf_link_get_info_by_fd(fd, &info, &len);
|
||||
ASSERT_EQ(err, -EFAULT, "invalid_buff");
|
||||
ASSERT_EQ(err, -EFAULT, "invalid_buff_addrs");
|
||||
|
||||
info.kprobe_multi.count = KMULTI_CNT;
|
||||
info.kprobe_multi.addrs = ptr_to_u64(addrs);
|
||||
info.kprobe_multi.cookies = 0x1; /* invalid addr */
|
||||
err = bpf_link_get_info_by_fd(fd, &info, &len);
|
||||
ASSERT_EQ(err, -EFAULT, "invalid_buff_cookies");
|
||||
|
||||
/* cookies && !count */
|
||||
info.kprobe_multi.count = 0;
|
||||
info.kprobe_multi.addrs = ptr_to_u64(NULL);
|
||||
info.kprobe_multi.cookies = ptr_to_u64(cookies);
|
||||
err = bpf_link_get_info_by_fd(fd, &info, &len);
|
||||
ASSERT_EQ(err, -EINVAL, "invalid_cookies_count");
|
||||
}
|
||||
|
||||
static int symbols_cmp_r(const void *a, const void *b)
|
||||
@ -278,13 +350,15 @@ static int symbols_cmp_r(const void *a, const void *b)
|
||||
}
|
||||
|
||||
static void test_kprobe_multi_fill_link_info(struct test_fill_link_info *skel,
|
||||
bool retprobe, bool invalid)
|
||||
bool retprobe, bool cookies,
|
||||
bool invalid)
|
||||
{
|
||||
LIBBPF_OPTS(bpf_kprobe_multi_opts, opts);
|
||||
struct bpf_link *link;
|
||||
int link_fd, err;
|
||||
|
||||
opts.syms = kmulti_syms;
|
||||
opts.cookies = cookies ? kmulti_cookies : NULL;
|
||||
opts.cnt = KMULTI_CNT;
|
||||
opts.retprobe = retprobe;
|
||||
link = bpf_program__attach_kprobe_multi_opts(skel->progs.kmulti_run, NULL, &opts);
|
||||
@ -293,7 +367,7 @@ static void test_kprobe_multi_fill_link_info(struct test_fill_link_info *skel,
|
||||
|
||||
link_fd = bpf_link__fd(link);
|
||||
if (!invalid) {
|
||||
err = verify_kmulti_link_info(link_fd, retprobe);
|
||||
err = verify_kmulti_link_info(link_fd, retprobe, cookies);
|
||||
ASSERT_OK(err, "verify_kmulti_link_info");
|
||||
} else {
|
||||
verify_kmulti_invalid_user_buffer(link_fd);
|
||||
@ -513,6 +587,8 @@ void test_fill_link_info(void)
|
||||
test_kprobe_fill_link_info(skel, BPF_PERF_EVENT_KPROBE, true);
|
||||
if (test__start_subtest("tracepoint_link_info"))
|
||||
test_tp_fill_link_info(skel);
|
||||
if (test__start_subtest("event_link_info"))
|
||||
test_event_fill_link_info(skel);
|
||||
|
||||
uprobe_offset = get_uprobe_offset(&uprobe_func);
|
||||
if (test__start_subtest("uprobe_link_info"))
|
||||
@ -523,12 +599,16 @@ void test_fill_link_info(void)
|
||||
qsort(kmulti_syms, KMULTI_CNT, sizeof(kmulti_syms[0]), symbols_cmp_r);
|
||||
for (i = 0; i < KMULTI_CNT; i++)
|
||||
kmulti_addrs[i] = ksym_get_addr(kmulti_syms[i]);
|
||||
if (test__start_subtest("kprobe_multi_link_info"))
|
||||
test_kprobe_multi_fill_link_info(skel, false, false);
|
||||
if (test__start_subtest("kretprobe_multi_link_info"))
|
||||
test_kprobe_multi_fill_link_info(skel, true, false);
|
||||
if (test__start_subtest("kprobe_multi_link_info")) {
|
||||
test_kprobe_multi_fill_link_info(skel, false, false, false);
|
||||
test_kprobe_multi_fill_link_info(skel, false, true, false);
|
||||
}
|
||||
if (test__start_subtest("kretprobe_multi_link_info")) {
|
||||
test_kprobe_multi_fill_link_info(skel, true, false, false);
|
||||
test_kprobe_multi_fill_link_info(skel, true, true, false);
|
||||
}
|
||||
if (test__start_subtest("kprobe_multi_invalid_ubuff"))
|
||||
test_kprobe_multi_fill_link_info(skel, true, true);
|
||||
test_kprobe_multi_fill_link_info(skel, true, true, true);
|
||||
|
||||
if (test__start_subtest("uprobe_multi_link_info"))
|
||||
test_uprobe_multi_fill_link_info(skel, false, false);
|
||||
|
@ -33,6 +33,12 @@ int BPF_PROG(tp_run)
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEC("perf_event")
|
||||
int event_run(void *ctx)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEC("kprobe.multi")
|
||||
int BPF_PROG(kmulti_run)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user