xref: /linux/tools/testing/selftests/bpf/prog_tests/module_attach.c (revision e2683c8868d03382da7e1ce8453b543a043066d1)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2020 Facebook */
3 
4 #include <test_progs.h>
5 #include <stdbool.h>
6 #include "test_module_attach.skel.h"
7 #include "testing_helpers.h"
8 
9 static const char * const read_tests[] = {
10 	"handle_raw_tp",
11 	"handle_tp_btf",
12 	"handle_fentry",
13 	"handle_fentry_explicit",
14 	"handle_fmod_ret",
15 };
16 
17 static const char * const detach_tests[] = {
18 	"handle_fentry",
19 	"handle_fexit",
20 	"kprobe_multi",
21 };
22 
23 static const int READ_SZ = 456;
24 static const int WRITE_SZ = 457;
25 
26 static int trigger_module_test_writable(int *val)
27 {
28 	int fd, err;
29 	char buf[65];
30 	ssize_t rd;
31 
32 	fd = open(BPF_TESTMOD_TEST_FILE, O_RDONLY);
33 	err = -errno;
34 	if (!ASSERT_GE(fd, 0, "testmode_file_open"))
35 		return err;
36 
37 	rd = read(fd, buf, sizeof(buf) - 1);
38 	err = -errno;
39 	if (!ASSERT_GT(rd, 0, "testmod_file_rd_val")) {
40 		close(fd);
41 		return err;
42 	}
43 
44 	buf[rd] = '\0';
45 	*val = strtol(buf, NULL, 0);
46 	close(fd);
47 
48 	return 0;
49 }
50 
51 static void test_module_attach_prog(const char *prog_name, int sz,
52 				    const char *attach_target, int ret)
53 {
54 	struct test_module_attach *skel;
55 	struct bpf_program *prog;
56 	int err;
57 
58 	skel = test_module_attach__open();
59 	if (!ASSERT_OK_PTR(skel, "module_attach open"))
60 		return;
61 
62 	prog = bpf_object__find_program_by_name(skel->obj, prog_name);
63 	if (!ASSERT_OK_PTR(prog, "module_attach find_program"))
64 		goto cleanup;
65 	bpf_program__set_autoload(prog, true);
66 
67 	if (attach_target) {
68 		err = bpf_program__set_attach_target(prog, 0, attach_target);
69 		if (!ASSERT_OK(err, attach_target))
70 			goto cleanup;
71 	}
72 
73 	err = test_module_attach__load(skel);
74 	if (!ASSERT_OK(err, "module_attach load"))
75 		goto cleanup;
76 
77 	err = test_module_attach__attach(skel);
78 	if (!ASSERT_OK(err, "module_attach attach"))
79 		goto cleanup;
80 
81 	if (sz) {
82 		/* trigger both read and write though each test uses only one */
83 		ASSERT_OK(trigger_module_test_read(sz), "trigger_read");
84 		ASSERT_OK(trigger_module_test_write(sz), "trigger_write");
85 
86 		ASSERT_EQ(skel->bss->sz, sz, prog_name);
87 	}
88 
89 	if (ret)
90 		ASSERT_EQ(skel->bss->retval, ret, "ret");
91 cleanup:
92 	test_module_attach__destroy(skel);
93 }
94 
95 static void test_module_attach_writable(void)
96 {
97 	struct test_module_attach__bss *bss;
98 	struct test_module_attach *skel;
99 	int writable_val = 0;
100 	int err;
101 
102 	skel = test_module_attach__open();
103 	if (!ASSERT_OK_PTR(skel, "module_attach open"))
104 		return;
105 
106 	bpf_program__set_autoload(skel->progs.handle_raw_tp_writable_bare, true);
107 
108 	err = test_module_attach__load(skel);
109 	if (!ASSERT_OK(err, "module_attach load"))
110 		goto cleanup;
111 
112 	bss = skel->bss;
113 
114 	err = test_module_attach__attach(skel);
115 	if (!ASSERT_OK(err, "module_attach attach"))
116 		goto cleanup;
117 
118 	bss->raw_tp_writable_bare_early_ret = true;
119 	bss->raw_tp_writable_bare_out_val = 0xf1f2f3f4;
120 	ASSERT_OK(trigger_module_test_writable(&writable_val),
121 		  "trigger_writable");
122 	ASSERT_EQ(bss->raw_tp_writable_bare_in_val, 1024, "writable_test_in");
123 	ASSERT_EQ(bss->raw_tp_writable_bare_out_val, writable_val,
124 		  "writable_test_out");
125 cleanup:
126 	test_module_attach__destroy(skel);
127 }
128 
129 static void test_module_attach_detach(const char *prog_name)
130 {
131 	struct test_module_attach *skel;
132 	struct bpf_program *prog;
133 	struct bpf_link *link;
134 	int err;
135 
136 	skel = test_module_attach__open();
137 	if (!ASSERT_OK_PTR(skel, "module_attach open"))
138 		return;
139 
140 	prog = bpf_object__find_program_by_name(skel->obj, prog_name);
141 	if (!ASSERT_OK_PTR(prog, "module_attach find_program"))
142 		goto cleanup;
143 	bpf_program__set_autoload(prog, true);
144 
145 	err = test_module_attach__load(skel);
146 	if (!ASSERT_OK(err, "module_attach load"))
147 		goto cleanup;
148 
149 	/* attach and make sure it gets module reference */
150 	link = bpf_program__attach(prog);
151 	if (!ASSERT_OK_PTR(link, "module_attach attach"))
152 		goto cleanup;
153 
154 	ASSERT_ERR(try_unload_module("bpf_testmod", 1, false), "try_unload_module");
155 	bpf_link__destroy(link);
156 cleanup:
157 	test_module_attach__destroy(skel);
158 }
159 
160 void test_module_attach(void)
161 {
162 	int i;
163 
164 	for (i = 0; i < ARRAY_SIZE(read_tests); i++) {
165 		if (!test__start_subtest(read_tests[i]))
166 			continue;
167 		test_module_attach_prog(read_tests[i], READ_SZ, NULL, 0);
168 	}
169 	if (test__start_subtest("handle_raw_tp_bare"))
170 		test_module_attach_prog("handle_raw_tp_bare", WRITE_SZ, NULL, 0);
171 	if (test__start_subtest("handle_raw_tp_writable_bare"))
172 		test_module_attach_writable();
173 	if (test__start_subtest("handle_fentry_manual")) {
174 		test_module_attach_prog("handle_fentry_manual", READ_SZ,
175 					"bpf_testmod_test_read", 0);
176 	}
177 	if (test__start_subtest("handle_fentry_explicit_manual")) {
178 		test_module_attach_prog("handle_fentry_explicit_manual",
179 					READ_SZ,
180 					"bpf_testmod:bpf_testmod_test_read", 0);
181 	}
182 	if (test__start_subtest("handle_fexit"))
183 		test_module_attach_prog("handle_fexit", READ_SZ, NULL, -EIO);
184 	if (test__start_subtest("handle_fexit_ret"))
185 		test_module_attach_prog("handle_fexit_ret", 0, NULL, 0);
186 	for (i = 0; i < ARRAY_SIZE(detach_tests); i++) {
187 		char test_name[50];
188 
189 		snprintf(test_name, sizeof(test_name), "%s_detach", detach_tests[i]);
190 		if (!test__start_subtest(test_name))
191 			continue;
192 		test_module_attach_detach(detach_tests[i]);
193 	}
194 }
195