1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2023 Hengqi Chen */
3 
4 #include <test_progs.h>
5 #include "test_uprobe.skel.h"
6 
urand_spawn(int * pid)7 static FILE *urand_spawn(int *pid)
8 {
9 	FILE *f;
10 
11 	/* urandom_read's stdout is wired into f */
12 	f = popen("./urandom_read 1 report-pid", "r");
13 	if (!f)
14 		return NULL;
15 
16 	if (fscanf(f, "%d", pid) != 1) {
17 		pclose(f);
18 		errno = EINVAL;
19 		return NULL;
20 	}
21 
22 	return f;
23 }
24 
urand_trigger(FILE ** urand_pipe)25 static int urand_trigger(FILE **urand_pipe)
26 {
27 	int exit_code;
28 
29 	/* pclose() waits for child process to exit and returns their exit code */
30 	exit_code = pclose(*urand_pipe);
31 	*urand_pipe = NULL;
32 
33 	return exit_code;
34 }
35 
test_uprobe(void)36 void test_uprobe(void)
37 {
38 	LIBBPF_OPTS(bpf_uprobe_opts, uprobe_opts);
39 	struct test_uprobe *skel;
40 	FILE *urand_pipe = NULL;
41 	int urand_pid = 0, err;
42 
43 	skel = test_uprobe__open_and_load();
44 	if (!ASSERT_OK_PTR(skel, "skel_open"))
45 		return;
46 
47 	urand_pipe = urand_spawn(&urand_pid);
48 	if (!ASSERT_OK_PTR(urand_pipe, "urand_spawn"))
49 		goto cleanup;
50 
51 	skel->bss->my_pid = urand_pid;
52 
53 	/* Manual attach uprobe to urandlib_api
54 	 * There are two `urandlib_api` symbols in .dynsym section:
55 	 *   - urandlib_api@LIBURANDOM_READ_1.0.0
56 	 *   - urandlib_api@@LIBURANDOM_READ_2.0.0
57 	 * Both are global bind and would cause a conflict if user
58 	 * specify the symbol name without a version suffix
59 	 */
60 	uprobe_opts.func_name = "urandlib_api";
61 	skel->links.test4 = bpf_program__attach_uprobe_opts(skel->progs.test4,
62 							    urand_pid,
63 							    "./liburandom_read.so",
64 							    0 /* offset */,
65 							    &uprobe_opts);
66 	if (!ASSERT_ERR_PTR(skel->links.test4, "urandlib_api_attach_conflict"))
67 		goto cleanup;
68 
69 	uprobe_opts.func_name = "urandlib_api@LIBURANDOM_READ_1.0.0";
70 	skel->links.test4 = bpf_program__attach_uprobe_opts(skel->progs.test4,
71 							    urand_pid,
72 							    "./liburandom_read.so",
73 							    0 /* offset */,
74 							    &uprobe_opts);
75 	if (!ASSERT_OK_PTR(skel->links.test4, "urandlib_api_attach_ok"))
76 		goto cleanup;
77 
78 	/* Auto attach 3 u[ret]probes to urandlib_api_sameoffset */
79 	err = test_uprobe__attach(skel);
80 	if (!ASSERT_OK(err, "skel_attach"))
81 		goto cleanup;
82 
83 	/* trigger urandom_read */
84 	ASSERT_OK(urand_trigger(&urand_pipe), "urand_exit_code");
85 
86 	ASSERT_EQ(skel->bss->test1_result, 1, "urandlib_api_sameoffset");
87 	ASSERT_EQ(skel->bss->test2_result, 1, "urandlib_api_sameoffset@v1");
88 	ASSERT_EQ(skel->bss->test3_result, 3, "urandlib_api_sameoffset@@v2");
89 	ASSERT_EQ(skel->bss->test4_result, 1, "urandlib_api");
90 
91 cleanup:
92 	if (urand_pipe)
93 		pclose(urand_pipe);
94 	test_uprobe__destroy(skel);
95 }
96