Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Tests for attaching, detaching, and replacing flow_dissector BPF program.
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     /* Expect success when attaching a different program */
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     /* Expect failure when attaching the same program twice */
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     /* Expect failure creating link when another link exists */
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     /* Expect failure creating link when prog attached */
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     /* Expect failure attaching prog when link exists */
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     /* Expect failure detaching prog when link exists */
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     /* Expect no prog attached after successful detach */
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     /* Expect no prog attached after closing last link FD */
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     /* Expect success replacing the prog when old prog not specified */
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     /* Expect success F_REPLACE and old prog specified to succeed */
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     /* Expect success updating the prog with the same one */
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     /* Expect update to fail w/ old prog FD but w/o F_REPLACE*/
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     /* Expect update to fail on old prog FD mismatch */
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     /* Expect update to fail for invalid old prog FD */
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     /* Expect update to fail with invalid flags */
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     /* Expect failure when new prog FD is not valid */
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     /* Expect failure when new prog FD type doesn't match */
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     /* Expect failure when netns destroyed */
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     /* Expect link info to be sane and match prog and netns details */
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     /* Expect no info change after update except in prog id */
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     /* Leave netns link is attached to and close last FD to it */
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     /* Expect netns_ino to change to 0 */
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     /* First run tests in root network namespace */
0660     run_tests(init_net);
0661 
0662     /* Then repeat tests in a non-root namespace */
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     /* Move back to netns we started in. */
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 }