1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Tests for attaching, detaching, and replacing flow_dissector BPF program.
4 */
5
6 #define _GNU_SOURCE
7 #include <errno.h>
8 #include <fcntl.h>
9 #include <sched.h>
10 #include <stdbool.h>
11 #include <sys/stat.h>
12 #include <unistd.h>
13
14 #include <linux/bpf.h>
15 #include <bpf/bpf.h>
16
17 #include "test_progs.h"
18
19 static int init_net = -1;
20
query_attached_prog_id(int netns)21 static __u32 query_attached_prog_id(int netns)
22 {
23 __u32 prog_ids[1] = {};
24 __u32 prog_cnt = ARRAY_SIZE(prog_ids);
25 int err;
26
27 err = bpf_prog_query(netns, BPF_FLOW_DISSECTOR, 0, NULL,
28 prog_ids, &prog_cnt);
29 if (CHECK_FAIL(err)) {
30 perror("bpf_prog_query");
31 return 0;
32 }
33
34 return prog_cnt == 1 ? prog_ids[0] : 0;
35 }
36
prog_is_attached(int netns)37 static bool prog_is_attached(int netns)
38 {
39 return query_attached_prog_id(netns) > 0;
40 }
41
load_prog(enum bpf_prog_type type)42 static int load_prog(enum bpf_prog_type type)
43 {
44 struct bpf_insn prog[] = {
45 BPF_MOV64_IMM(BPF_REG_0, BPF_OK),
46 BPF_EXIT_INSN(),
47 };
48 int fd;
49
50 fd = bpf_test_load_program(type, prog, ARRAY_SIZE(prog), "GPL", 0, NULL, 0);
51 if (CHECK_FAIL(fd < 0))
52 perror("bpf_test_load_program");
53
54 return fd;
55 }
56
query_prog_id(int prog)57 static __u32 query_prog_id(int prog)
58 {
59 struct bpf_prog_info info = {};
60 __u32 info_len = sizeof(info);
61 int err;
62
63 err = bpf_obj_get_info_by_fd(prog, &info, &info_len);
64 if (CHECK_FAIL(err || info_len != sizeof(info))) {
65 perror("bpf_obj_get_info_by_fd");
66 return 0;
67 }
68
69 return info.id;
70 }
71
unshare_net(int old_net)72 static int unshare_net(int old_net)
73 {
74 int err, new_net;
75
76 err = unshare(CLONE_NEWNET);
77 if (CHECK_FAIL(err)) {
78 perror("unshare(CLONE_NEWNET)");
79 return -1;
80 }
81 new_net = open("/proc/self/ns/net", O_RDONLY);
82 if (CHECK_FAIL(new_net < 0)) {
83 perror("open(/proc/self/ns/net)");
84 setns(old_net, CLONE_NEWNET);
85 return -1;
86 }
87 return new_net;
88 }
89
test_prog_attach_prog_attach(int netns,int prog1,int prog2)90 static void test_prog_attach_prog_attach(int netns, int prog1, int prog2)
91 {
92 int err;
93
94 err = bpf_prog_attach(prog1, 0, BPF_FLOW_DISSECTOR, 0);
95 if (CHECK_FAIL(err)) {
96 perror("bpf_prog_attach(prog1)");
97 return;
98 }
99 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
100
101 /* Expect success when attaching a different program */
102 err = bpf_prog_attach(prog2, 0, BPF_FLOW_DISSECTOR, 0);
103 if (CHECK_FAIL(err)) {
104 perror("bpf_prog_attach(prog2) #1");
105 goto out_detach;
106 }
107 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog2));
108
109 /* Expect failure when attaching the same program twice */
110 err = bpf_prog_attach(prog2, 0, BPF_FLOW_DISSECTOR, 0);
111 if (CHECK_FAIL(!err || errno != EINVAL))
112 perror("bpf_prog_attach(prog2) #2");
113 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog2));
114
115 out_detach:
116 err = bpf_prog_detach2(prog2, 0, BPF_FLOW_DISSECTOR);
117 if (CHECK_FAIL(err))
118 perror("bpf_prog_detach");
119 CHECK_FAIL(prog_is_attached(netns));
120 }
121
test_link_create_link_create(int netns,int prog1,int prog2)122 static void test_link_create_link_create(int netns, int prog1, int prog2)
123 {
124 DECLARE_LIBBPF_OPTS(bpf_link_create_opts, opts);
125 int link1, link2;
126
127 link1 = bpf_link_create(prog1, netns, BPF_FLOW_DISSECTOR, &opts);
128 if (CHECK_FAIL(link < 0)) {
129 perror("bpf_link_create(prog1)");
130 return;
131 }
132 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
133
134 /* Expect failure creating link when another link exists */
135 errno = 0;
136 link2 = bpf_link_create(prog2, netns, BPF_FLOW_DISSECTOR, &opts);
137 if (CHECK_FAIL(link2 >= 0 || errno != E2BIG))
138 perror("bpf_prog_attach(prog2) expected E2BIG");
139 if (link2 >= 0)
140 close(link2);
141 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
142
143 close(link1);
144 CHECK_FAIL(prog_is_attached(netns));
145 }
146
test_prog_attach_link_create(int netns,int prog1,int prog2)147 static void test_prog_attach_link_create(int netns, int prog1, int prog2)
148 {
149 DECLARE_LIBBPF_OPTS(bpf_link_create_opts, opts);
150 int err, link;
151
152 err = bpf_prog_attach(prog1, 0, BPF_FLOW_DISSECTOR, 0);
153 if (CHECK_FAIL(err)) {
154 perror("bpf_prog_attach(prog1)");
155 return;
156 }
157 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
158
159 /* Expect failure creating link when prog attached */
160 errno = 0;
161 link = bpf_link_create(prog2, netns, BPF_FLOW_DISSECTOR, &opts);
162 if (CHECK_FAIL(link >= 0 || errno != EEXIST))
163 perror("bpf_link_create(prog2) expected EEXIST");
164 if (link >= 0)
165 close(link);
166 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
167
168 err = bpf_prog_detach2(prog1, 0, BPF_FLOW_DISSECTOR);
169 if (CHECK_FAIL(err))
170 perror("bpf_prog_detach");
171 CHECK_FAIL(prog_is_attached(netns));
172 }
173
test_link_create_prog_attach(int netns,int prog1,int prog2)174 static void test_link_create_prog_attach(int netns, int prog1, int prog2)
175 {
176 DECLARE_LIBBPF_OPTS(bpf_link_create_opts, opts);
177 int err, link;
178
179 link = bpf_link_create(prog1, netns, BPF_FLOW_DISSECTOR, &opts);
180 if (CHECK_FAIL(link < 0)) {
181 perror("bpf_link_create(prog1)");
182 return;
183 }
184 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
185
186 /* Expect failure attaching prog when link exists */
187 errno = 0;
188 err = bpf_prog_attach(prog2, 0, BPF_FLOW_DISSECTOR, 0);
189 if (CHECK_FAIL(!err || errno != EEXIST))
190 perror("bpf_prog_attach(prog2) expected EEXIST");
191 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
192
193 close(link);
194 CHECK_FAIL(prog_is_attached(netns));
195 }
196
test_link_create_prog_detach(int netns,int prog1,int prog2)197 static void test_link_create_prog_detach(int netns, int prog1, int prog2)
198 {
199 DECLARE_LIBBPF_OPTS(bpf_link_create_opts, opts);
200 int err, link;
201
202 link = bpf_link_create(prog1, netns, BPF_FLOW_DISSECTOR, &opts);
203 if (CHECK_FAIL(link < 0)) {
204 perror("bpf_link_create(prog1)");
205 return;
206 }
207 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
208
209 /* Expect failure detaching prog when link exists */
210 errno = 0;
211 err = bpf_prog_detach2(prog1, 0, BPF_FLOW_DISSECTOR);
212 if (CHECK_FAIL(!err || errno != EINVAL))
213 perror("bpf_prog_detach expected EINVAL");
214 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
215
216 close(link);
217 CHECK_FAIL(prog_is_attached(netns));
218 }
219
test_prog_attach_detach_query(int netns,int prog1,int prog2)220 static void test_prog_attach_detach_query(int netns, int prog1, int prog2)
221 {
222 int err;
223
224 err = bpf_prog_attach(prog1, 0, BPF_FLOW_DISSECTOR, 0);
225 if (CHECK_FAIL(err)) {
226 perror("bpf_prog_attach(prog1)");
227 return;
228 }
229 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
230
231 err = bpf_prog_detach2(prog1, 0, BPF_FLOW_DISSECTOR);
232 if (CHECK_FAIL(err)) {
233 perror("bpf_prog_detach");
234 return;
235 }
236
237 /* Expect no prog attached after successful detach */
238 CHECK_FAIL(prog_is_attached(netns));
239 }
240
test_link_create_close_query(int netns,int prog1,int prog2)241 static void test_link_create_close_query(int netns, int prog1, int prog2)
242 {
243 DECLARE_LIBBPF_OPTS(bpf_link_create_opts, opts);
244 int link;
245
246 link = bpf_link_create(prog1, netns, BPF_FLOW_DISSECTOR, &opts);
247 if (CHECK_FAIL(link < 0)) {
248 perror("bpf_link_create(prog1)");
249 return;
250 }
251 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
252
253 close(link);
254 /* Expect no prog attached after closing last link FD */
255 CHECK_FAIL(prog_is_attached(netns));
256 }
257
test_link_update_no_old_prog(int netns,int prog1,int prog2)258 static void test_link_update_no_old_prog(int netns, int prog1, int prog2)
259 {
260 DECLARE_LIBBPF_OPTS(bpf_link_create_opts, create_opts);
261 DECLARE_LIBBPF_OPTS(bpf_link_update_opts, update_opts);
262 int err, link;
263
264 link = bpf_link_create(prog1, netns, BPF_FLOW_DISSECTOR, &create_opts);
265 if (CHECK_FAIL(link < 0)) {
266 perror("bpf_link_create(prog1)");
267 return;
268 }
269 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
270
271 /* Expect success replacing the prog when old prog not specified */
272 update_opts.flags = 0;
273 update_opts.old_prog_fd = 0;
274 err = bpf_link_update(link, prog2, &update_opts);
275 if (CHECK_FAIL(err))
276 perror("bpf_link_update");
277 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog2));
278
279 close(link);
280 CHECK_FAIL(prog_is_attached(netns));
281 }
282
test_link_update_replace_old_prog(int netns,int prog1,int prog2)283 static void test_link_update_replace_old_prog(int netns, int prog1, int prog2)
284 {
285 DECLARE_LIBBPF_OPTS(bpf_link_create_opts, create_opts);
286 DECLARE_LIBBPF_OPTS(bpf_link_update_opts, update_opts);
287 int err, link;
288
289 link = bpf_link_create(prog1, netns, BPF_FLOW_DISSECTOR, &create_opts);
290 if (CHECK_FAIL(link < 0)) {
291 perror("bpf_link_create(prog1)");
292 return;
293 }
294 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
295
296 /* Expect success F_REPLACE and old prog specified to succeed */
297 update_opts.flags = BPF_F_REPLACE;
298 update_opts.old_prog_fd = prog1;
299 err = bpf_link_update(link, prog2, &update_opts);
300 if (CHECK_FAIL(err))
301 perror("bpf_link_update");
302 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog2));
303
304 close(link);
305 CHECK_FAIL(prog_is_attached(netns));
306 }
307
test_link_update_same_prog(int netns,int prog1,int prog2)308 static void test_link_update_same_prog(int netns, int prog1, int prog2)
309 {
310 DECLARE_LIBBPF_OPTS(bpf_link_create_opts, create_opts);
311 DECLARE_LIBBPF_OPTS(bpf_link_update_opts, update_opts);
312 int err, link;
313
314 link = bpf_link_create(prog1, netns, BPF_FLOW_DISSECTOR, &create_opts);
315 if (CHECK_FAIL(link < 0)) {
316 perror("bpf_link_create(prog1)");
317 return;
318 }
319 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
320
321 /* Expect success updating the prog with the same one */
322 update_opts.flags = 0;
323 update_opts.old_prog_fd = 0;
324 err = bpf_link_update(link, prog1, &update_opts);
325 if (CHECK_FAIL(err))
326 perror("bpf_link_update");
327 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
328
329 close(link);
330 CHECK_FAIL(prog_is_attached(netns));
331 }
332
test_link_update_invalid_opts(int netns,int prog1,int prog2)333 static void test_link_update_invalid_opts(int netns, int prog1, int prog2)
334 {
335 DECLARE_LIBBPF_OPTS(bpf_link_create_opts, create_opts);
336 DECLARE_LIBBPF_OPTS(bpf_link_update_opts, update_opts);
337 int err, link;
338
339 link = bpf_link_create(prog1, netns, BPF_FLOW_DISSECTOR, &create_opts);
340 if (CHECK_FAIL(link < 0)) {
341 perror("bpf_link_create(prog1)");
342 return;
343 }
344 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
345
346 /* Expect update to fail w/ old prog FD but w/o F_REPLACE*/
347 errno = 0;
348 update_opts.flags = 0;
349 update_opts.old_prog_fd = prog1;
350 err = bpf_link_update(link, prog2, &update_opts);
351 if (CHECK_FAIL(!err || errno != EINVAL)) {
352 perror("bpf_link_update expected EINVAL");
353 goto out_close;
354 }
355 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
356
357 /* Expect update to fail on old prog FD mismatch */
358 errno = 0;
359 update_opts.flags = BPF_F_REPLACE;
360 update_opts.old_prog_fd = prog2;
361 err = bpf_link_update(link, prog2, &update_opts);
362 if (CHECK_FAIL(!err || errno != EPERM)) {
363 perror("bpf_link_update expected EPERM");
364 goto out_close;
365 }
366 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
367
368 /* Expect update to fail for invalid old prog FD */
369 errno = 0;
370 update_opts.flags = BPF_F_REPLACE;
371 update_opts.old_prog_fd = -1;
372 err = bpf_link_update(link, prog2, &update_opts);
373 if (CHECK_FAIL(!err || errno != EBADF)) {
374 perror("bpf_link_update expected EBADF");
375 goto out_close;
376 }
377 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
378
379 /* Expect update to fail with invalid flags */
380 errno = 0;
381 update_opts.flags = BPF_F_ALLOW_MULTI;
382 update_opts.old_prog_fd = 0;
383 err = bpf_link_update(link, prog2, &update_opts);
384 if (CHECK_FAIL(!err || errno != EINVAL))
385 perror("bpf_link_update expected EINVAL");
386 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
387
388 out_close:
389 close(link);
390 CHECK_FAIL(prog_is_attached(netns));
391 }
392
test_link_update_invalid_prog(int netns,int prog1,int prog2)393 static void test_link_update_invalid_prog(int netns, int prog1, int prog2)
394 {
395 DECLARE_LIBBPF_OPTS(bpf_link_create_opts, create_opts);
396 DECLARE_LIBBPF_OPTS(bpf_link_update_opts, update_opts);
397 int err, link, prog3;
398
399 link = bpf_link_create(prog1, netns, BPF_FLOW_DISSECTOR, &create_opts);
400 if (CHECK_FAIL(link < 0)) {
401 perror("bpf_link_create(prog1)");
402 return;
403 }
404 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
405
406 /* Expect failure when new prog FD is not valid */
407 errno = 0;
408 update_opts.flags = 0;
409 update_opts.old_prog_fd = 0;
410 err = bpf_link_update(link, -1, &update_opts);
411 if (CHECK_FAIL(!err || errno != EBADF)) {
412 perror("bpf_link_update expected EINVAL");
413 goto out_close_link;
414 }
415 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
416
417 prog3 = load_prog(BPF_PROG_TYPE_SOCKET_FILTER);
418 if (prog3 < 0)
419 goto out_close_link;
420
421 /* Expect failure when new prog FD type doesn't match */
422 errno = 0;
423 update_opts.flags = 0;
424 update_opts.old_prog_fd = 0;
425 err = bpf_link_update(link, prog3, &update_opts);
426 if (CHECK_FAIL(!err || errno != EINVAL))
427 perror("bpf_link_update expected EINVAL");
428 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
429
430 close(prog3);
431 out_close_link:
432 close(link);
433 CHECK_FAIL(prog_is_attached(netns));
434 }
435
test_link_update_netns_gone(int netns,int prog1,int prog2)436 static void test_link_update_netns_gone(int netns, int prog1, int prog2)
437 {
438 DECLARE_LIBBPF_OPTS(bpf_link_create_opts, create_opts);
439 DECLARE_LIBBPF_OPTS(bpf_link_update_opts, update_opts);
440 int err, link, old_net;
441
442 old_net = netns;
443 netns = unshare_net(old_net);
444 if (netns < 0)
445 return;
446
447 link = bpf_link_create(prog1, netns, BPF_FLOW_DISSECTOR, &create_opts);
448 if (CHECK_FAIL(link < 0)) {
449 perror("bpf_link_create(prog1)");
450 return;
451 }
452 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
453
454 close(netns);
455 err = setns(old_net, CLONE_NEWNET);
456 if (CHECK_FAIL(err)) {
457 perror("setns(CLONE_NEWNET)");
458 close(link);
459 return;
460 }
461
462 /* Expect failure when netns destroyed */
463 errno = 0;
464 update_opts.flags = 0;
465 update_opts.old_prog_fd = 0;
466 err = bpf_link_update(link, prog2, &update_opts);
467 if (CHECK_FAIL(!err || errno != ENOLINK))
468 perror("bpf_link_update");
469
470 close(link);
471 }
472
test_link_get_info(int netns,int prog1,int prog2)473 static void test_link_get_info(int netns, int prog1, int prog2)
474 {
475 DECLARE_LIBBPF_OPTS(bpf_link_create_opts, create_opts);
476 DECLARE_LIBBPF_OPTS(bpf_link_update_opts, update_opts);
477 struct bpf_link_info info = {};
478 struct stat netns_stat = {};
479 __u32 info_len, link_id;
480 int err, link, old_net;
481
482 old_net = netns;
483 netns = unshare_net(old_net);
484 if (netns < 0)
485 return;
486
487 err = fstat(netns, &netns_stat);
488 if (CHECK_FAIL(err)) {
489 perror("stat(netns)");
490 goto out_resetns;
491 }
492
493 link = bpf_link_create(prog1, netns, BPF_FLOW_DISSECTOR, &create_opts);
494 if (CHECK_FAIL(link < 0)) {
495 perror("bpf_link_create(prog1)");
496 goto out_resetns;
497 }
498
499 info_len = sizeof(info);
500 err = bpf_obj_get_info_by_fd(link, &info, &info_len);
501 if (CHECK_FAIL(err)) {
502 perror("bpf_obj_get_info");
503 goto out_unlink;
504 }
505 CHECK_FAIL(info_len != sizeof(info));
506
507 /* Expect link info to be sane and match prog and netns details */
508 CHECK_FAIL(info.type != BPF_LINK_TYPE_NETNS);
509 CHECK_FAIL(info.id == 0);
510 CHECK_FAIL(info.prog_id != query_prog_id(prog1));
511 CHECK_FAIL(info.netns.netns_ino != netns_stat.st_ino);
512 CHECK_FAIL(info.netns.attach_type != BPF_FLOW_DISSECTOR);
513
514 update_opts.flags = 0;
515 update_opts.old_prog_fd = 0;
516 err = bpf_link_update(link, prog2, &update_opts);
517 if (CHECK_FAIL(err)) {
518 perror("bpf_link_update(prog2)");
519 goto out_unlink;
520 }
521
522 link_id = info.id;
523 info_len = sizeof(info);
524 err = bpf_obj_get_info_by_fd(link, &info, &info_len);
525 if (CHECK_FAIL(err)) {
526 perror("bpf_obj_get_info");
527 goto out_unlink;
528 }
529 CHECK_FAIL(info_len != sizeof(info));
530
531 /* Expect no info change after update except in prog id */
532 CHECK_FAIL(info.type != BPF_LINK_TYPE_NETNS);
533 CHECK_FAIL(info.id != link_id);
534 CHECK_FAIL(info.prog_id != query_prog_id(prog2));
535 CHECK_FAIL(info.netns.netns_ino != netns_stat.st_ino);
536 CHECK_FAIL(info.netns.attach_type != BPF_FLOW_DISSECTOR);
537
538 /* Leave netns link is attached to and close last FD to it */
539 err = setns(old_net, CLONE_NEWNET);
540 if (CHECK_FAIL(err)) {
541 perror("setns(NEWNET)");
542 goto out_unlink;
543 }
544 close(netns);
545 old_net = -1;
546 netns = -1;
547
548 info_len = sizeof(info);
549 err = bpf_obj_get_info_by_fd(link, &info, &info_len);
550 if (CHECK_FAIL(err)) {
551 perror("bpf_obj_get_info");
552 goto out_unlink;
553 }
554 CHECK_FAIL(info_len != sizeof(info));
555
556 /* Expect netns_ino to change to 0 */
557 CHECK_FAIL(info.type != BPF_LINK_TYPE_NETNS);
558 CHECK_FAIL(info.id != link_id);
559 CHECK_FAIL(info.prog_id != query_prog_id(prog2));
560 CHECK_FAIL(info.netns.netns_ino != 0);
561 CHECK_FAIL(info.netns.attach_type != BPF_FLOW_DISSECTOR);
562
563 out_unlink:
564 close(link);
565 out_resetns:
566 if (old_net != -1)
567 setns(old_net, CLONE_NEWNET);
568 if (netns != -1)
569 close(netns);
570 }
571
run_tests(int netns)572 static void run_tests(int netns)
573 {
574 struct test {
575 const char *test_name;
576 void (*test_func)(int netns, int prog1, int prog2);
577 } tests[] = {
578 { "prog attach, prog attach",
579 test_prog_attach_prog_attach },
580 { "link create, link create",
581 test_link_create_link_create },
582 { "prog attach, link create",
583 test_prog_attach_link_create },
584 { "link create, prog attach",
585 test_link_create_prog_attach },
586 { "link create, prog detach",
587 test_link_create_prog_detach },
588 { "prog attach, detach, query",
589 test_prog_attach_detach_query },
590 { "link create, close, query",
591 test_link_create_close_query },
592 { "link update no old prog",
593 test_link_update_no_old_prog },
594 { "link update with replace old prog",
595 test_link_update_replace_old_prog },
596 { "link update with same prog",
597 test_link_update_same_prog },
598 { "link update invalid opts",
599 test_link_update_invalid_opts },
600 { "link update invalid prog",
601 test_link_update_invalid_prog },
602 { "link update netns gone",
603 test_link_update_netns_gone },
604 { "link get info",
605 test_link_get_info },
606 };
607 int i, progs[2] = { -1, -1 };
608 char test_name[80];
609
610 for (i = 0; i < ARRAY_SIZE(progs); i++) {
611 progs[i] = load_prog(BPF_PROG_TYPE_FLOW_DISSECTOR);
612 if (progs[i] < 0)
613 goto out_close;
614 }
615
616 for (i = 0; i < ARRAY_SIZE(tests); i++) {
617 snprintf(test_name, sizeof(test_name),
618 "flow dissector %s%s",
619 tests[i].test_name,
620 netns == init_net ? " (init_net)" : "");
621 if (test__start_subtest(test_name))
622 tests[i].test_func(netns, progs[0], progs[1]);
623 }
624 out_close:
625 for (i = 0; i < ARRAY_SIZE(progs); i++) {
626 if (progs[i] >= 0)
627 CHECK_FAIL(close(progs[i]));
628 }
629 }
630
serial_test_flow_dissector_reattach(void)631 void serial_test_flow_dissector_reattach(void)
632 {
633 int err, new_net, saved_net;
634
635 saved_net = open("/proc/self/ns/net", O_RDONLY);
636 if (CHECK_FAIL(saved_net < 0)) {
637 perror("open(/proc/self/ns/net");
638 return;
639 }
640
641 init_net = open("/proc/1/ns/net", O_RDONLY);
642 if (CHECK_FAIL(init_net < 0)) {
643 perror("open(/proc/1/ns/net)");
644 goto out_close;
645 }
646
647 err = setns(init_net, CLONE_NEWNET);
648 if (CHECK_FAIL(err)) {
649 perror("setns(/proc/1/ns/net)");
650 goto out_close;
651 }
652
653 if (prog_is_attached(init_net)) {
654 test__skip();
655 printf("Can't test with flow dissector attached to init_net\n");
656 goto out_setns;
657 }
658
659 /* First run tests in root network namespace */
660 run_tests(init_net);
661
662 /* Then repeat tests in a non-root namespace */
663 new_net = unshare_net(init_net);
664 if (new_net < 0)
665 goto out_setns;
666 run_tests(new_net);
667 close(new_net);
668
669 out_setns:
670 /* Move back to netns we started in. */
671 err = setns(saved_net, CLONE_NEWNET);
672 if (CHECK_FAIL(err))
673 perror("setns(/proc/self/ns/net)");
674
675 out_close:
676 close(init_net);
677 close(saved_net);
678 }
679