flow_dissector_reattach.c (18443B)
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 19static int init_net = -1; 20 21static __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 37static bool prog_is_attached(int netns) 38{ 39 return query_attached_prog_id(netns) > 0; 40} 41 42static 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 57static __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 72static 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 90static 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 115out_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 122static 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 147static 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 174static 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 197static 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 220static 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 241static 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 258static 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 283static 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 308static 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 333static 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 388out_close: 389 close(link); 390 CHECK_FAIL(prog_is_attached(netns)); 391} 392 393static 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); 431out_close_link: 432 close(link); 433 CHECK_FAIL(prog_is_attached(netns)); 434} 435 436static 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 473static 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 563out_unlink: 564 close(link); 565out_resetns: 566 if (old_net != -1) 567 setns(old_net, CLONE_NEWNET); 568 if (netns != -1) 569 close(netns); 570} 571 572static 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 } 624out_close: 625 for (i = 0; i < ARRAY_SIZE(progs); i++) { 626 if (progs[i] >= 0) 627 CHECK_FAIL(close(progs[i])); 628 } 629} 630 631void 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 669out_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 675out_close: 676 close(init_net); 677 close(saved_net); 678}