0001
0002
0003
0004
0005
0006 #define _GNU_SOURCE
0007 #include <errno.h>
0008 #include <fcntl.h>
0009 #include <sched.h>
0010 #include <stdbool.h>
0011 #include <sys/stat.h>
0012 #include <unistd.h>
0013
0014 #include <linux/bpf.h>
0015 #include <bpf/bpf.h>
0016
0017 #include "test_progs.h"
0018
0019 static int init_net = -1;
0020
0021 static __u32 query_attached_prog_id(int netns)
0022 {
0023 __u32 prog_ids[1] = {};
0024 __u32 prog_cnt = ARRAY_SIZE(prog_ids);
0025 int err;
0026
0027 err = bpf_prog_query(netns, BPF_FLOW_DISSECTOR, 0, NULL,
0028 prog_ids, &prog_cnt);
0029 if (CHECK_FAIL(err)) {
0030 perror("bpf_prog_query");
0031 return 0;
0032 }
0033
0034 return prog_cnt == 1 ? prog_ids[0] : 0;
0035 }
0036
0037 static bool prog_is_attached(int netns)
0038 {
0039 return query_attached_prog_id(netns) > 0;
0040 }
0041
0042 static int load_prog(enum bpf_prog_type type)
0043 {
0044 struct bpf_insn prog[] = {
0045 BPF_MOV64_IMM(BPF_REG_0, BPF_OK),
0046 BPF_EXIT_INSN(),
0047 };
0048 int fd;
0049
0050 fd = bpf_test_load_program(type, prog, ARRAY_SIZE(prog), "GPL", 0, NULL, 0);
0051 if (CHECK_FAIL(fd < 0))
0052 perror("bpf_test_load_program");
0053
0054 return fd;
0055 }
0056
0057 static __u32 query_prog_id(int prog)
0058 {
0059 struct bpf_prog_info info = {};
0060 __u32 info_len = sizeof(info);
0061 int err;
0062
0063 err = bpf_obj_get_info_by_fd(prog, &info, &info_len);
0064 if (CHECK_FAIL(err || info_len != sizeof(info))) {
0065 perror("bpf_obj_get_info_by_fd");
0066 return 0;
0067 }
0068
0069 return info.id;
0070 }
0071
0072 static int unshare_net(int old_net)
0073 {
0074 int err, new_net;
0075
0076 err = unshare(CLONE_NEWNET);
0077 if (CHECK_FAIL(err)) {
0078 perror("unshare(CLONE_NEWNET)");
0079 return -1;
0080 }
0081 new_net = open("/proc/self/ns/net", O_RDONLY);
0082 if (CHECK_FAIL(new_net < 0)) {
0083 perror("open(/proc/self/ns/net)");
0084 setns(old_net, CLONE_NEWNET);
0085 return -1;
0086 }
0087 return new_net;
0088 }
0089
0090 static void test_prog_attach_prog_attach(int netns, int prog1, int prog2)
0091 {
0092 int err;
0093
0094 err = bpf_prog_attach(prog1, 0, BPF_FLOW_DISSECTOR, 0);
0095 if (CHECK_FAIL(err)) {
0096 perror("bpf_prog_attach(prog1)");
0097 return;
0098 }
0099 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
0100
0101
0102 err = bpf_prog_attach(prog2, 0, BPF_FLOW_DISSECTOR, 0);
0103 if (CHECK_FAIL(err)) {
0104 perror("bpf_prog_attach(prog2) #1");
0105 goto out_detach;
0106 }
0107 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog2));
0108
0109
0110 err = bpf_prog_attach(prog2, 0, BPF_FLOW_DISSECTOR, 0);
0111 if (CHECK_FAIL(!err || errno != EINVAL))
0112 perror("bpf_prog_attach(prog2) #2");
0113 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog2));
0114
0115 out_detach:
0116 err = bpf_prog_detach2(prog2, 0, BPF_FLOW_DISSECTOR);
0117 if (CHECK_FAIL(err))
0118 perror("bpf_prog_detach");
0119 CHECK_FAIL(prog_is_attached(netns));
0120 }
0121
0122 static void test_link_create_link_create(int netns, int prog1, int prog2)
0123 {
0124 DECLARE_LIBBPF_OPTS(bpf_link_create_opts, opts);
0125 int link1, link2;
0126
0127 link1 = bpf_link_create(prog1, netns, BPF_FLOW_DISSECTOR, &opts);
0128 if (CHECK_FAIL(link < 0)) {
0129 perror("bpf_link_create(prog1)");
0130 return;
0131 }
0132 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
0133
0134
0135 errno = 0;
0136 link2 = bpf_link_create(prog2, netns, BPF_FLOW_DISSECTOR, &opts);
0137 if (CHECK_FAIL(link2 >= 0 || errno != E2BIG))
0138 perror("bpf_prog_attach(prog2) expected E2BIG");
0139 if (link2 >= 0)
0140 close(link2);
0141 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
0142
0143 close(link1);
0144 CHECK_FAIL(prog_is_attached(netns));
0145 }
0146
0147 static void test_prog_attach_link_create(int netns, int prog1, int prog2)
0148 {
0149 DECLARE_LIBBPF_OPTS(bpf_link_create_opts, opts);
0150 int err, link;
0151
0152 err = bpf_prog_attach(prog1, 0, BPF_FLOW_DISSECTOR, 0);
0153 if (CHECK_FAIL(err)) {
0154 perror("bpf_prog_attach(prog1)");
0155 return;
0156 }
0157 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
0158
0159
0160 errno = 0;
0161 link = bpf_link_create(prog2, netns, BPF_FLOW_DISSECTOR, &opts);
0162 if (CHECK_FAIL(link >= 0 || errno != EEXIST))
0163 perror("bpf_link_create(prog2) expected EEXIST");
0164 if (link >= 0)
0165 close(link);
0166 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
0167
0168 err = bpf_prog_detach2(prog1, 0, BPF_FLOW_DISSECTOR);
0169 if (CHECK_FAIL(err))
0170 perror("bpf_prog_detach");
0171 CHECK_FAIL(prog_is_attached(netns));
0172 }
0173
0174 static void test_link_create_prog_attach(int netns, int prog1, int prog2)
0175 {
0176 DECLARE_LIBBPF_OPTS(bpf_link_create_opts, opts);
0177 int err, link;
0178
0179 link = bpf_link_create(prog1, netns, BPF_FLOW_DISSECTOR, &opts);
0180 if (CHECK_FAIL(link < 0)) {
0181 perror("bpf_link_create(prog1)");
0182 return;
0183 }
0184 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
0185
0186
0187 errno = 0;
0188 err = bpf_prog_attach(prog2, 0, BPF_FLOW_DISSECTOR, 0);
0189 if (CHECK_FAIL(!err || errno != EEXIST))
0190 perror("bpf_prog_attach(prog2) expected EEXIST");
0191 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
0192
0193 close(link);
0194 CHECK_FAIL(prog_is_attached(netns));
0195 }
0196
0197 static void test_link_create_prog_detach(int netns, int prog1, int prog2)
0198 {
0199 DECLARE_LIBBPF_OPTS(bpf_link_create_opts, opts);
0200 int err, link;
0201
0202 link = bpf_link_create(prog1, netns, BPF_FLOW_DISSECTOR, &opts);
0203 if (CHECK_FAIL(link < 0)) {
0204 perror("bpf_link_create(prog1)");
0205 return;
0206 }
0207 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
0208
0209
0210 errno = 0;
0211 err = bpf_prog_detach2(prog1, 0, BPF_FLOW_DISSECTOR);
0212 if (CHECK_FAIL(!err || errno != EINVAL))
0213 perror("bpf_prog_detach expected EINVAL");
0214 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
0215
0216 close(link);
0217 CHECK_FAIL(prog_is_attached(netns));
0218 }
0219
0220 static void test_prog_attach_detach_query(int netns, int prog1, int prog2)
0221 {
0222 int err;
0223
0224 err = bpf_prog_attach(prog1, 0, BPF_FLOW_DISSECTOR, 0);
0225 if (CHECK_FAIL(err)) {
0226 perror("bpf_prog_attach(prog1)");
0227 return;
0228 }
0229 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
0230
0231 err = bpf_prog_detach2(prog1, 0, BPF_FLOW_DISSECTOR);
0232 if (CHECK_FAIL(err)) {
0233 perror("bpf_prog_detach");
0234 return;
0235 }
0236
0237
0238 CHECK_FAIL(prog_is_attached(netns));
0239 }
0240
0241 static void test_link_create_close_query(int netns, int prog1, int prog2)
0242 {
0243 DECLARE_LIBBPF_OPTS(bpf_link_create_opts, opts);
0244 int link;
0245
0246 link = bpf_link_create(prog1, netns, BPF_FLOW_DISSECTOR, &opts);
0247 if (CHECK_FAIL(link < 0)) {
0248 perror("bpf_link_create(prog1)");
0249 return;
0250 }
0251 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
0252
0253 close(link);
0254
0255 CHECK_FAIL(prog_is_attached(netns));
0256 }
0257
0258 static void test_link_update_no_old_prog(int netns, int prog1, int prog2)
0259 {
0260 DECLARE_LIBBPF_OPTS(bpf_link_create_opts, create_opts);
0261 DECLARE_LIBBPF_OPTS(bpf_link_update_opts, update_opts);
0262 int err, link;
0263
0264 link = bpf_link_create(prog1, netns, BPF_FLOW_DISSECTOR, &create_opts);
0265 if (CHECK_FAIL(link < 0)) {
0266 perror("bpf_link_create(prog1)");
0267 return;
0268 }
0269 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
0270
0271
0272 update_opts.flags = 0;
0273 update_opts.old_prog_fd = 0;
0274 err = bpf_link_update(link, prog2, &update_opts);
0275 if (CHECK_FAIL(err))
0276 perror("bpf_link_update");
0277 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog2));
0278
0279 close(link);
0280 CHECK_FAIL(prog_is_attached(netns));
0281 }
0282
0283 static void test_link_update_replace_old_prog(int netns, int prog1, int prog2)
0284 {
0285 DECLARE_LIBBPF_OPTS(bpf_link_create_opts, create_opts);
0286 DECLARE_LIBBPF_OPTS(bpf_link_update_opts, update_opts);
0287 int err, link;
0288
0289 link = bpf_link_create(prog1, netns, BPF_FLOW_DISSECTOR, &create_opts);
0290 if (CHECK_FAIL(link < 0)) {
0291 perror("bpf_link_create(prog1)");
0292 return;
0293 }
0294 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
0295
0296
0297 update_opts.flags = BPF_F_REPLACE;
0298 update_opts.old_prog_fd = prog1;
0299 err = bpf_link_update(link, prog2, &update_opts);
0300 if (CHECK_FAIL(err))
0301 perror("bpf_link_update");
0302 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog2));
0303
0304 close(link);
0305 CHECK_FAIL(prog_is_attached(netns));
0306 }
0307
0308 static void test_link_update_same_prog(int netns, int prog1, int prog2)
0309 {
0310 DECLARE_LIBBPF_OPTS(bpf_link_create_opts, create_opts);
0311 DECLARE_LIBBPF_OPTS(bpf_link_update_opts, update_opts);
0312 int err, link;
0313
0314 link = bpf_link_create(prog1, netns, BPF_FLOW_DISSECTOR, &create_opts);
0315 if (CHECK_FAIL(link < 0)) {
0316 perror("bpf_link_create(prog1)");
0317 return;
0318 }
0319 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
0320
0321
0322 update_opts.flags = 0;
0323 update_opts.old_prog_fd = 0;
0324 err = bpf_link_update(link, prog1, &update_opts);
0325 if (CHECK_FAIL(err))
0326 perror("bpf_link_update");
0327 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
0328
0329 close(link);
0330 CHECK_FAIL(prog_is_attached(netns));
0331 }
0332
0333 static void test_link_update_invalid_opts(int netns, int prog1, int prog2)
0334 {
0335 DECLARE_LIBBPF_OPTS(bpf_link_create_opts, create_opts);
0336 DECLARE_LIBBPF_OPTS(bpf_link_update_opts, update_opts);
0337 int err, link;
0338
0339 link = bpf_link_create(prog1, netns, BPF_FLOW_DISSECTOR, &create_opts);
0340 if (CHECK_FAIL(link < 0)) {
0341 perror("bpf_link_create(prog1)");
0342 return;
0343 }
0344 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
0345
0346
0347 errno = 0;
0348 update_opts.flags = 0;
0349 update_opts.old_prog_fd = prog1;
0350 err = bpf_link_update(link, prog2, &update_opts);
0351 if (CHECK_FAIL(!err || errno != EINVAL)) {
0352 perror("bpf_link_update expected EINVAL");
0353 goto out_close;
0354 }
0355 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
0356
0357
0358 errno = 0;
0359 update_opts.flags = BPF_F_REPLACE;
0360 update_opts.old_prog_fd = prog2;
0361 err = bpf_link_update(link, prog2, &update_opts);
0362 if (CHECK_FAIL(!err || errno != EPERM)) {
0363 perror("bpf_link_update expected EPERM");
0364 goto out_close;
0365 }
0366 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
0367
0368
0369 errno = 0;
0370 update_opts.flags = BPF_F_REPLACE;
0371 update_opts.old_prog_fd = -1;
0372 err = bpf_link_update(link, prog2, &update_opts);
0373 if (CHECK_FAIL(!err || errno != EBADF)) {
0374 perror("bpf_link_update expected EBADF");
0375 goto out_close;
0376 }
0377 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
0378
0379
0380 errno = 0;
0381 update_opts.flags = BPF_F_ALLOW_MULTI;
0382 update_opts.old_prog_fd = 0;
0383 err = bpf_link_update(link, prog2, &update_opts);
0384 if (CHECK_FAIL(!err || errno != EINVAL))
0385 perror("bpf_link_update expected EINVAL");
0386 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
0387
0388 out_close:
0389 close(link);
0390 CHECK_FAIL(prog_is_attached(netns));
0391 }
0392
0393 static void test_link_update_invalid_prog(int netns, int prog1, int prog2)
0394 {
0395 DECLARE_LIBBPF_OPTS(bpf_link_create_opts, create_opts);
0396 DECLARE_LIBBPF_OPTS(bpf_link_update_opts, update_opts);
0397 int err, link, prog3;
0398
0399 link = bpf_link_create(prog1, netns, BPF_FLOW_DISSECTOR, &create_opts);
0400 if (CHECK_FAIL(link < 0)) {
0401 perror("bpf_link_create(prog1)");
0402 return;
0403 }
0404 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
0405
0406
0407 errno = 0;
0408 update_opts.flags = 0;
0409 update_opts.old_prog_fd = 0;
0410 err = bpf_link_update(link, -1, &update_opts);
0411 if (CHECK_FAIL(!err || errno != EBADF)) {
0412 perror("bpf_link_update expected EINVAL");
0413 goto out_close_link;
0414 }
0415 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
0416
0417 prog3 = load_prog(BPF_PROG_TYPE_SOCKET_FILTER);
0418 if (prog3 < 0)
0419 goto out_close_link;
0420
0421
0422 errno = 0;
0423 update_opts.flags = 0;
0424 update_opts.old_prog_fd = 0;
0425 err = bpf_link_update(link, prog3, &update_opts);
0426 if (CHECK_FAIL(!err || errno != EINVAL))
0427 perror("bpf_link_update expected EINVAL");
0428 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
0429
0430 close(prog3);
0431 out_close_link:
0432 close(link);
0433 CHECK_FAIL(prog_is_attached(netns));
0434 }
0435
0436 static void test_link_update_netns_gone(int netns, int prog1, int prog2)
0437 {
0438 DECLARE_LIBBPF_OPTS(bpf_link_create_opts, create_opts);
0439 DECLARE_LIBBPF_OPTS(bpf_link_update_opts, update_opts);
0440 int err, link, old_net;
0441
0442 old_net = netns;
0443 netns = unshare_net(old_net);
0444 if (netns < 0)
0445 return;
0446
0447 link = bpf_link_create(prog1, netns, BPF_FLOW_DISSECTOR, &create_opts);
0448 if (CHECK_FAIL(link < 0)) {
0449 perror("bpf_link_create(prog1)");
0450 return;
0451 }
0452 CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
0453
0454 close(netns);
0455 err = setns(old_net, CLONE_NEWNET);
0456 if (CHECK_FAIL(err)) {
0457 perror("setns(CLONE_NEWNET)");
0458 close(link);
0459 return;
0460 }
0461
0462
0463 errno = 0;
0464 update_opts.flags = 0;
0465 update_opts.old_prog_fd = 0;
0466 err = bpf_link_update(link, prog2, &update_opts);
0467 if (CHECK_FAIL(!err || errno != ENOLINK))
0468 perror("bpf_link_update");
0469
0470 close(link);
0471 }
0472
0473 static void test_link_get_info(int netns, int prog1, int prog2)
0474 {
0475 DECLARE_LIBBPF_OPTS(bpf_link_create_opts, create_opts);
0476 DECLARE_LIBBPF_OPTS(bpf_link_update_opts, update_opts);
0477 struct bpf_link_info info = {};
0478 struct stat netns_stat = {};
0479 __u32 info_len, link_id;
0480 int err, link, old_net;
0481
0482 old_net = netns;
0483 netns = unshare_net(old_net);
0484 if (netns < 0)
0485 return;
0486
0487 err = fstat(netns, &netns_stat);
0488 if (CHECK_FAIL(err)) {
0489 perror("stat(netns)");
0490 goto out_resetns;
0491 }
0492
0493 link = bpf_link_create(prog1, netns, BPF_FLOW_DISSECTOR, &create_opts);
0494 if (CHECK_FAIL(link < 0)) {
0495 perror("bpf_link_create(prog1)");
0496 goto out_resetns;
0497 }
0498
0499 info_len = sizeof(info);
0500 err = bpf_obj_get_info_by_fd(link, &info, &info_len);
0501 if (CHECK_FAIL(err)) {
0502 perror("bpf_obj_get_info");
0503 goto out_unlink;
0504 }
0505 CHECK_FAIL(info_len != sizeof(info));
0506
0507
0508 CHECK_FAIL(info.type != BPF_LINK_TYPE_NETNS);
0509 CHECK_FAIL(info.id == 0);
0510 CHECK_FAIL(info.prog_id != query_prog_id(prog1));
0511 CHECK_FAIL(info.netns.netns_ino != netns_stat.st_ino);
0512 CHECK_FAIL(info.netns.attach_type != BPF_FLOW_DISSECTOR);
0513
0514 update_opts.flags = 0;
0515 update_opts.old_prog_fd = 0;
0516 err = bpf_link_update(link, prog2, &update_opts);
0517 if (CHECK_FAIL(err)) {
0518 perror("bpf_link_update(prog2)");
0519 goto out_unlink;
0520 }
0521
0522 link_id = info.id;
0523 info_len = sizeof(info);
0524 err = bpf_obj_get_info_by_fd(link, &info, &info_len);
0525 if (CHECK_FAIL(err)) {
0526 perror("bpf_obj_get_info");
0527 goto out_unlink;
0528 }
0529 CHECK_FAIL(info_len != sizeof(info));
0530
0531
0532 CHECK_FAIL(info.type != BPF_LINK_TYPE_NETNS);
0533 CHECK_FAIL(info.id != link_id);
0534 CHECK_FAIL(info.prog_id != query_prog_id(prog2));
0535 CHECK_FAIL(info.netns.netns_ino != netns_stat.st_ino);
0536 CHECK_FAIL(info.netns.attach_type != BPF_FLOW_DISSECTOR);
0537
0538
0539 err = setns(old_net, CLONE_NEWNET);
0540 if (CHECK_FAIL(err)) {
0541 perror("setns(NEWNET)");
0542 goto out_unlink;
0543 }
0544 close(netns);
0545 old_net = -1;
0546 netns = -1;
0547
0548 info_len = sizeof(info);
0549 err = bpf_obj_get_info_by_fd(link, &info, &info_len);
0550 if (CHECK_FAIL(err)) {
0551 perror("bpf_obj_get_info");
0552 goto out_unlink;
0553 }
0554 CHECK_FAIL(info_len != sizeof(info));
0555
0556
0557 CHECK_FAIL(info.type != BPF_LINK_TYPE_NETNS);
0558 CHECK_FAIL(info.id != link_id);
0559 CHECK_FAIL(info.prog_id != query_prog_id(prog2));
0560 CHECK_FAIL(info.netns.netns_ino != 0);
0561 CHECK_FAIL(info.netns.attach_type != BPF_FLOW_DISSECTOR);
0562
0563 out_unlink:
0564 close(link);
0565 out_resetns:
0566 if (old_net != -1)
0567 setns(old_net, CLONE_NEWNET);
0568 if (netns != -1)
0569 close(netns);
0570 }
0571
0572 static void run_tests(int netns)
0573 {
0574 struct test {
0575 const char *test_name;
0576 void (*test_func)(int netns, int prog1, int prog2);
0577 } tests[] = {
0578 { "prog attach, prog attach",
0579 test_prog_attach_prog_attach },
0580 { "link create, link create",
0581 test_link_create_link_create },
0582 { "prog attach, link create",
0583 test_prog_attach_link_create },
0584 { "link create, prog attach",
0585 test_link_create_prog_attach },
0586 { "link create, prog detach",
0587 test_link_create_prog_detach },
0588 { "prog attach, detach, query",
0589 test_prog_attach_detach_query },
0590 { "link create, close, query",
0591 test_link_create_close_query },
0592 { "link update no old prog",
0593 test_link_update_no_old_prog },
0594 { "link update with replace old prog",
0595 test_link_update_replace_old_prog },
0596 { "link update with same prog",
0597 test_link_update_same_prog },
0598 { "link update invalid opts",
0599 test_link_update_invalid_opts },
0600 { "link update invalid prog",
0601 test_link_update_invalid_prog },
0602 { "link update netns gone",
0603 test_link_update_netns_gone },
0604 { "link get info",
0605 test_link_get_info },
0606 };
0607 int i, progs[2] = { -1, -1 };
0608 char test_name[80];
0609
0610 for (i = 0; i < ARRAY_SIZE(progs); i++) {
0611 progs[i] = load_prog(BPF_PROG_TYPE_FLOW_DISSECTOR);
0612 if (progs[i] < 0)
0613 goto out_close;
0614 }
0615
0616 for (i = 0; i < ARRAY_SIZE(tests); i++) {
0617 snprintf(test_name, sizeof(test_name),
0618 "flow dissector %s%s",
0619 tests[i].test_name,
0620 netns == init_net ? " (init_net)" : "");
0621 if (test__start_subtest(test_name))
0622 tests[i].test_func(netns, progs[0], progs[1]);
0623 }
0624 out_close:
0625 for (i = 0; i < ARRAY_SIZE(progs); i++) {
0626 if (progs[i] >= 0)
0627 CHECK_FAIL(close(progs[i]));
0628 }
0629 }
0630
0631 void serial_test_flow_dissector_reattach(void)
0632 {
0633 int err, new_net, saved_net;
0634
0635 saved_net = open("/proc/self/ns/net", O_RDONLY);
0636 if (CHECK_FAIL(saved_net < 0)) {
0637 perror("open(/proc/self/ns/net");
0638 return;
0639 }
0640
0641 init_net = open("/proc/1/ns/net", O_RDONLY);
0642 if (CHECK_FAIL(init_net < 0)) {
0643 perror("open(/proc/1/ns/net)");
0644 goto out_close;
0645 }
0646
0647 err = setns(init_net, CLONE_NEWNET);
0648 if (CHECK_FAIL(err)) {
0649 perror("setns(/proc/1/ns/net)");
0650 goto out_close;
0651 }
0652
0653 if (prog_is_attached(init_net)) {
0654 test__skip();
0655 printf("Can't test with flow dissector attached to init_net\n");
0656 goto out_setns;
0657 }
0658
0659
0660 run_tests(init_net);
0661
0662
0663 new_net = unshare_net(init_net);
0664 if (new_net < 0)
0665 goto out_setns;
0666 run_tests(new_net);
0667 close(new_net);
0668
0669 out_setns:
0670
0671 err = setns(saved_net, CLONE_NEWNET);
0672 if (CHECK_FAIL(err))
0673 perror("setns(/proc/self/ns/net)");
0674
0675 out_close:
0676 close(init_net);
0677 close(saved_net);
0678 }