xref: /linux/tools/testing/selftests/bpf/prog_tests/sock_create.c (revision 25768de50b1f2dbb6ea44bd5148a87fe2c9c3688)
1ec6c4be0SDaniel T. Lee // SPDX-License-Identifier: GPL-2.0
2ec6c4be0SDaniel T. Lee #include <linux/bpf.h>
3ec6c4be0SDaniel T. Lee #include <test_progs.h>
4ec6c4be0SDaniel T. Lee #include "cgroup_helpers.h"
5ec6c4be0SDaniel T. Lee 
6ec6c4be0SDaniel T. Lee static char bpf_log_buf[4096];
7ec6c4be0SDaniel T. Lee static bool verbose;
8ec6c4be0SDaniel T. Lee 
964a4658dSDaniel T. Lee enum sock_create_test_error {
1064a4658dSDaniel T. Lee 	OK = 0,
1164a4658dSDaniel T. Lee 	DENY_CREATE,
1264a4658dSDaniel T. Lee };
1364a4658dSDaniel T. Lee 
14ec6c4be0SDaniel T. Lee static struct sock_create_test {
15ec6c4be0SDaniel T. Lee 	const char			*descr;
16ec6c4be0SDaniel T. Lee 	const struct bpf_insn		insns[64];
17ec6c4be0SDaniel T. Lee 	enum bpf_attach_type		attach_type;
18ec6c4be0SDaniel T. Lee 	enum bpf_attach_type		expected_attach_type;
19ec6c4be0SDaniel T. Lee 
20ec6c4be0SDaniel T. Lee 	int				domain;
21ec6c4be0SDaniel T. Lee 	int				type;
2264a4658dSDaniel T. Lee 	int				protocol;
23ec6c4be0SDaniel T. Lee 
24ec6c4be0SDaniel T. Lee 	int				optname;
25ec6c4be0SDaniel T. Lee 	int				optval;
2664a4658dSDaniel T. Lee 	enum sock_create_test_error	error;
27ec6c4be0SDaniel T. Lee } tests[] = {
28ec6c4be0SDaniel T. Lee 	{
29ec6c4be0SDaniel T. Lee 		.descr = "AF_INET set priority",
30ec6c4be0SDaniel T. Lee 		.insns = {
31ec6c4be0SDaniel T. Lee 			/* r3 = 123 (priority) */
32ec6c4be0SDaniel T. Lee 			BPF_MOV64_IMM(BPF_REG_3, 123),
33ec6c4be0SDaniel T. Lee 			BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_3,
34ec6c4be0SDaniel T. Lee 				    offsetof(struct bpf_sock, priority)),
35ec6c4be0SDaniel T. Lee 
36ec6c4be0SDaniel T. Lee 			/* return 1 */
37ec6c4be0SDaniel T. Lee 			BPF_MOV64_IMM(BPF_REG_0, 1),
38ec6c4be0SDaniel T. Lee 			BPF_EXIT_INSN(),
39ec6c4be0SDaniel T. Lee 		},
40ec6c4be0SDaniel T. Lee 		.expected_attach_type = BPF_CGROUP_INET_SOCK_CREATE,
41ec6c4be0SDaniel T. Lee 		.attach_type = BPF_CGROUP_INET_SOCK_CREATE,
42ec6c4be0SDaniel T. Lee 
43ec6c4be0SDaniel T. Lee 		.domain = AF_INET,
44ec6c4be0SDaniel T. Lee 		.type = SOCK_DGRAM,
45ec6c4be0SDaniel T. Lee 
46ec6c4be0SDaniel T. Lee 		.optname = SO_PRIORITY,
47ec6c4be0SDaniel T. Lee 		.optval = 123,
48ec6c4be0SDaniel T. Lee 	},
49ec6c4be0SDaniel T. Lee 	{
50ec6c4be0SDaniel T. Lee 		.descr = "AF_INET6 set priority",
51ec6c4be0SDaniel T. Lee 		.insns = {
52ec6c4be0SDaniel T. Lee 			/* r3 = 123 (priority) */
53ec6c4be0SDaniel T. Lee 			BPF_MOV64_IMM(BPF_REG_3, 123),
54ec6c4be0SDaniel T. Lee 			BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_3,
55ec6c4be0SDaniel T. Lee 				    offsetof(struct bpf_sock, priority)),
56ec6c4be0SDaniel T. Lee 
57ec6c4be0SDaniel T. Lee 			/* return 1 */
58ec6c4be0SDaniel T. Lee 			BPF_MOV64_IMM(BPF_REG_0, 1),
59ec6c4be0SDaniel T. Lee 			BPF_EXIT_INSN(),
60ec6c4be0SDaniel T. Lee 		},
61ec6c4be0SDaniel T. Lee 		.expected_attach_type = BPF_CGROUP_INET_SOCK_CREATE,
62ec6c4be0SDaniel T. Lee 		.attach_type = BPF_CGROUP_INET_SOCK_CREATE,
63ec6c4be0SDaniel T. Lee 
64ec6c4be0SDaniel T. Lee 		.domain = AF_INET6,
65ec6c4be0SDaniel T. Lee 		.type = SOCK_DGRAM,
66ec6c4be0SDaniel T. Lee 
67ec6c4be0SDaniel T. Lee 		.optname = SO_PRIORITY,
68ec6c4be0SDaniel T. Lee 		.optval = 123,
69ec6c4be0SDaniel T. Lee 	},
70ec6c4be0SDaniel T. Lee 	{
71ec6c4be0SDaniel T. Lee 		.descr = "AF_INET set mark",
72ec6c4be0SDaniel T. Lee 		.insns = {
73ec6c4be0SDaniel T. Lee 			BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
74ec6c4be0SDaniel T. Lee 
75ec6c4be0SDaniel T. Lee 			/* get uid of process */
76ec6c4be0SDaniel T. Lee 			BPF_EMIT_CALL(BPF_FUNC_get_current_uid_gid),
77ec6c4be0SDaniel T. Lee 			BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 0xffffffff),
78ec6c4be0SDaniel T. Lee 
79ec6c4be0SDaniel T. Lee 			/* if uid is 0, use given mark(666), else use uid as the mark */
80ec6c4be0SDaniel T. Lee 			BPF_MOV64_REG(BPF_REG_3, BPF_REG_0),
81ec6c4be0SDaniel T. Lee 			BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
82ec6c4be0SDaniel T. Lee 			BPF_MOV64_IMM(BPF_REG_3, 666),
83ec6c4be0SDaniel T. Lee 
84ec6c4be0SDaniel T. Lee 			BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
85ec6c4be0SDaniel T. Lee 			BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_3,
86ec6c4be0SDaniel T. Lee 				    offsetof(struct bpf_sock, mark)),
87ec6c4be0SDaniel T. Lee 
88ec6c4be0SDaniel T. Lee 			/* return 1 */
89ec6c4be0SDaniel T. Lee 			BPF_MOV64_IMM(BPF_REG_0, 1),
90ec6c4be0SDaniel T. Lee 			BPF_EXIT_INSN(),
91ec6c4be0SDaniel T. Lee 		},
92ec6c4be0SDaniel T. Lee 		.expected_attach_type = BPF_CGROUP_INET_SOCK_CREATE,
93ec6c4be0SDaniel T. Lee 		.attach_type = BPF_CGROUP_INET_SOCK_CREATE,
94ec6c4be0SDaniel T. Lee 
95ec6c4be0SDaniel T. Lee 		.domain = AF_INET,
96ec6c4be0SDaniel T. Lee 		.type = SOCK_DGRAM,
97ec6c4be0SDaniel T. Lee 
98ec6c4be0SDaniel T. Lee 		.optname = SO_MARK,
99ec6c4be0SDaniel T. Lee 		.optval = 666,
100ec6c4be0SDaniel T. Lee 	},
101ec6c4be0SDaniel T. Lee 	{
102ec6c4be0SDaniel T. Lee 		.descr = "AF_INET6 set mark",
103ec6c4be0SDaniel T. Lee 		.insns = {
104ec6c4be0SDaniel T. Lee 			BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
105ec6c4be0SDaniel T. Lee 
106ec6c4be0SDaniel T. Lee 			/* get uid of process */
107ec6c4be0SDaniel T. Lee 			BPF_EMIT_CALL(BPF_FUNC_get_current_uid_gid),
108ec6c4be0SDaniel T. Lee 			BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 0xffffffff),
109ec6c4be0SDaniel T. Lee 
110ec6c4be0SDaniel T. Lee 			/* if uid is 0, use given mark(666), else use uid as the mark */
111ec6c4be0SDaniel T. Lee 			BPF_MOV64_REG(BPF_REG_3, BPF_REG_0),
112ec6c4be0SDaniel T. Lee 			BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
113ec6c4be0SDaniel T. Lee 			BPF_MOV64_IMM(BPF_REG_3, 666),
114ec6c4be0SDaniel T. Lee 
115ec6c4be0SDaniel T. Lee 			BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
116ec6c4be0SDaniel T. Lee 			BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_3,
117ec6c4be0SDaniel T. Lee 				    offsetof(struct bpf_sock, mark)),
118ec6c4be0SDaniel T. Lee 
119ec6c4be0SDaniel T. Lee 			/* return 1 */
120ec6c4be0SDaniel T. Lee 			BPF_MOV64_IMM(BPF_REG_0, 1),
121ec6c4be0SDaniel T. Lee 			BPF_EXIT_INSN(),
122ec6c4be0SDaniel T. Lee 		},
123ec6c4be0SDaniel T. Lee 		.expected_attach_type = BPF_CGROUP_INET_SOCK_CREATE,
124ec6c4be0SDaniel T. Lee 		.attach_type = BPF_CGROUP_INET_SOCK_CREATE,
125ec6c4be0SDaniel T. Lee 
126ec6c4be0SDaniel T. Lee 		.domain = AF_INET6,
127ec6c4be0SDaniel T. Lee 		.type = SOCK_DGRAM,
128ec6c4be0SDaniel T. Lee 
129ec6c4be0SDaniel T. Lee 		.optname = SO_MARK,
130ec6c4be0SDaniel T. Lee 		.optval = 666,
131ec6c4be0SDaniel T. Lee 	},
132ec6c4be0SDaniel T. Lee 	{
133ec6c4be0SDaniel T. Lee 		.descr = "AF_INET bound to iface",
134ec6c4be0SDaniel T. Lee 		.insns = {
135ec6c4be0SDaniel T. Lee 			/* r3 = 1 (lo interface) */
136ec6c4be0SDaniel T. Lee 			BPF_MOV64_IMM(BPF_REG_3, 1),
137ec6c4be0SDaniel T. Lee 			BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_3,
138ec6c4be0SDaniel T. Lee 				    offsetof(struct bpf_sock, bound_dev_if)),
139ec6c4be0SDaniel T. Lee 
140ec6c4be0SDaniel T. Lee 			/* return 1 */
141ec6c4be0SDaniel T. Lee 			BPF_MOV64_IMM(BPF_REG_0, 1),
142ec6c4be0SDaniel T. Lee 			BPF_EXIT_INSN(),
143ec6c4be0SDaniel T. Lee 		},
144ec6c4be0SDaniel T. Lee 		.expected_attach_type = BPF_CGROUP_INET_SOCK_CREATE,
145ec6c4be0SDaniel T. Lee 		.attach_type = BPF_CGROUP_INET_SOCK_CREATE,
146ec6c4be0SDaniel T. Lee 
147ec6c4be0SDaniel T. Lee 		.domain = AF_INET,
148ec6c4be0SDaniel T. Lee 		.type = SOCK_DGRAM,
149ec6c4be0SDaniel T. Lee 
150ec6c4be0SDaniel T. Lee 		.optname = SO_BINDTOIFINDEX,
151ec6c4be0SDaniel T. Lee 		.optval = 1,
152ec6c4be0SDaniel T. Lee 	},
153ec6c4be0SDaniel T. Lee 	{
154ec6c4be0SDaniel T. Lee 		.descr = "AF_INET6 bound to iface",
155ec6c4be0SDaniel T. Lee 		.insns = {
156ec6c4be0SDaniel T. Lee 			/* r3 = 1 (lo interface) */
157ec6c4be0SDaniel T. Lee 			BPF_MOV64_IMM(BPF_REG_3, 1),
158ec6c4be0SDaniel T. Lee 			BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_3,
159ec6c4be0SDaniel T. Lee 				    offsetof(struct bpf_sock, bound_dev_if)),
160ec6c4be0SDaniel T. Lee 
161ec6c4be0SDaniel T. Lee 			/* return 1 */
162ec6c4be0SDaniel T. Lee 			BPF_MOV64_IMM(BPF_REG_0, 1),
163ec6c4be0SDaniel T. Lee 			BPF_EXIT_INSN(),
164ec6c4be0SDaniel T. Lee 		},
165ec6c4be0SDaniel T. Lee 		.expected_attach_type = BPF_CGROUP_INET_SOCK_CREATE,
166ec6c4be0SDaniel T. Lee 		.attach_type = BPF_CGROUP_INET_SOCK_CREATE,
167ec6c4be0SDaniel T. Lee 
168ec6c4be0SDaniel T. Lee 		.domain = AF_INET6,
169ec6c4be0SDaniel T. Lee 		.type = SOCK_DGRAM,
170ec6c4be0SDaniel T. Lee 
171ec6c4be0SDaniel T. Lee 		.optname = SO_BINDTOIFINDEX,
172ec6c4be0SDaniel T. Lee 		.optval = 1,
173ec6c4be0SDaniel T. Lee 	},
17464a4658dSDaniel T. Lee 	{
17564a4658dSDaniel T. Lee 		.descr = "block AF_INET, SOCK_DGRAM, IPPROTO_ICMP socket",
17664a4658dSDaniel T. Lee 		.insns = {
17764a4658dSDaniel T. Lee 			BPF_MOV64_IMM(BPF_REG_0, 1),	/* r0 = verdict */
17864a4658dSDaniel T. Lee 
17964a4658dSDaniel T. Lee 			/* sock->family == AF_INET */
18064a4658dSDaniel T. Lee 			BPF_LDX_MEM(BPF_H, BPF_REG_2, BPF_REG_1,
18164a4658dSDaniel T. Lee 				    offsetof(struct bpf_sock, family)),
18264a4658dSDaniel T. Lee 			BPF_JMP_IMM(BPF_JNE, BPF_REG_2, AF_INET, 5),
18364a4658dSDaniel T. Lee 
18464a4658dSDaniel T. Lee 			/* sock->type == SOCK_DGRAM */
18564a4658dSDaniel T. Lee 			BPF_LDX_MEM(BPF_H, BPF_REG_2, BPF_REG_1,
18664a4658dSDaniel T. Lee 				    offsetof(struct bpf_sock, type)),
18764a4658dSDaniel T. Lee 			BPF_JMP_IMM(BPF_JNE, BPF_REG_2, SOCK_DGRAM, 3),
18864a4658dSDaniel T. Lee 
18964a4658dSDaniel T. Lee 			/* sock->protocol == IPPROTO_ICMP */
19064a4658dSDaniel T. Lee 			BPF_LDX_MEM(BPF_H, BPF_REG_2, BPF_REG_1,
19164a4658dSDaniel T. Lee 				    offsetof(struct bpf_sock, protocol)),
19264a4658dSDaniel T. Lee 			BPF_JMP_IMM(BPF_JNE, BPF_REG_2, IPPROTO_ICMP, 1),
19364a4658dSDaniel T. Lee 
19464a4658dSDaniel T. Lee 			/* return 0 (block) */
19564a4658dSDaniel T. Lee 			BPF_MOV64_IMM(BPF_REG_0, 0),
19664a4658dSDaniel T. Lee 			BPF_EXIT_INSN(),
19764a4658dSDaniel T. Lee 		},
19864a4658dSDaniel T. Lee 		.expected_attach_type = BPF_CGROUP_INET_SOCK_CREATE,
19964a4658dSDaniel T. Lee 		.attach_type = BPF_CGROUP_INET_SOCK_CREATE,
20064a4658dSDaniel T. Lee 
20164a4658dSDaniel T. Lee 		.domain = AF_INET,
20264a4658dSDaniel T. Lee 		.type = SOCK_DGRAM,
20364a4658dSDaniel T. Lee 		.protocol = IPPROTO_ICMP,
20464a4658dSDaniel T. Lee 
20564a4658dSDaniel T. Lee 		.error = DENY_CREATE,
20664a4658dSDaniel T. Lee 	},
20764a4658dSDaniel T. Lee 	{
20864a4658dSDaniel T. Lee 		.descr = "block AF_INET6, SOCK_DGRAM, IPPROTO_ICMPV6 socket",
20964a4658dSDaniel T. Lee 		.insns = {
21064a4658dSDaniel T. Lee 			BPF_MOV64_IMM(BPF_REG_0, 1),	/* r0 = verdict */
21164a4658dSDaniel T. Lee 
21264a4658dSDaniel T. Lee 			/* sock->family == AF_INET6 */
21364a4658dSDaniel T. Lee 			BPF_LDX_MEM(BPF_H, BPF_REG_2, BPF_REG_1,
21464a4658dSDaniel T. Lee 				    offsetof(struct bpf_sock, family)),
21564a4658dSDaniel T. Lee 			BPF_JMP_IMM(BPF_JNE, BPF_REG_2, AF_INET6, 5),
21664a4658dSDaniel T. Lee 
21764a4658dSDaniel T. Lee 			/* sock->type == SOCK_DGRAM */
21864a4658dSDaniel T. Lee 			BPF_LDX_MEM(BPF_H, BPF_REG_2, BPF_REG_1,
21964a4658dSDaniel T. Lee 				    offsetof(struct bpf_sock, type)),
22064a4658dSDaniel T. Lee 			BPF_JMP_IMM(BPF_JNE, BPF_REG_2, SOCK_DGRAM, 3),
22164a4658dSDaniel T. Lee 
22264a4658dSDaniel T. Lee 			/* sock->protocol == IPPROTO_ICMPV6 */
22364a4658dSDaniel T. Lee 			BPF_LDX_MEM(BPF_H, BPF_REG_2, BPF_REG_1,
22464a4658dSDaniel T. Lee 				    offsetof(struct bpf_sock, protocol)),
22564a4658dSDaniel T. Lee 			BPF_JMP_IMM(BPF_JNE, BPF_REG_2, IPPROTO_ICMPV6, 1),
22664a4658dSDaniel T. Lee 
22764a4658dSDaniel T. Lee 			/* return 0 (block) */
22864a4658dSDaniel T. Lee 			BPF_MOV64_IMM(BPF_REG_0, 0),
22964a4658dSDaniel T. Lee 			BPF_EXIT_INSN(),
23064a4658dSDaniel T. Lee 		},
23164a4658dSDaniel T. Lee 		.expected_attach_type = BPF_CGROUP_INET_SOCK_CREATE,
23264a4658dSDaniel T. Lee 		.attach_type = BPF_CGROUP_INET_SOCK_CREATE,
23364a4658dSDaniel T. Lee 
23464a4658dSDaniel T. Lee 		.domain = AF_INET,
23564a4658dSDaniel T. Lee 		.type = SOCK_DGRAM,
23664a4658dSDaniel T. Lee 		.protocol = IPPROTO_ICMPV6,
23764a4658dSDaniel T. Lee 
23864a4658dSDaniel T. Lee 		.error = DENY_CREATE,
23964a4658dSDaniel T. Lee 	},
240*af522f13SJordan Rife 	{
241*af522f13SJordan Rife 		.descr = "load w/o expected_attach_type (compat mode)",
242*af522f13SJordan Rife 		.insns = {
243*af522f13SJordan Rife 			/* return 1 */
244*af522f13SJordan Rife 			BPF_MOV64_IMM(BPF_REG_0, 1),
245*af522f13SJordan Rife 			BPF_EXIT_INSN(),
246*af522f13SJordan Rife 		},
247*af522f13SJordan Rife 		.expected_attach_type = 0,
248*af522f13SJordan Rife 		.attach_type = BPF_CGROUP_INET_SOCK_CREATE,
249*af522f13SJordan Rife 
250*af522f13SJordan Rife 		.domain = AF_INET,
251*af522f13SJordan Rife 		.type = SOCK_STREAM,
252*af522f13SJordan Rife 	},
253ec6c4be0SDaniel T. Lee };
254ec6c4be0SDaniel T. Lee 
255ec6c4be0SDaniel T. Lee static int load_prog(const struct bpf_insn *insns,
256ec6c4be0SDaniel T. Lee 		     enum bpf_attach_type expected_attach_type)
257ec6c4be0SDaniel T. Lee {
258ec6c4be0SDaniel T. Lee 	LIBBPF_OPTS(bpf_prog_load_opts, opts,
259ec6c4be0SDaniel T. Lee 		    .expected_attach_type = expected_attach_type,
260ec6c4be0SDaniel T. Lee 		    .log_level = 2,
261ec6c4be0SDaniel T. Lee 		    .log_buf = bpf_log_buf,
262ec6c4be0SDaniel T. Lee 		    .log_size = sizeof(bpf_log_buf),
263ec6c4be0SDaniel T. Lee 	);
264ec6c4be0SDaniel T. Lee 	int fd, insns_cnt = 0;
265ec6c4be0SDaniel T. Lee 
266ec6c4be0SDaniel T. Lee 	for (;
267ec6c4be0SDaniel T. Lee 	     insns[insns_cnt].code != (BPF_JMP | BPF_EXIT);
268ec6c4be0SDaniel T. Lee 	     insns_cnt++) {
269ec6c4be0SDaniel T. Lee 	}
270ec6c4be0SDaniel T. Lee 	insns_cnt++;
271ec6c4be0SDaniel T. Lee 
272ec6c4be0SDaniel T. Lee 	fd = bpf_prog_load(BPF_PROG_TYPE_CGROUP_SOCK, NULL, "GPL", insns,
273ec6c4be0SDaniel T. Lee 			   insns_cnt, &opts);
274ec6c4be0SDaniel T. Lee 	if (verbose && fd < 0)
275ec6c4be0SDaniel T. Lee 		fprintf(stderr, "%s\n", bpf_log_buf);
276ec6c4be0SDaniel T. Lee 
277ec6c4be0SDaniel T. Lee 	return fd;
278ec6c4be0SDaniel T. Lee }
279ec6c4be0SDaniel T. Lee 
280ec6c4be0SDaniel T. Lee static int run_test(int cgroup_fd, struct sock_create_test *test)
281ec6c4be0SDaniel T. Lee {
282ec6c4be0SDaniel T. Lee 	int sock_fd, err, prog_fd, optval, ret = -1;
283ec6c4be0SDaniel T. Lee 	socklen_t optlen = sizeof(optval);
284ec6c4be0SDaniel T. Lee 
285ec6c4be0SDaniel T. Lee 	prog_fd = load_prog(test->insns, test->expected_attach_type);
286ec6c4be0SDaniel T. Lee 	if (prog_fd < 0) {
287ec6c4be0SDaniel T. Lee 		log_err("Failed to load BPF program");
288ec6c4be0SDaniel T. Lee 		return -1;
289ec6c4be0SDaniel T. Lee 	}
290ec6c4be0SDaniel T. Lee 
291ec6c4be0SDaniel T. Lee 	err = bpf_prog_attach(prog_fd, cgroup_fd, test->attach_type, 0);
292ec6c4be0SDaniel T. Lee 	if (err < 0) {
293ec6c4be0SDaniel T. Lee 		log_err("Failed to attach BPF program");
294ec6c4be0SDaniel T. Lee 		goto close_prog_fd;
295ec6c4be0SDaniel T. Lee 	}
296ec6c4be0SDaniel T. Lee 
29764a4658dSDaniel T. Lee 	sock_fd = socket(test->domain, test->type, test->protocol);
298ec6c4be0SDaniel T. Lee 	if (sock_fd < 0) {
29964a4658dSDaniel T. Lee 		if (test->error == DENY_CREATE)
30064a4658dSDaniel T. Lee 			ret = 0;
30164a4658dSDaniel T. Lee 		else
302ec6c4be0SDaniel T. Lee 			log_err("Failed to create socket");
30364a4658dSDaniel T. Lee 
304ec6c4be0SDaniel T. Lee 		goto detach_prog;
305ec6c4be0SDaniel T. Lee 	}
306ec6c4be0SDaniel T. Lee 
307*af522f13SJordan Rife 	if (test->optname) {
308ec6c4be0SDaniel T. Lee 		err = getsockopt(sock_fd, SOL_SOCKET, test->optname, &optval, &optlen);
309ec6c4be0SDaniel T. Lee 		if (err) {
310ec6c4be0SDaniel T. Lee 			log_err("Failed to call getsockopt");
311ec6c4be0SDaniel T. Lee 			goto cleanup;
312ec6c4be0SDaniel T. Lee 		}
313ec6c4be0SDaniel T. Lee 
314ec6c4be0SDaniel T. Lee 		if (optval != test->optval) {
315ec6c4be0SDaniel T. Lee 			errno = 0;
316ec6c4be0SDaniel T. Lee 			log_err("getsockopt returned unexpected optval");
317ec6c4be0SDaniel T. Lee 			goto cleanup;
318ec6c4be0SDaniel T. Lee 		}
319*af522f13SJordan Rife 	}
320ec6c4be0SDaniel T. Lee 
32164a4658dSDaniel T. Lee 	ret = test->error != OK;
322ec6c4be0SDaniel T. Lee 
323ec6c4be0SDaniel T. Lee cleanup:
324ec6c4be0SDaniel T. Lee 	close(sock_fd);
325ec6c4be0SDaniel T. Lee detach_prog:
326ec6c4be0SDaniel T. Lee 	bpf_prog_detach2(prog_fd, cgroup_fd, test->attach_type);
327ec6c4be0SDaniel T. Lee close_prog_fd:
328ec6c4be0SDaniel T. Lee 	close(prog_fd);
329ec6c4be0SDaniel T. Lee 	return ret;
330ec6c4be0SDaniel T. Lee }
331ec6c4be0SDaniel T. Lee 
332ec6c4be0SDaniel T. Lee void test_sock_create(void)
333ec6c4be0SDaniel T. Lee {
334ec6c4be0SDaniel T. Lee 	int cgroup_fd, i;
335ec6c4be0SDaniel T. Lee 
336ec6c4be0SDaniel T. Lee 	cgroup_fd = test__join_cgroup("/sock_create");
337ec6c4be0SDaniel T. Lee 	if (!ASSERT_GE(cgroup_fd, 0, "join_cgroup"))
338ec6c4be0SDaniel T. Lee 		return;
339ec6c4be0SDaniel T. Lee 
340ec6c4be0SDaniel T. Lee 	for (i = 0; i < ARRAY_SIZE(tests); i++) {
341ec6c4be0SDaniel T. Lee 		if (!test__start_subtest(tests[i].descr))
342ec6c4be0SDaniel T. Lee 			continue;
343ec6c4be0SDaniel T. Lee 
344ec6c4be0SDaniel T. Lee 		ASSERT_OK(run_test(cgroup_fd, &tests[i]), tests[i].descr);
345ec6c4be0SDaniel T. Lee 	}
346ec6c4be0SDaniel T. Lee 
347ec6c4be0SDaniel T. Lee 	close(cgroup_fd);
348ec6c4be0SDaniel T. Lee }
349