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