cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

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}