staging: rtl8192u: remove redundant assignment to pointer crypt
[linux/fpc-iii.git] / tools / testing / selftests / bpf / test_sockopt_multi.c
blob4be3441db86737bf87bc57f52eec924ce4e769c6
1 // SPDX-License-Identifier: GPL-2.0
3 #include <error.h>
4 #include <errno.h>
5 #include <stdio.h>
6 #include <unistd.h>
7 #include <sys/types.h>
8 #include <sys/socket.h>
9 #include <netinet/in.h>
11 #include <linux/filter.h>
12 #include <bpf/bpf.h>
13 #include <bpf/libbpf.h>
15 #include "bpf_rlimit.h"
16 #include "bpf_util.h"
17 #include "cgroup_helpers.h"
19 static int prog_attach(struct bpf_object *obj, int cgroup_fd, const char *title)
21 enum bpf_attach_type attach_type;
22 enum bpf_prog_type prog_type;
23 struct bpf_program *prog;
24 int err;
26 err = libbpf_prog_type_by_name(title, &prog_type, &attach_type);
27 if (err) {
28 log_err("Failed to deduct types for %s BPF program", title);
29 return -1;
32 prog = bpf_object__find_program_by_title(obj, title);
33 if (!prog) {
34 log_err("Failed to find %s BPF program", title);
35 return -1;
38 err = bpf_prog_attach(bpf_program__fd(prog), cgroup_fd,
39 attach_type, BPF_F_ALLOW_MULTI);
40 if (err) {
41 log_err("Failed to attach %s BPF program", title);
42 return -1;
45 return 0;
48 static int prog_detach(struct bpf_object *obj, int cgroup_fd, const char *title)
50 enum bpf_attach_type attach_type;
51 enum bpf_prog_type prog_type;
52 struct bpf_program *prog;
53 int err;
55 err = libbpf_prog_type_by_name(title, &prog_type, &attach_type);
56 if (err)
57 return -1;
59 prog = bpf_object__find_program_by_title(obj, title);
60 if (!prog)
61 return -1;
63 err = bpf_prog_detach2(bpf_program__fd(prog), cgroup_fd,
64 attach_type);
65 if (err)
66 return -1;
68 return 0;
71 static int run_getsockopt_test(struct bpf_object *obj, int cg_parent,
72 int cg_child, int sock_fd)
74 socklen_t optlen;
75 __u8 buf;
76 int err;
78 /* Set IP_TOS to the expected value (0x80). */
80 buf = 0x80;
81 err = setsockopt(sock_fd, SOL_IP, IP_TOS, &buf, 1);
82 if (err < 0) {
83 log_err("Failed to call setsockopt(IP_TOS)");
84 goto detach;
87 buf = 0x00;
88 optlen = 1;
89 err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
90 if (err) {
91 log_err("Failed to call getsockopt(IP_TOS)");
92 goto detach;
95 if (buf != 0x80) {
96 log_err("Unexpected getsockopt 0x%x != 0x80 without BPF", buf);
97 err = -1;
98 goto detach;
101 /* Attach child program and make sure it returns new value:
102 * - kernel: -> 0x80
103 * - child: 0x80 -> 0x90
106 err = prog_attach(obj, cg_child, "cgroup/getsockopt/child");
107 if (err)
108 goto detach;
110 buf = 0x00;
111 optlen = 1;
112 err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
113 if (err) {
114 log_err("Failed to call getsockopt(IP_TOS)");
115 goto detach;
118 if (buf != 0x90) {
119 log_err("Unexpected getsockopt 0x%x != 0x90", buf);
120 err = -1;
121 goto detach;
124 /* Attach parent program and make sure it returns new value:
125 * - kernel: -> 0x80
126 * - child: 0x80 -> 0x90
127 * - parent: 0x90 -> 0xA0
130 err = prog_attach(obj, cg_parent, "cgroup/getsockopt/parent");
131 if (err)
132 goto detach;
134 buf = 0x00;
135 optlen = 1;
136 err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
137 if (err) {
138 log_err("Failed to call getsockopt(IP_TOS)");
139 goto detach;
142 if (buf != 0xA0) {
143 log_err("Unexpected getsockopt 0x%x != 0xA0", buf);
144 err = -1;
145 goto detach;
148 /* Setting unexpected initial sockopt should return EPERM:
149 * - kernel: -> 0x40
150 * - child: unexpected 0x40, EPERM
151 * - parent: unexpected 0x40, EPERM
154 buf = 0x40;
155 if (setsockopt(sock_fd, SOL_IP, IP_TOS, &buf, 1) < 0) {
156 log_err("Failed to call setsockopt(IP_TOS)");
157 goto detach;
160 buf = 0x00;
161 optlen = 1;
162 err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
163 if (!err) {
164 log_err("Unexpected success from getsockopt(IP_TOS)");
165 goto detach;
168 /* Detach child program and make sure we still get EPERM:
169 * - kernel: -> 0x40
170 * - parent: unexpected 0x40, EPERM
173 err = prog_detach(obj, cg_child, "cgroup/getsockopt/child");
174 if (err) {
175 log_err("Failed to detach child program");
176 goto detach;
179 buf = 0x00;
180 optlen = 1;
181 err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
182 if (!err) {
183 log_err("Unexpected success from getsockopt(IP_TOS)");
184 goto detach;
187 /* Set initial value to the one the parent program expects:
188 * - kernel: -> 0x90
189 * - parent: 0x90 -> 0xA0
192 buf = 0x90;
193 err = setsockopt(sock_fd, SOL_IP, IP_TOS, &buf, 1);
194 if (err < 0) {
195 log_err("Failed to call setsockopt(IP_TOS)");
196 goto detach;
199 buf = 0x00;
200 optlen = 1;
201 err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
202 if (err) {
203 log_err("Failed to call getsockopt(IP_TOS)");
204 goto detach;
207 if (buf != 0xA0) {
208 log_err("Unexpected getsockopt 0x%x != 0xA0", buf);
209 err = -1;
210 goto detach;
213 detach:
214 prog_detach(obj, cg_child, "cgroup/getsockopt/child");
215 prog_detach(obj, cg_parent, "cgroup/getsockopt/parent");
217 return err;
220 static int run_setsockopt_test(struct bpf_object *obj, int cg_parent,
221 int cg_child, int sock_fd)
223 socklen_t optlen;
224 __u8 buf;
225 int err;
227 /* Set IP_TOS to the expected value (0x80). */
229 buf = 0x80;
230 err = setsockopt(sock_fd, SOL_IP, IP_TOS, &buf, 1);
231 if (err < 0) {
232 log_err("Failed to call setsockopt(IP_TOS)");
233 goto detach;
236 buf = 0x00;
237 optlen = 1;
238 err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
239 if (err) {
240 log_err("Failed to call getsockopt(IP_TOS)");
241 goto detach;
244 if (buf != 0x80) {
245 log_err("Unexpected getsockopt 0x%x != 0x80 without BPF", buf);
246 err = -1;
247 goto detach;
250 /* Attach child program and make sure it adds 0x10. */
252 err = prog_attach(obj, cg_child, "cgroup/setsockopt");
253 if (err)
254 goto detach;
256 buf = 0x80;
257 err = setsockopt(sock_fd, SOL_IP, IP_TOS, &buf, 1);
258 if (err < 0) {
259 log_err("Failed to call setsockopt(IP_TOS)");
260 goto detach;
263 buf = 0x00;
264 optlen = 1;
265 err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
266 if (err) {
267 log_err("Failed to call getsockopt(IP_TOS)");
268 goto detach;
271 if (buf != 0x80 + 0x10) {
272 log_err("Unexpected getsockopt 0x%x != 0x80 + 0x10", buf);
273 err = -1;
274 goto detach;
277 /* Attach parent program and make sure it adds another 0x10. */
279 err = prog_attach(obj, cg_parent, "cgroup/setsockopt");
280 if (err)
281 goto detach;
283 buf = 0x80;
284 err = setsockopt(sock_fd, SOL_IP, IP_TOS, &buf, 1);
285 if (err < 0) {
286 log_err("Failed to call setsockopt(IP_TOS)");
287 goto detach;
290 buf = 0x00;
291 optlen = 1;
292 err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
293 if (err) {
294 log_err("Failed to call getsockopt(IP_TOS)");
295 goto detach;
298 if (buf != 0x80 + 2 * 0x10) {
299 log_err("Unexpected getsockopt 0x%x != 0x80 + 2 * 0x10", buf);
300 err = -1;
301 goto detach;
304 detach:
305 prog_detach(obj, cg_child, "cgroup/setsockopt");
306 prog_detach(obj, cg_parent, "cgroup/setsockopt");
308 return err;
311 int main(int argc, char **argv)
313 struct bpf_prog_load_attr attr = {
314 .file = "./sockopt_multi.o",
316 int cg_parent = -1, cg_child = -1;
317 struct bpf_object *obj = NULL;
318 int sock_fd = -1;
319 int err = -1;
320 int ignored;
322 if (setup_cgroup_environment()) {
323 log_err("Failed to setup cgroup environment\n");
324 goto out;
327 cg_parent = create_and_get_cgroup("/parent");
328 if (cg_parent < 0) {
329 log_err("Failed to create cgroup /parent\n");
330 goto out;
333 cg_child = create_and_get_cgroup("/parent/child");
334 if (cg_child < 0) {
335 log_err("Failed to create cgroup /parent/child\n");
336 goto out;
339 if (join_cgroup("/parent/child")) {
340 log_err("Failed to join cgroup /parent/child\n");
341 goto out;
344 err = bpf_prog_load_xattr(&attr, &obj, &ignored);
345 if (err) {
346 log_err("Failed to load BPF object");
347 goto out;
350 sock_fd = socket(AF_INET, SOCK_STREAM, 0);
351 if (sock_fd < 0) {
352 log_err("Failed to create socket");
353 goto out;
356 if (run_getsockopt_test(obj, cg_parent, cg_child, sock_fd))
357 err = -1;
358 printf("test_sockopt_multi: getsockopt %s\n",
359 err ? "FAILED" : "PASSED");
361 if (run_setsockopt_test(obj, cg_parent, cg_child, sock_fd))
362 err = -1;
363 printf("test_sockopt_multi: setsockopt %s\n",
364 err ? "FAILED" : "PASSED");
366 out:
367 close(sock_fd);
368 bpf_object__close(obj);
369 close(cg_child);
370 close(cg_parent);
372 printf("test_sockopt_multi: %s\n", err ? "FAILED" : "PASSED");
373 return err ? EXIT_FAILURE : EXIT_SUCCESS;