Skip to content

Commit 147c693

Browse files
olsajirianakryiko
authored andcommitted
selftests/bpf: Add link_info test for uprobe_multi link
Adding fill_link_info test for uprobe_multi link. Setting up uprobes with bogus ref_ctr_offsets and cookie values to test all the bpf_link_info::uprobe_multi fields. Signed-off-by: Jiri Olsa <[email protected]> Signed-off-by: Andrii Nakryiko <[email protected]> Acked-by: Song Liu <[email protected]> Acked-by: Yonghong Song <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent 1703612 commit 147c693

File tree

2 files changed

+204
-0
lines changed

2 files changed

+204
-0
lines changed

tools/testing/selftests/bpf/prog_tests/fill_link_info.c

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <test_progs.h>
88
#include "trace_helpers.h"
99
#include "test_fill_link_info.skel.h"
10+
#include "bpf/libbpf_internal.h"
1011

1112
#define TP_CAT "sched"
1213
#define TP_NAME "sched_switch"
@@ -300,6 +301,196 @@ static void test_kprobe_multi_fill_link_info(struct test_fill_link_info *skel,
300301
bpf_link__destroy(link);
301302
}
302303

304+
#define SEC(name) __attribute__((section(name), used))
305+
306+
static short uprobe_link_info_sema_1 SEC(".probes");
307+
static short uprobe_link_info_sema_2 SEC(".probes");
308+
static short uprobe_link_info_sema_3 SEC(".probes");
309+
310+
noinline void uprobe_link_info_func_1(void)
311+
{
312+
asm volatile ("");
313+
uprobe_link_info_sema_1++;
314+
}
315+
316+
noinline void uprobe_link_info_func_2(void)
317+
{
318+
asm volatile ("");
319+
uprobe_link_info_sema_2++;
320+
}
321+
322+
noinline void uprobe_link_info_func_3(void)
323+
{
324+
asm volatile ("");
325+
uprobe_link_info_sema_3++;
326+
}
327+
328+
static int
329+
verify_umulti_link_info(int fd, bool retprobe, __u64 *offsets,
330+
__u64 *cookies, __u64 *ref_ctr_offsets)
331+
{
332+
char path[PATH_MAX], path_buf[PATH_MAX];
333+
struct bpf_link_info info;
334+
__u32 len = sizeof(info);
335+
__u64 ref_ctr_offsets_buf[3];
336+
__u64 offsets_buf[3];
337+
__u64 cookies_buf[3];
338+
int i, err, bit;
339+
__u32 count = 0;
340+
341+
memset(path, 0, sizeof(path));
342+
err = readlink("/proc/self/exe", path, sizeof(path));
343+
if (!ASSERT_NEQ(err, -1, "readlink"))
344+
return -1;
345+
346+
for (bit = 0; bit < 8; bit++) {
347+
memset(&info, 0, sizeof(info));
348+
info.uprobe_multi.path = ptr_to_u64(path_buf);
349+
info.uprobe_multi.path_size = sizeof(path_buf);
350+
info.uprobe_multi.count = count;
351+
352+
if (bit & 0x1)
353+
info.uprobe_multi.offsets = ptr_to_u64(offsets_buf);
354+
if (bit & 0x2)
355+
info.uprobe_multi.cookies = ptr_to_u64(cookies_buf);
356+
if (bit & 0x4)
357+
info.uprobe_multi.ref_ctr_offsets = ptr_to_u64(ref_ctr_offsets_buf);
358+
359+
err = bpf_link_get_info_by_fd(fd, &info, &len);
360+
if (!ASSERT_OK(err, "bpf_link_get_info_by_fd"))
361+
return -1;
362+
363+
if (!ASSERT_EQ(info.type, BPF_LINK_TYPE_UPROBE_MULTI, "info.type"))
364+
return -1;
365+
366+
ASSERT_EQ(info.uprobe_multi.pid, getpid(), "info.uprobe_multi.pid");
367+
ASSERT_EQ(info.uprobe_multi.count, 3, "info.uprobe_multi.count");
368+
ASSERT_EQ(info.uprobe_multi.flags & BPF_F_KPROBE_MULTI_RETURN,
369+
retprobe, "info.uprobe_multi.flags.retprobe");
370+
ASSERT_EQ(info.uprobe_multi.path_size, strlen(path) + 1, "info.uprobe_multi.path_size");
371+
ASSERT_STREQ(path_buf, path, "info.uprobe_multi.path");
372+
373+
for (i = 0; i < info.uprobe_multi.count; i++) {
374+
if (info.uprobe_multi.offsets)
375+
ASSERT_EQ(offsets_buf[i], offsets[i], "info.uprobe_multi.offsets");
376+
if (info.uprobe_multi.cookies)
377+
ASSERT_EQ(cookies_buf[i], cookies[i], "info.uprobe_multi.cookies");
378+
if (info.uprobe_multi.ref_ctr_offsets) {
379+
ASSERT_EQ(ref_ctr_offsets_buf[i], ref_ctr_offsets[i],
380+
"info.uprobe_multi.ref_ctr_offsets");
381+
}
382+
}
383+
count = count ?: info.uprobe_multi.count;
384+
}
385+
386+
return 0;
387+
}
388+
389+
static void verify_umulti_invalid_user_buffer(int fd)
390+
{
391+
struct bpf_link_info info;
392+
__u32 len = sizeof(info);
393+
__u64 buf[3];
394+
int err;
395+
396+
/* upath_size defined, not path */
397+
memset(&info, 0, sizeof(info));
398+
info.uprobe_multi.path_size = 3;
399+
err = bpf_link_get_info_by_fd(fd, &info, &len);
400+
ASSERT_EQ(err, -EINVAL, "failed_upath_size");
401+
402+
/* path defined, but small */
403+
memset(&info, 0, sizeof(info));
404+
info.uprobe_multi.path = ptr_to_u64(buf);
405+
info.uprobe_multi.path_size = 3;
406+
err = bpf_link_get_info_by_fd(fd, &info, &len);
407+
ASSERT_LT(err, 0, "failed_upath_small");
408+
409+
/* path has wrong pointer */
410+
memset(&info, 0, sizeof(info));
411+
info.uprobe_multi.path_size = PATH_MAX;
412+
info.uprobe_multi.path = 123;
413+
err = bpf_link_get_info_by_fd(fd, &info, &len);
414+
ASSERT_EQ(err, -EFAULT, "failed_bad_path_ptr");
415+
416+
/* count zero, with offsets */
417+
memset(&info, 0, sizeof(info));
418+
info.uprobe_multi.offsets = ptr_to_u64(buf);
419+
err = bpf_link_get_info_by_fd(fd, &info, &len);
420+
ASSERT_EQ(err, -EINVAL, "failed_count");
421+
422+
/* offsets not big enough */
423+
memset(&info, 0, sizeof(info));
424+
info.uprobe_multi.offsets = ptr_to_u64(buf);
425+
info.uprobe_multi.count = 2;
426+
err = bpf_link_get_info_by_fd(fd, &info, &len);
427+
ASSERT_EQ(err, -ENOSPC, "failed_small_count");
428+
429+
/* offsets has wrong pointer */
430+
memset(&info, 0, sizeof(info));
431+
info.uprobe_multi.offsets = 123;
432+
info.uprobe_multi.count = 3;
433+
err = bpf_link_get_info_by_fd(fd, &info, &len);
434+
ASSERT_EQ(err, -EFAULT, "failed_wrong_offsets");
435+
}
436+
437+
static void test_uprobe_multi_fill_link_info(struct test_fill_link_info *skel,
438+
bool retprobe, bool invalid)
439+
{
440+
LIBBPF_OPTS(bpf_uprobe_multi_opts, opts,
441+
.retprobe = retprobe,
442+
);
443+
const char *syms[3] = {
444+
"uprobe_link_info_func_1",
445+
"uprobe_link_info_func_2",
446+
"uprobe_link_info_func_3",
447+
};
448+
__u64 cookies[3] = {
449+
0xdead,
450+
0xbeef,
451+
0xcafe,
452+
};
453+
const char *sema[3] = {
454+
"uprobe_link_info_sema_1",
455+
"uprobe_link_info_sema_2",
456+
"uprobe_link_info_sema_3",
457+
};
458+
__u64 *offsets = NULL, *ref_ctr_offsets;
459+
struct bpf_link *link;
460+
int link_fd, err;
461+
462+
err = elf_resolve_syms_offsets("/proc/self/exe", 3, sema,
463+
(unsigned long **) &ref_ctr_offsets, STT_OBJECT);
464+
if (!ASSERT_OK(err, "elf_resolve_syms_offsets_object"))
465+
return;
466+
467+
err = elf_resolve_syms_offsets("/proc/self/exe", 3, syms,
468+
(unsigned long **) &offsets, STT_FUNC);
469+
if (!ASSERT_OK(err, "elf_resolve_syms_offsets_func"))
470+
goto out;
471+
472+
opts.syms = syms;
473+
opts.cookies = &cookies[0];
474+
opts.ref_ctr_offsets = (unsigned long *) &ref_ctr_offsets[0];
475+
opts.cnt = ARRAY_SIZE(syms);
476+
477+
link = bpf_program__attach_uprobe_multi(skel->progs.umulti_run, 0,
478+
"/proc/self/exe", NULL, &opts);
479+
if (!ASSERT_OK_PTR(link, "bpf_program__attach_uprobe_multi"))
480+
goto out;
481+
482+
link_fd = bpf_link__fd(link);
483+
if (invalid)
484+
verify_umulti_invalid_user_buffer(link_fd);
485+
else
486+
verify_umulti_link_info(link_fd, retprobe, offsets, cookies, ref_ctr_offsets);
487+
488+
bpf_link__destroy(link);
489+
out:
490+
free(ref_ctr_offsets);
491+
free(offsets);
492+
}
493+
303494
void test_fill_link_info(void)
304495
{
305496
struct test_fill_link_info *skel;
@@ -339,6 +530,13 @@ void test_fill_link_info(void)
339530
if (test__start_subtest("kprobe_multi_invalid_ubuff"))
340531
test_kprobe_multi_fill_link_info(skel, true, true);
341532

533+
if (test__start_subtest("uprobe_multi_link_info"))
534+
test_uprobe_multi_fill_link_info(skel, false, false);
535+
if (test__start_subtest("uretprobe_multi_link_info"))
536+
test_uprobe_multi_fill_link_info(skel, true, false);
537+
if (test__start_subtest("uprobe_multi_invalid"))
538+
test_uprobe_multi_fill_link_info(skel, false, true);
539+
342540
cleanup:
343541
test_fill_link_info__destroy(skel);
344542
}

tools/testing/selftests/bpf/progs/test_fill_link_info.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,10 @@ int BPF_PROG(kmulti_run)
3939
return 0;
4040
}
4141

42+
SEC("uprobe.multi")
43+
int BPF_PROG(umulti_run)
44+
{
45+
return 0;
46+
}
47+
4248
char _license[] SEC("license") = "GPL";

0 commit comments

Comments
 (0)