1 // SPDX-License-Identifier: GPL-2.0
3 #include <test_progs.h>
4 #include "cgroup_helpers.h"
6 static char bpf_log_buf[4096];
9 enum sock_create_test_error {
14 static struct sock_create_test {
16 const struct bpf_insn insns[64];
17 enum bpf_attach_type attach_type;
18 enum bpf_attach_type expected_attach_type;
26 enum sock_create_test_error error;
29 .descr = "AF_INET set priority",
31 /* r3 = 123 (priority) */
32 BPF_MOV64_IMM(BPF_REG_3, 123),
33 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_3,
34 offsetof(struct bpf_sock, priority)),
37 BPF_MOV64_IMM(BPF_REG_0, 1),
40 .expected_attach_type = BPF_CGROUP_INET_SOCK_CREATE,
41 .attach_type = BPF_CGROUP_INET_SOCK_CREATE,
46 .optname = SO_PRIORITY,
50 .descr = "AF_INET6 set priority",
52 /* r3 = 123 (priority) */
53 BPF_MOV64_IMM(BPF_REG_3, 123),
54 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_3,
55 offsetof(struct bpf_sock, priority)),
58 BPF_MOV64_IMM(BPF_REG_0, 1),
61 .expected_attach_type = BPF_CGROUP_INET_SOCK_CREATE,
62 .attach_type = BPF_CGROUP_INET_SOCK_CREATE,
67 .optname = SO_PRIORITY,
71 .descr = "AF_INET set mark",
73 BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
75 /* get uid of process */
76 BPF_EMIT_CALL(BPF_FUNC_get_current_uid_gid),
77 BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 0xffffffff),
79 /* if uid is 0, use given mark(666), else use uid as the mark */
80 BPF_MOV64_REG(BPF_REG_3, BPF_REG_0),
81 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
82 BPF_MOV64_IMM(BPF_REG_3, 666),
84 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
85 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_3,
86 offsetof(struct bpf_sock, mark)),
89 BPF_MOV64_IMM(BPF_REG_0, 1),
92 .expected_attach_type = BPF_CGROUP_INET_SOCK_CREATE,
93 .attach_type = BPF_CGROUP_INET_SOCK_CREATE,
102 .descr = "AF_INET6 set mark",
104 BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
106 /* get uid of process */
107 BPF_EMIT_CALL(BPF_FUNC_get_current_uid_gid),
108 BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 0xffffffff),
110 /* if uid is 0, use given mark(666), else use uid as the mark */
111 BPF_MOV64_REG(BPF_REG_3, BPF_REG_0),
112 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
113 BPF_MOV64_IMM(BPF_REG_3, 666),
115 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
116 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_3,
117 offsetof(struct bpf_sock, mark)),
120 BPF_MOV64_IMM(BPF_REG_0, 1),
123 .expected_attach_type = BPF_CGROUP_INET_SOCK_CREATE,
124 .attach_type = BPF_CGROUP_INET_SOCK_CREATE,
133 .descr = "AF_INET bound to iface",
135 /* r3 = 1 (lo interface) */
136 BPF_MOV64_IMM(BPF_REG_3, 1),
137 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_3,
138 offsetof(struct bpf_sock, bound_dev_if)),
141 BPF_MOV64_IMM(BPF_REG_0, 1),
144 .expected_attach_type = BPF_CGROUP_INET_SOCK_CREATE,
145 .attach_type = BPF_CGROUP_INET_SOCK_CREATE,
150 .optname = SO_BINDTOIFINDEX,
154 .descr = "AF_INET6 bound to iface",
156 /* r3 = 1 (lo interface) */
157 BPF_MOV64_IMM(BPF_REG_3, 1),
158 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_3,
159 offsetof(struct bpf_sock, bound_dev_if)),
162 BPF_MOV64_IMM(BPF_REG_0, 1),
165 .expected_attach_type = BPF_CGROUP_INET_SOCK_CREATE,
166 .attach_type = BPF_CGROUP_INET_SOCK_CREATE,
171 .optname = SO_BINDTOIFINDEX,
175 .descr = "block AF_INET, SOCK_DGRAM, IPPROTO_ICMP socket",
177 BPF_MOV64_IMM(BPF_REG_0, 1), /* r0 = verdict */
179 /* sock->family == AF_INET */
180 BPF_LDX_MEM(BPF_H, BPF_REG_2, BPF_REG_1,
181 offsetof(struct bpf_sock, family)),
182 BPF_JMP_IMM(BPF_JNE, BPF_REG_2, AF_INET, 5),
184 /* sock->type == SOCK_DGRAM */
185 BPF_LDX_MEM(BPF_H, BPF_REG_2, BPF_REG_1,
186 offsetof(struct bpf_sock, type)),
187 BPF_JMP_IMM(BPF_JNE, BPF_REG_2, SOCK_DGRAM, 3),
189 /* sock->protocol == IPPROTO_ICMP */
190 BPF_LDX_MEM(BPF_H, BPF_REG_2, BPF_REG_1,
191 offsetof(struct bpf_sock, protocol)),
192 BPF_JMP_IMM(BPF_JNE, BPF_REG_2, IPPROTO_ICMP, 1),
194 /* return 0 (block) */
195 BPF_MOV64_IMM(BPF_REG_0, 0),
198 .expected_attach_type = BPF_CGROUP_INET_SOCK_CREATE,
199 .attach_type = BPF_CGROUP_INET_SOCK_CREATE,
203 .protocol = IPPROTO_ICMP,
205 .error = DENY_CREATE,
208 .descr = "block AF_INET6, SOCK_DGRAM, IPPROTO_ICMPV6 socket",
210 BPF_MOV64_IMM(BPF_REG_0, 1), /* r0 = verdict */
212 /* sock->family == AF_INET6 */
213 BPF_LDX_MEM(BPF_H, BPF_REG_2, BPF_REG_1,
214 offsetof(struct bpf_sock, family)),
215 BPF_JMP_IMM(BPF_JNE, BPF_REG_2, AF_INET6, 5),
217 /* sock->type == SOCK_DGRAM */
218 BPF_LDX_MEM(BPF_H, BPF_REG_2, BPF_REG_1,
219 offsetof(struct bpf_sock, type)),
220 BPF_JMP_IMM(BPF_JNE, BPF_REG_2, SOCK_DGRAM, 3),
222 /* sock->protocol == IPPROTO_ICMPV6 */
223 BPF_LDX_MEM(BPF_H, BPF_REG_2, BPF_REG_1,
224 offsetof(struct bpf_sock, protocol)),
225 BPF_JMP_IMM(BPF_JNE, BPF_REG_2, IPPROTO_ICMPV6, 1),
227 /* return 0 (block) */
228 BPF_MOV64_IMM(BPF_REG_0, 0),
231 .expected_attach_type = BPF_CGROUP_INET_SOCK_CREATE,
232 .attach_type = BPF_CGROUP_INET_SOCK_CREATE,
236 .protocol = IPPROTO_ICMPV6,
238 .error = DENY_CREATE,
241 .descr = "load w/o expected_attach_type (compat mode)",
244 BPF_MOV64_IMM(BPF_REG_0, 1),
247 .expected_attach_type = 0,
248 .attach_type = BPF_CGROUP_INET_SOCK_CREATE,
255 static int load_prog(const struct bpf_insn *insns,
256 enum bpf_attach_type expected_attach_type)
258 LIBBPF_OPTS(bpf_prog_load_opts, opts,
259 .expected_attach_type = expected_attach_type,
261 .log_buf = bpf_log_buf,
262 .log_size = sizeof(bpf_log_buf),
264 int fd, insns_cnt = 0;
267 insns[insns_cnt].code != (BPF_JMP | BPF_EXIT);
272 fd = bpf_prog_load(BPF_PROG_TYPE_CGROUP_SOCK, NULL, "GPL", insns,
274 if (verbose && fd < 0)
275 fprintf(stderr, "%s\n", bpf_log_buf);
280 static int run_test(int cgroup_fd, struct sock_create_test *test)
282 int sock_fd, err, prog_fd, optval, ret = -1;
283 socklen_t optlen = sizeof(optval);
285 prog_fd = load_prog(test->insns, test->expected_attach_type);
287 log_err("Failed to load BPF program");
291 err = bpf_prog_attach(prog_fd, cgroup_fd, test->attach_type, 0);
293 log_err("Failed to attach BPF program");
297 sock_fd = socket(test->domain, test->type, test->protocol);
299 if (test->error == DENY_CREATE)
302 log_err("Failed to create socket");
308 err = getsockopt(sock_fd, SOL_SOCKET, test->optname, &optval, &optlen);
310 log_err("Failed to call getsockopt");
314 if (optval != test->optval) {
316 log_err("getsockopt returned unexpected optval");
321 ret = test->error != OK;
326 bpf_prog_detach2(prog_fd, cgroup_fd, test->attach_type);
332 void test_sock_create(void)
336 cgroup_fd = test__join_cgroup("/sock_create");
337 if (!ASSERT_GE(cgroup_fd, 0, "join_cgroup"))
340 for (i = 0; i < ARRAY_SIZE(tests); i++) {
341 if (!test__start_subtest(tests[i].descr))
344 ASSERT_OK(run_test(cgroup_fd, &tests[i]), tests[i].descr);