Skip to content

Commit b7d1af3

Browse files
author
Alexei Starovoitov
committed
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 <[email protected]> --- ==================== Reviewed-by: Quentin Monnet <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
2 parents bbc094b + b0dc037 commit b7d1af3

File tree

7 files changed

+214
-33
lines changed

7 files changed

+214
-33
lines changed

include/uapi/linux/bpf.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6563,6 +6563,7 @@ struct bpf_link_info {
65636563
__u32 count; /* in/out: kprobe_multi function count */
65646564
__u32 flags;
65656565
__u64 missed;
6566+
__aligned_u64 cookies;
65666567
} kprobe_multi;
65676568
struct {
65686569
__aligned_u64 path;
@@ -6582,21 +6583,27 @@ struct bpf_link_info {
65826583
__aligned_u64 file_name; /* in/out */
65836584
__u32 name_len;
65846585
__u32 offset; /* offset from file_name */
6586+
__u64 cookie;
65856587
} uprobe; /* BPF_PERF_EVENT_UPROBE, BPF_PERF_EVENT_URETPROBE */
65866588
struct {
65876589
__aligned_u64 func_name; /* in/out */
65886590
__u32 name_len;
65896591
__u32 offset; /* offset from func_name */
65906592
__u64 addr;
65916593
__u64 missed;
6594+
__u64 cookie;
65926595
} kprobe; /* BPF_PERF_EVENT_KPROBE, BPF_PERF_EVENT_KRETPROBE */
65936596
struct {
65946597
__aligned_u64 tp_name; /* in/out */
65956598
__u32 name_len;
6599+
__u32 :32;
6600+
__u64 cookie;
65966601
} tracepoint; /* BPF_PERF_EVENT_TRACEPOINT */
65976602
struct {
65986603
__u64 config;
65996604
__u32 type;
6605+
__u32 :32;
6606+
__u64 cookie;
66006607
} event; /* BPF_PERF_EVENT_EVENT */
66016608
};
66026609
} perf_event;

kernel/bpf/syscall.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3501,6 +3501,7 @@ static int bpf_perf_link_fill_kprobe(const struct perf_event *event,
35013501
if (!kallsyms_show_value(current_cred()))
35023502
addr = 0;
35033503
info->perf_event.kprobe.addr = addr;
3504+
info->perf_event.kprobe.cookie = event->bpf_cookie;
35043505
return 0;
35053506
}
35063507
#endif
@@ -3526,6 +3527,7 @@ static int bpf_perf_link_fill_uprobe(const struct perf_event *event,
35263527
else
35273528
info->perf_event.type = BPF_PERF_EVENT_UPROBE;
35283529
info->perf_event.uprobe.offset = offset;
3530+
info->perf_event.uprobe.cookie = event->bpf_cookie;
35293531
return 0;
35303532
}
35313533
#endif
@@ -3553,6 +3555,7 @@ static int bpf_perf_link_fill_tracepoint(const struct perf_event *event,
35533555
uname = u64_to_user_ptr(info->perf_event.tracepoint.tp_name);
35543556
ulen = info->perf_event.tracepoint.name_len;
35553557
info->perf_event.type = BPF_PERF_EVENT_TRACEPOINT;
3558+
info->perf_event.tracepoint.cookie = event->bpf_cookie;
35563559
return bpf_perf_link_fill_common(event, uname, ulen, NULL, NULL, NULL, NULL);
35573560
}
35583561

@@ -3561,6 +3564,7 @@ static int bpf_perf_link_fill_perf_event(const struct perf_event *event,
35613564
{
35623565
info->perf_event.event.type = event->attr.type;
35633566
info->perf_event.event.config = event->attr.config;
3567+
info->perf_event.event.cookie = event->bpf_cookie;
35643568
info->perf_event.type = BPF_PERF_EVENT_EVENT;
35653569
return 0;
35663570
}

kernel/trace/bpf_trace.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2679,13 +2679,16 @@ static void bpf_kprobe_multi_link_dealloc(struct bpf_link *link)
26792679
static int bpf_kprobe_multi_link_fill_link_info(const struct bpf_link *link,
26802680
struct bpf_link_info *info)
26812681
{
2682+
u64 __user *ucookies = u64_to_user_ptr(info->kprobe_multi.cookies);
26822683
u64 __user *uaddrs = u64_to_user_ptr(info->kprobe_multi.addrs);
26832684
struct bpf_kprobe_multi_link *kmulti_link;
26842685
u32 ucount = info->kprobe_multi.count;
26852686
int err = 0, i;
26862687

26872688
if (!uaddrs ^ !ucount)
26882689
return -EINVAL;
2690+
if (ucookies && !ucount)
2691+
return -EINVAL;
26892692

26902693
kmulti_link = container_of(link, struct bpf_kprobe_multi_link, link);
26912694
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,
26992702
else
27002703
ucount = kmulti_link->cnt;
27012704

2705+
if (ucookies) {
2706+
if (kmulti_link->cookies) {
2707+
if (copy_to_user(ucookies, kmulti_link->cookies, ucount * sizeof(u64)))
2708+
return -EFAULT;
2709+
} else {
2710+
for (i = 0; i < ucount; i++) {
2711+
if (put_user(0, ucookies + i))
2712+
return -EFAULT;
2713+
}
2714+
}
2715+
}
2716+
27022717
if (kallsyms_show_value(current_cred())) {
27032718
if (copy_to_user(uaddrs, kmulti_link->addrs, ucount * sizeof(u64)))
27042719
return -EFAULT;

tools/bpf/bpftool/link.c

Lines changed: 78 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -249,33 +249,65 @@ static int get_prog_info(int prog_id, struct bpf_prog_info *info)
249249
return err;
250250
}
251251

252-
static int cmp_u64(const void *A, const void *B)
252+
struct addr_cookie {
253+
__u64 addr;
254+
__u64 cookie;
255+
};
256+
257+
static int cmp_addr_cookie(const void *A, const void *B)
253258
{
254-
const __u64 *a = A, *b = B;
259+
const struct addr_cookie *a = A, *b = B;
255260

256-
return *a - *b;
261+
if (a->addr == b->addr)
262+
return 0;
263+
return a->addr < b->addr ? -1 : 1;
264+
}
265+
266+
static struct addr_cookie *
267+
get_addr_cookie_array(__u64 *addrs, __u64 *cookies, __u32 count)
268+
{
269+
struct addr_cookie *data;
270+
__u32 i;
271+
272+
data = calloc(count, sizeof(data[0]));
273+
if (!data) {
274+
p_err("mem alloc failed");
275+
return NULL;
276+
}
277+
for (i = 0; i < count; i++) {
278+
data[i].addr = addrs[i];
279+
data[i].cookie = cookies[i];
280+
}
281+
qsort(data, count, sizeof(data[0]), cmp_addr_cookie);
282+
return data;
257283
}
258284

259285
static void
260286
show_kprobe_multi_json(struct bpf_link_info *info, json_writer_t *wtr)
261287
{
288+
struct addr_cookie *data;
262289
__u32 i, j = 0;
263-
__u64 *addrs;
264290

265291
jsonw_bool_field(json_wtr, "retprobe",
266292
info->kprobe_multi.flags & BPF_F_KPROBE_MULTI_RETURN);
267293
jsonw_uint_field(json_wtr, "func_cnt", info->kprobe_multi.count);
268294
jsonw_uint_field(json_wtr, "missed", info->kprobe_multi.missed);
269295
jsonw_name(json_wtr, "funcs");
270296
jsonw_start_array(json_wtr);
271-
addrs = u64_to_ptr(info->kprobe_multi.addrs);
272-
qsort(addrs, info->kprobe_multi.count, sizeof(addrs[0]), cmp_u64);
297+
data = get_addr_cookie_array(u64_to_ptr(info->kprobe_multi.addrs),
298+
u64_to_ptr(info->kprobe_multi.cookies),
299+
info->kprobe_multi.count);
300+
if (!data)
301+
return;
273302

274303
/* Load it once for all. */
275304
if (!dd.sym_count)
276305
kernel_syms_load(&dd);
306+
if (!dd.sym_count)
307+
goto error;
308+
277309
for (i = 0; i < dd.sym_count; i++) {
278-
if (dd.sym_mapping[i].address != addrs[j])
310+
if (dd.sym_mapping[i].address != data[j].addr)
279311
continue;
280312
jsonw_start_object(json_wtr);
281313
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)
287319
} else {
288320
jsonw_string_field(json_wtr, "module", dd.sym_mapping[i].module);
289321
}
322+
jsonw_uint_field(json_wtr, "cookie", data[j].cookie);
290323
jsonw_end_object(json_wtr);
291324
if (j++ == info->kprobe_multi.count)
292325
break;
293326
}
294327
jsonw_end_array(json_wtr);
328+
error:
329+
free(data);
295330
}
296331

297332
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)
334369
u64_to_ptr(info->perf_event.kprobe.func_name));
335370
jsonw_uint_field(wtr, "offset", info->perf_event.kprobe.offset);
336371
jsonw_uint_field(wtr, "missed", info->perf_event.kprobe.missed);
372+
jsonw_uint_field(wtr, "cookie", info->perf_event.kprobe.cookie);
337373
}
338374

339375
static void
@@ -343,13 +379,15 @@ show_perf_event_uprobe_json(struct bpf_link_info *info, json_writer_t *wtr)
343379
jsonw_string_field(wtr, "file",
344380
u64_to_ptr(info->perf_event.uprobe.file_name));
345381
jsonw_uint_field(wtr, "offset", info->perf_event.uprobe.offset);
382+
jsonw_uint_field(wtr, "cookie", info->perf_event.uprobe.cookie);
346383
}
347384

348385
static void
349386
show_perf_event_tracepoint_json(struct bpf_link_info *info, json_writer_t *wtr)
350387
{
351388
jsonw_string_field(wtr, "tracepoint",
352389
u64_to_ptr(info->perf_event.tracepoint.tp_name));
390+
jsonw_uint_field(wtr, "cookie", info->perf_event.tracepoint.cookie);
353391
}
354392

355393
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)
426464
else
427465
jsonw_uint_field(wtr, "event_config", config);
428466

467+
jsonw_uint_field(wtr, "cookie", info->perf_event.event.cookie);
468+
429469
if (type == PERF_TYPE_HW_CACHE && perf_config)
430470
free((void *)perf_config);
431471
}
@@ -670,8 +710,8 @@ void netfilter_dump_plain(const struct bpf_link_info *info)
670710

671711
static void show_kprobe_multi_plain(struct bpf_link_info *info)
672712
{
713+
struct addr_cookie *data;
673714
__u32 i, j = 0;
674-
__u64 *addrs;
675715

676716
if (!info->kprobe_multi.count)
677717
return;
@@ -683,21 +723,24 @@ static void show_kprobe_multi_plain(struct bpf_link_info *info)
683723
printf("func_cnt %u ", info->kprobe_multi.count);
684724
if (info->kprobe_multi.missed)
685725
printf("missed %llu ", info->kprobe_multi.missed);
686-
addrs = (__u64 *)u64_to_ptr(info->kprobe_multi.addrs);
687-
qsort(addrs, info->kprobe_multi.count, sizeof(__u64), cmp_u64);
726+
data = get_addr_cookie_array(u64_to_ptr(info->kprobe_multi.addrs),
727+
u64_to_ptr(info->kprobe_multi.cookies),
728+
info->kprobe_multi.count);
729+
if (!data)
730+
return;
688731

689732
/* Load it once for all. */
690733
if (!dd.sym_count)
691734
kernel_syms_load(&dd);
692735
if (!dd.sym_count)
693-
return;
736+
goto error;
694737

695-
printf("\n\t%-16s %s", "addr", "func [module]");
738+
printf("\n\t%-16s %-16s %s", "addr", "cookie", "func [module]");
696739
for (i = 0; i < dd.sym_count; i++) {
697-
if (dd.sym_mapping[i].address != addrs[j])
740+
if (dd.sym_mapping[i].address != data[j].addr)
698741
continue;
699-
printf("\n\t%016lx %s",
700-
dd.sym_mapping[i].address, dd.sym_mapping[i].name);
742+
printf("\n\t%016lx %-16llx %s",
743+
dd.sym_mapping[i].address, data[j].cookie, dd.sym_mapping[i].name);
701744
if (dd.sym_mapping[i].module[0] != '\0')
702745
printf(" [%s] ", dd.sym_mapping[i].module);
703746
else
@@ -706,6 +749,8 @@ static void show_kprobe_multi_plain(struct bpf_link_info *info)
706749
if (j++ == info->kprobe_multi.count)
707750
break;
708751
}
752+
error:
753+
free(data);
709754
}
710755

711756
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)
754799
printf("+%#x", info->perf_event.kprobe.offset);
755800
if (info->perf_event.kprobe.missed)
756801
printf(" missed %llu", info->perf_event.kprobe.missed);
802+
if (info->perf_event.kprobe.cookie)
803+
printf(" cookie %llu", info->perf_event.kprobe.cookie);
757804
printf(" ");
758805
}
759806

@@ -770,6 +817,8 @@ static void show_perf_event_uprobe_plain(struct bpf_link_info *info)
770817
else
771818
printf("\n\tuprobe ");
772819
printf("%s+%#x ", buf, info->perf_event.uprobe.offset);
820+
if (info->perf_event.uprobe.cookie)
821+
printf("cookie %llu ", info->perf_event.uprobe.cookie);
773822
}
774823

775824
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)
781830
return;
782831

783832
printf("\n\ttracepoint %s ", buf);
833+
if (info->perf_event.tracepoint.cookie)
834+
printf("cookie %llu ", info->perf_event.tracepoint.cookie);
784835
}
785836

786837
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)
802853
else
803854
printf("%llu ", config);
804855

856+
if (info->perf_event.event.cookie)
857+
printf("cookie %llu ", info->perf_event.event.cookie);
858+
805859
if (type == PERF_TYPE_HW_CACHE && perf_config)
806860
free((void *)perf_config);
807861
}
@@ -952,6 +1006,14 @@ static int do_show_link(int fd)
9521006
return -ENOMEM;
9531007
}
9541008
info.kprobe_multi.addrs = ptr_to_u64(addrs);
1009+
cookies = calloc(count, sizeof(__u64));
1010+
if (!cookies) {
1011+
p_err("mem alloc failed");
1012+
free(addrs);
1013+
close(fd);
1014+
return -ENOMEM;
1015+
}
1016+
info.kprobe_multi.cookies = ptr_to_u64(cookies);
9551017
goto again;
9561018
}
9571019
}
@@ -977,7 +1039,7 @@ static int do_show_link(int fd)
9771039
cookies = calloc(count, sizeof(__u64));
9781040
if (!cookies) {
9791041
p_err("mem alloc failed");
980-
free(cookies);
1042+
free(ref_ctr_offsets);
9811043
free(offsets);
9821044
close(fd);
9831045
return -ENOMEM;

tools/include/uapi/linux/bpf.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6563,6 +6563,7 @@ struct bpf_link_info {
65636563
__u32 count; /* in/out: kprobe_multi function count */
65646564
__u32 flags;
65656565
__u64 missed;
6566+
__aligned_u64 cookies;
65666567
} kprobe_multi;
65676568
struct {
65686569
__aligned_u64 path;
@@ -6582,21 +6583,27 @@ struct bpf_link_info {
65826583
__aligned_u64 file_name; /* in/out */
65836584
__u32 name_len;
65846585
__u32 offset; /* offset from file_name */
6586+
__u64 cookie;
65856587
} uprobe; /* BPF_PERF_EVENT_UPROBE, BPF_PERF_EVENT_URETPROBE */
65866588
struct {
65876589
__aligned_u64 func_name; /* in/out */
65886590
__u32 name_len;
65896591
__u32 offset; /* offset from func_name */
65906592
__u64 addr;
65916593
__u64 missed;
6594+
__u64 cookie;
65926595
} kprobe; /* BPF_PERF_EVENT_KPROBE, BPF_PERF_EVENT_KRETPROBE */
65936596
struct {
65946597
__aligned_u64 tp_name; /* in/out */
65956598
__u32 name_len;
6599+
__u32 :32;
6600+
__u64 cookie;
65966601
} tracepoint; /* BPF_PERF_EVENT_TRACEPOINT */
65976602
struct {
65986603
__u64 config;
65996604
__u32 type;
6605+
__u32 :32;
6606+
__u64 cookie;
66006607
} event; /* BPF_PERF_EVENT_EVENT */
66016608
};
66026609
} perf_event;

0 commit comments

Comments
 (0)