1 // SPDX-License-Identifier: GPL-2.0
2 #include <test_progs.h>
3 #include "cgroup_helpers.h"
5 static int prog_attach(struct bpf_object
*obj
, int cgroup_fd
, const char *title
)
7 enum bpf_attach_type attach_type
;
8 enum bpf_prog_type prog_type
;
9 struct bpf_program
*prog
;
12 err
= libbpf_prog_type_by_name(title
, &prog_type
, &attach_type
);
14 log_err("Failed to deduct types for %s BPF program", title
);
18 prog
= bpf_object__find_program_by_title(obj
, title
);
20 log_err("Failed to find %s BPF program", title
);
24 err
= bpf_prog_attach(bpf_program__fd(prog
), cgroup_fd
,
25 attach_type
, BPF_F_ALLOW_MULTI
);
27 log_err("Failed to attach %s BPF program", title
);
34 static int prog_detach(struct bpf_object
*obj
, int cgroup_fd
, const char *title
)
36 enum bpf_attach_type attach_type
;
37 enum bpf_prog_type prog_type
;
38 struct bpf_program
*prog
;
41 err
= libbpf_prog_type_by_name(title
, &prog_type
, &attach_type
);
45 prog
= bpf_object__find_program_by_title(obj
, title
);
49 err
= bpf_prog_detach2(bpf_program__fd(prog
), cgroup_fd
,
57 static int run_getsockopt_test(struct bpf_object
*obj
, int cg_parent
,
58 int cg_child
, int sock_fd
)
64 /* Set IP_TOS to the expected value (0x80). */
67 err
= setsockopt(sock_fd
, SOL_IP
, IP_TOS
, &buf
, 1);
69 log_err("Failed to call setsockopt(IP_TOS)");
75 err
= getsockopt(sock_fd
, SOL_IP
, IP_TOS
, &buf
, &optlen
);
77 log_err("Failed to call getsockopt(IP_TOS)");
82 log_err("Unexpected getsockopt 0x%x != 0x80 without BPF", buf
);
87 /* Attach child program and make sure it returns new value:
89 * - child: 0x80 -> 0x90
92 err
= prog_attach(obj
, cg_child
, "cgroup/getsockopt/child");
98 err
= getsockopt(sock_fd
, SOL_IP
, IP_TOS
, &buf
, &optlen
);
100 log_err("Failed to call getsockopt(IP_TOS)");
105 log_err("Unexpected getsockopt 0x%x != 0x90", buf
);
110 /* Attach parent program and make sure it returns new value:
112 * - child: 0x80 -> 0x90
113 * - parent: 0x90 -> 0xA0
116 err
= prog_attach(obj
, cg_parent
, "cgroup/getsockopt/parent");
122 err
= getsockopt(sock_fd
, SOL_IP
, IP_TOS
, &buf
, &optlen
);
124 log_err("Failed to call getsockopt(IP_TOS)");
129 log_err("Unexpected getsockopt 0x%x != 0xA0", buf
);
134 /* Setting unexpected initial sockopt should return EPERM:
136 * - child: unexpected 0x40, EPERM
137 * - parent: unexpected 0x40, EPERM
141 err
= setsockopt(sock_fd
, SOL_IP
, IP_TOS
, &buf
, 1);
143 log_err("Failed to call setsockopt(IP_TOS)");
149 err
= getsockopt(sock_fd
, SOL_IP
, IP_TOS
, &buf
, &optlen
);
151 log_err("Unexpected success from getsockopt(IP_TOS)");
155 /* Detach child program and make sure we still get EPERM:
157 * - parent: unexpected 0x40, EPERM
160 err
= prog_detach(obj
, cg_child
, "cgroup/getsockopt/child");
162 log_err("Failed to detach child program");
168 err
= getsockopt(sock_fd
, SOL_IP
, IP_TOS
, &buf
, &optlen
);
170 log_err("Unexpected success from getsockopt(IP_TOS)");
174 /* Set initial value to the one the parent program expects:
176 * - parent: 0x90 -> 0xA0
180 err
= setsockopt(sock_fd
, SOL_IP
, IP_TOS
, &buf
, 1);
182 log_err("Failed to call setsockopt(IP_TOS)");
188 err
= getsockopt(sock_fd
, SOL_IP
, IP_TOS
, &buf
, &optlen
);
190 log_err("Failed to call getsockopt(IP_TOS)");
195 log_err("Unexpected getsockopt 0x%x != 0xA0", buf
);
201 prog_detach(obj
, cg_child
, "cgroup/getsockopt/child");
202 prog_detach(obj
, cg_parent
, "cgroup/getsockopt/parent");
207 static int run_setsockopt_test(struct bpf_object
*obj
, int cg_parent
,
208 int cg_child
, int sock_fd
)
214 /* Set IP_TOS to the expected value (0x80). */
217 err
= setsockopt(sock_fd
, SOL_IP
, IP_TOS
, &buf
, 1);
219 log_err("Failed to call setsockopt(IP_TOS)");
225 err
= getsockopt(sock_fd
, SOL_IP
, IP_TOS
, &buf
, &optlen
);
227 log_err("Failed to call getsockopt(IP_TOS)");
232 log_err("Unexpected getsockopt 0x%x != 0x80 without BPF", buf
);
237 /* Attach child program and make sure it adds 0x10. */
239 err
= prog_attach(obj
, cg_child
, "cgroup/setsockopt");
244 err
= setsockopt(sock_fd
, SOL_IP
, IP_TOS
, &buf
, 1);
246 log_err("Failed to call setsockopt(IP_TOS)");
252 err
= getsockopt(sock_fd
, SOL_IP
, IP_TOS
, &buf
, &optlen
);
254 log_err("Failed to call getsockopt(IP_TOS)");
258 if (buf
!= 0x80 + 0x10) {
259 log_err("Unexpected getsockopt 0x%x != 0x80 + 0x10", buf
);
264 /* Attach parent program and make sure it adds another 0x10. */
266 err
= prog_attach(obj
, cg_parent
, "cgroup/setsockopt");
271 err
= setsockopt(sock_fd
, SOL_IP
, IP_TOS
, &buf
, 1);
273 log_err("Failed to call setsockopt(IP_TOS)");
279 err
= getsockopt(sock_fd
, SOL_IP
, IP_TOS
, &buf
, &optlen
);
281 log_err("Failed to call getsockopt(IP_TOS)");
285 if (buf
!= 0x80 + 2 * 0x10) {
286 log_err("Unexpected getsockopt 0x%x != 0x80 + 2 * 0x10", buf
);
292 prog_detach(obj
, cg_child
, "cgroup/setsockopt");
293 prog_detach(obj
, cg_parent
, "cgroup/setsockopt");
298 void test_sockopt_multi(void)
300 struct bpf_prog_load_attr attr
= {
301 .file
= "./sockopt_multi.o",
303 int cg_parent
= -1, cg_child
= -1;
304 struct bpf_object
*obj
= NULL
;
309 cg_parent
= test__join_cgroup("/parent");
310 if (CHECK_FAIL(cg_parent
< 0))
313 cg_child
= test__join_cgroup("/parent/child");
314 if (CHECK_FAIL(cg_child
< 0))
317 err
= bpf_prog_load_xattr(&attr
, &obj
, &ignored
);
321 sock_fd
= socket(AF_INET
, SOCK_STREAM
, 0);
322 if (CHECK_FAIL(sock_fd
< 0))
325 CHECK_FAIL(run_getsockopt_test(obj
, cg_parent
, cg_child
, sock_fd
));
326 CHECK_FAIL(run_setsockopt_test(obj
, cg_parent
, cg_child
, sock_fd
));
330 bpf_object__close(obj
);