1 // SPDX-License-Identifier: GPL-2.0
3 * Test that the flow_dissector program can be updated with a single
4 * syscall by attaching a new program that replaces the existing one.
6 * Corner case - the same program cannot be attached twice.
16 #include <linux/bpf.h>
19 #include "test_progs.h"
21 static bool is_attached(int netns
)
26 err
= bpf_prog_query(netns
, BPF_FLOW_DISSECTOR
, 0, NULL
, NULL
, &cnt
);
27 if (CHECK_FAIL(err
)) {
28 perror("bpf_prog_query");
29 return true; /* fail-safe */
35 static int load_prog(void)
37 struct bpf_insn prog
[] = {
38 BPF_MOV64_IMM(BPF_REG_0
, BPF_OK
),
43 fd
= bpf_load_program(BPF_PROG_TYPE_FLOW_DISSECTOR
, prog
,
44 ARRAY_SIZE(prog
), "GPL", 0, NULL
, 0);
45 if (CHECK_FAIL(fd
< 0))
46 perror("bpf_load_program");
51 static void do_flow_dissector_reattach(void)
53 int prog_fd
[2] = { -1, -1 };
56 prog_fd
[0] = load_prog();
60 prog_fd
[1] = load_prog();
64 err
= bpf_prog_attach(prog_fd
[0], 0, BPF_FLOW_DISSECTOR
, 0);
65 if (CHECK_FAIL(err
)) {
66 perror("bpf_prog_attach-0");
70 /* Expect success when attaching a different program */
71 err
= bpf_prog_attach(prog_fd
[1], 0, BPF_FLOW_DISSECTOR
, 0);
72 if (CHECK_FAIL(err
)) {
73 perror("bpf_prog_attach-1");
77 /* Expect failure when attaching the same program twice */
78 err
= bpf_prog_attach(prog_fd
[1], 0, BPF_FLOW_DISSECTOR
, 0);
79 if (CHECK_FAIL(!err
|| errno
!= EINVAL
))
80 perror("bpf_prog_attach-2");
83 err
= bpf_prog_detach(0, BPF_FLOW_DISSECTOR
);
85 perror("bpf_prog_detach");
92 void test_flow_dissector_reattach(void)
94 int init_net
, self_net
, err
;
96 self_net
= open("/proc/self/ns/net", O_RDONLY
);
97 if (CHECK_FAIL(self_net
< 0)) {
98 perror("open(/proc/self/ns/net");
102 init_net
= open("/proc/1/ns/net", O_RDONLY
);
103 if (CHECK_FAIL(init_net
< 0)) {
104 perror("open(/proc/1/ns/net)");
108 err
= setns(init_net
, CLONE_NEWNET
);
109 if (CHECK_FAIL(err
)) {
110 perror("setns(/proc/1/ns/net)");
114 if (is_attached(init_net
)) {
116 printf("Can't test with flow dissector attached to init_net\n");
120 /* First run tests in root network namespace */
121 do_flow_dissector_reattach();
123 /* Then repeat tests in a non-root namespace */
124 err
= unshare(CLONE_NEWNET
);
125 if (CHECK_FAIL(err
)) {
126 perror("unshare(CLONE_NEWNET)");
129 do_flow_dissector_reattach();
132 /* Move back to netns we started in. */
133 err
= setns(self_net
, CLONE_NEWNET
);
135 perror("setns(/proc/self/ns/net)");