1 // SPDX-License-Identifier: GPL-2.0-only
2 
3 /*
4  * Copyright 2021 Google LLC.
5  */
6 
7 #include <test_progs.h>
8 #include <cgroup_helpers.h>
9 #include <network_helpers.h>
10 
11 #include "cgroup_getset_retval_setsockopt.skel.h"
12 #include "cgroup_getset_retval_getsockopt.skel.h"
13 #include "cgroup_getset_retval_hooks.skel.h"
14 
15 #define SOL_CUSTOM	0xdeadbeef
16 
17 static int zero;
18 
test_setsockopt_set(int cgroup_fd,int sock_fd)19 static void test_setsockopt_set(int cgroup_fd, int sock_fd)
20 {
21 	struct cgroup_getset_retval_setsockopt *obj;
22 	struct bpf_link *link_set_eunatch = NULL;
23 
24 	obj = cgroup_getset_retval_setsockopt__open_and_load();
25 	if (!ASSERT_OK_PTR(obj, "skel-load"))
26 		return;
27 
28 	obj->bss->page_size = sysconf(_SC_PAGESIZE);
29 
30 	/* Attach setsockopt that sets EUNATCH, assert that
31 	 * we actually get that error when we run setsockopt()
32 	 */
33 	link_set_eunatch = bpf_program__attach_cgroup(obj->progs.set_eunatch,
34 						      cgroup_fd);
35 	if (!ASSERT_OK_PTR(link_set_eunatch, "cg-attach-set_eunatch"))
36 		goto close_bpf_object;
37 
38 	if (!ASSERT_ERR(setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR,
39 				   &zero, sizeof(int)), "setsockopt"))
40 		goto close_bpf_object;
41 	if (!ASSERT_EQ(errno, EUNATCH, "setsockopt-errno"))
42 		goto close_bpf_object;
43 
44 	if (!ASSERT_EQ(obj->bss->invocations, 1, "invocations"))
45 		goto close_bpf_object;
46 	if (!ASSERT_FALSE(obj->bss->assertion_error, "assertion_error"))
47 		goto close_bpf_object;
48 
49 close_bpf_object:
50 	bpf_link__destroy(link_set_eunatch);
51 
52 	cgroup_getset_retval_setsockopt__destroy(obj);
53 }
54 
test_setsockopt_set_and_get(int cgroup_fd,int sock_fd)55 static void test_setsockopt_set_and_get(int cgroup_fd, int sock_fd)
56 {
57 	struct cgroup_getset_retval_setsockopt *obj;
58 	struct bpf_link *link_set_eunatch = NULL, *link_get_retval = NULL;
59 
60 	obj = cgroup_getset_retval_setsockopt__open_and_load();
61 	if (!ASSERT_OK_PTR(obj, "skel-load"))
62 		return;
63 
64 	obj->bss->page_size = sysconf(_SC_PAGESIZE);
65 
66 	/* Attach setsockopt that sets EUNATCH, and one that gets the
67 	 * previously set errno. Assert that we get the same errno back.
68 	 */
69 	link_set_eunatch = bpf_program__attach_cgroup(obj->progs.set_eunatch,
70 						      cgroup_fd);
71 	if (!ASSERT_OK_PTR(link_set_eunatch, "cg-attach-set_eunatch"))
72 		goto close_bpf_object;
73 	link_get_retval = bpf_program__attach_cgroup(obj->progs.get_retval,
74 						     cgroup_fd);
75 	if (!ASSERT_OK_PTR(link_get_retval, "cg-attach-get_retval"))
76 		goto close_bpf_object;
77 
78 	if (!ASSERT_ERR(setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR,
79 				   &zero, sizeof(int)), "setsockopt"))
80 		goto close_bpf_object;
81 	if (!ASSERT_EQ(errno, EUNATCH, "setsockopt-errno"))
82 		goto close_bpf_object;
83 
84 	if (!ASSERT_EQ(obj->bss->invocations, 2, "invocations"))
85 		goto close_bpf_object;
86 	if (!ASSERT_FALSE(obj->bss->assertion_error, "assertion_error"))
87 		goto close_bpf_object;
88 	if (!ASSERT_EQ(obj->bss->retval_value, -EUNATCH, "retval_value"))
89 		goto close_bpf_object;
90 
91 close_bpf_object:
92 	bpf_link__destroy(link_set_eunatch);
93 	bpf_link__destroy(link_get_retval);
94 
95 	cgroup_getset_retval_setsockopt__destroy(obj);
96 }
97 
test_setsockopt_default_zero(int cgroup_fd,int sock_fd)98 static void test_setsockopt_default_zero(int cgroup_fd, int sock_fd)
99 {
100 	struct cgroup_getset_retval_setsockopt *obj;
101 	struct bpf_link *link_get_retval = NULL;
102 
103 	obj = cgroup_getset_retval_setsockopt__open_and_load();
104 	if (!ASSERT_OK_PTR(obj, "skel-load"))
105 		return;
106 
107 	obj->bss->page_size = sysconf(_SC_PAGESIZE);
108 
109 	/* Attach setsockopt that gets the previously set errno.
110 	 * Assert that, without anything setting one, we get 0.
111 	 */
112 	link_get_retval = bpf_program__attach_cgroup(obj->progs.get_retval,
113 						     cgroup_fd);
114 	if (!ASSERT_OK_PTR(link_get_retval, "cg-attach-get_retval"))
115 		goto close_bpf_object;
116 
117 	if (!ASSERT_OK(setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR,
118 				  &zero, sizeof(int)), "setsockopt"))
119 		goto close_bpf_object;
120 
121 	if (!ASSERT_EQ(obj->bss->invocations, 1, "invocations"))
122 		goto close_bpf_object;
123 	if (!ASSERT_FALSE(obj->bss->assertion_error, "assertion_error"))
124 		goto close_bpf_object;
125 	if (!ASSERT_EQ(obj->bss->retval_value, 0, "retval_value"))
126 		goto close_bpf_object;
127 
128 close_bpf_object:
129 	bpf_link__destroy(link_get_retval);
130 
131 	cgroup_getset_retval_setsockopt__destroy(obj);
132 }
133 
test_setsockopt_default_zero_and_set(int cgroup_fd,int sock_fd)134 static void test_setsockopt_default_zero_and_set(int cgroup_fd, int sock_fd)
135 {
136 	struct cgroup_getset_retval_setsockopt *obj;
137 	struct bpf_link *link_get_retval = NULL, *link_set_eunatch = NULL;
138 
139 	obj = cgroup_getset_retval_setsockopt__open_and_load();
140 	if (!ASSERT_OK_PTR(obj, "skel-load"))
141 		return;
142 
143 	obj->bss->page_size = sysconf(_SC_PAGESIZE);
144 
145 	/* Attach setsockopt that gets the previously set errno, and then
146 	 * one that sets the errno to EUNATCH. Assert that the get does not
147 	 * see EUNATCH set later, and does not prevent EUNATCH from being set.
148 	 */
149 	link_get_retval = bpf_program__attach_cgroup(obj->progs.get_retval,
150 						     cgroup_fd);
151 	if (!ASSERT_OK_PTR(link_get_retval, "cg-attach-get_retval"))
152 		goto close_bpf_object;
153 	link_set_eunatch = bpf_program__attach_cgroup(obj->progs.set_eunatch,
154 						      cgroup_fd);
155 	if (!ASSERT_OK_PTR(link_set_eunatch, "cg-attach-set_eunatch"))
156 		goto close_bpf_object;
157 
158 	if (!ASSERT_ERR(setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR,
159 				   &zero, sizeof(int)), "setsockopt"))
160 		goto close_bpf_object;
161 	if (!ASSERT_EQ(errno, EUNATCH, "setsockopt-errno"))
162 		goto close_bpf_object;
163 
164 	if (!ASSERT_EQ(obj->bss->invocations, 2, "invocations"))
165 		goto close_bpf_object;
166 	if (!ASSERT_FALSE(obj->bss->assertion_error, "assertion_error"))
167 		goto close_bpf_object;
168 	if (!ASSERT_EQ(obj->bss->retval_value, 0, "retval_value"))
169 		goto close_bpf_object;
170 
171 close_bpf_object:
172 	bpf_link__destroy(link_get_retval);
173 	bpf_link__destroy(link_set_eunatch);
174 
175 	cgroup_getset_retval_setsockopt__destroy(obj);
176 }
177 
test_setsockopt_override(int cgroup_fd,int sock_fd)178 static void test_setsockopt_override(int cgroup_fd, int sock_fd)
179 {
180 	struct cgroup_getset_retval_setsockopt *obj;
181 	struct bpf_link *link_set_eunatch = NULL, *link_set_eisconn = NULL;
182 	struct bpf_link *link_get_retval = NULL;
183 
184 	obj = cgroup_getset_retval_setsockopt__open_and_load();
185 	if (!ASSERT_OK_PTR(obj, "skel-load"))
186 		return;
187 
188 	obj->bss->page_size = sysconf(_SC_PAGESIZE);
189 
190 	/* Attach setsockopt that sets EUNATCH, then one that sets EISCONN,
191 	 * and then one that gets the exported errno. Assert both the syscall
192 	 * and the helper sees the last set errno.
193 	 */
194 	link_set_eunatch = bpf_program__attach_cgroup(obj->progs.set_eunatch,
195 						      cgroup_fd);
196 	if (!ASSERT_OK_PTR(link_set_eunatch, "cg-attach-set_eunatch"))
197 		goto close_bpf_object;
198 	link_set_eisconn = bpf_program__attach_cgroup(obj->progs.set_eisconn,
199 						      cgroup_fd);
200 	if (!ASSERT_OK_PTR(link_set_eisconn, "cg-attach-set_eisconn"))
201 		goto close_bpf_object;
202 	link_get_retval = bpf_program__attach_cgroup(obj->progs.get_retval,
203 						     cgroup_fd);
204 	if (!ASSERT_OK_PTR(link_get_retval, "cg-attach-get_retval"))
205 		goto close_bpf_object;
206 
207 	if (!ASSERT_ERR(setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR,
208 				   &zero, sizeof(int)), "setsockopt"))
209 		goto close_bpf_object;
210 	if (!ASSERT_EQ(errno, EISCONN, "setsockopt-errno"))
211 		goto close_bpf_object;
212 
213 	if (!ASSERT_EQ(obj->bss->invocations, 3, "invocations"))
214 		goto close_bpf_object;
215 	if (!ASSERT_FALSE(obj->bss->assertion_error, "assertion_error"))
216 		goto close_bpf_object;
217 	if (!ASSERT_EQ(obj->bss->retval_value, -EISCONN, "retval_value"))
218 		goto close_bpf_object;
219 
220 close_bpf_object:
221 	bpf_link__destroy(link_set_eunatch);
222 	bpf_link__destroy(link_set_eisconn);
223 	bpf_link__destroy(link_get_retval);
224 
225 	cgroup_getset_retval_setsockopt__destroy(obj);
226 }
227 
test_setsockopt_legacy_eperm(int cgroup_fd,int sock_fd)228 static void test_setsockopt_legacy_eperm(int cgroup_fd, int sock_fd)
229 {
230 	struct cgroup_getset_retval_setsockopt *obj;
231 	struct bpf_link *link_legacy_eperm = NULL, *link_get_retval = NULL;
232 
233 	obj = cgroup_getset_retval_setsockopt__open_and_load();
234 	if (!ASSERT_OK_PTR(obj, "skel-load"))
235 		return;
236 
237 	obj->bss->page_size = sysconf(_SC_PAGESIZE);
238 
239 	/* Attach setsockopt that return a reject without setting errno
240 	 * (legacy reject), and one that gets the errno. Assert that for
241 	 * backward compatibility the syscall result in EPERM, and this
242 	 * is also visible to the helper.
243 	 */
244 	link_legacy_eperm = bpf_program__attach_cgroup(obj->progs.legacy_eperm,
245 						       cgroup_fd);
246 	if (!ASSERT_OK_PTR(link_legacy_eperm, "cg-attach-legacy_eperm"))
247 		goto close_bpf_object;
248 	link_get_retval = bpf_program__attach_cgroup(obj->progs.get_retval,
249 						     cgroup_fd);
250 	if (!ASSERT_OK_PTR(link_get_retval, "cg-attach-get_retval"))
251 		goto close_bpf_object;
252 
253 	if (!ASSERT_ERR(setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR,
254 				   &zero, sizeof(int)), "setsockopt"))
255 		goto close_bpf_object;
256 	if (!ASSERT_EQ(errno, EPERM, "setsockopt-errno"))
257 		goto close_bpf_object;
258 
259 	if (!ASSERT_EQ(obj->bss->invocations, 2, "invocations"))
260 		goto close_bpf_object;
261 	if (!ASSERT_FALSE(obj->bss->assertion_error, "assertion_error"))
262 		goto close_bpf_object;
263 	if (!ASSERT_EQ(obj->bss->retval_value, -EPERM, "retval_value"))
264 		goto close_bpf_object;
265 
266 close_bpf_object:
267 	bpf_link__destroy(link_legacy_eperm);
268 	bpf_link__destroy(link_get_retval);
269 
270 	cgroup_getset_retval_setsockopt__destroy(obj);
271 }
272 
test_setsockopt_legacy_no_override(int cgroup_fd,int sock_fd)273 static void test_setsockopt_legacy_no_override(int cgroup_fd, int sock_fd)
274 {
275 	struct cgroup_getset_retval_setsockopt *obj;
276 	struct bpf_link *link_set_eunatch = NULL, *link_legacy_eperm = NULL;
277 	struct bpf_link *link_get_retval = NULL;
278 
279 	obj = cgroup_getset_retval_setsockopt__open_and_load();
280 	if (!ASSERT_OK_PTR(obj, "skel-load"))
281 		return;
282 
283 	obj->bss->page_size = sysconf(_SC_PAGESIZE);
284 
285 	/* Attach setsockopt that sets EUNATCH, then one that return a reject
286 	 * without setting errno, and then one that gets the exported errno.
287 	 * Assert both the syscall and the helper's errno are unaffected by
288 	 * the second prog (i.e. legacy rejects does not override the errno
289 	 * to EPERM).
290 	 */
291 	link_set_eunatch = bpf_program__attach_cgroup(obj->progs.set_eunatch,
292 						      cgroup_fd);
293 	if (!ASSERT_OK_PTR(link_set_eunatch, "cg-attach-set_eunatch"))
294 		goto close_bpf_object;
295 	link_legacy_eperm = bpf_program__attach_cgroup(obj->progs.legacy_eperm,
296 						       cgroup_fd);
297 	if (!ASSERT_OK_PTR(link_legacy_eperm, "cg-attach-legacy_eperm"))
298 		goto close_bpf_object;
299 	link_get_retval = bpf_program__attach_cgroup(obj->progs.get_retval,
300 						     cgroup_fd);
301 	if (!ASSERT_OK_PTR(link_get_retval, "cg-attach-get_retval"))
302 		goto close_bpf_object;
303 
304 	if (!ASSERT_ERR(setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR,
305 				   &zero, sizeof(int)), "setsockopt"))
306 		goto close_bpf_object;
307 	if (!ASSERT_EQ(errno, EUNATCH, "setsockopt-errno"))
308 		goto close_bpf_object;
309 
310 	if (!ASSERT_EQ(obj->bss->invocations, 3, "invocations"))
311 		goto close_bpf_object;
312 	if (!ASSERT_FALSE(obj->bss->assertion_error, "assertion_error"))
313 		goto close_bpf_object;
314 	if (!ASSERT_EQ(obj->bss->retval_value, -EUNATCH, "retval_value"))
315 		goto close_bpf_object;
316 
317 close_bpf_object:
318 	bpf_link__destroy(link_set_eunatch);
319 	bpf_link__destroy(link_legacy_eperm);
320 	bpf_link__destroy(link_get_retval);
321 
322 	cgroup_getset_retval_setsockopt__destroy(obj);
323 }
324 
test_getsockopt_get(int cgroup_fd,int sock_fd)325 static void test_getsockopt_get(int cgroup_fd, int sock_fd)
326 {
327 	struct cgroup_getset_retval_getsockopt *obj;
328 	struct bpf_link *link_get_retval = NULL;
329 	int buf;
330 	socklen_t optlen = sizeof(buf);
331 
332 	obj = cgroup_getset_retval_getsockopt__open_and_load();
333 	if (!ASSERT_OK_PTR(obj, "skel-load"))
334 		return;
335 
336 	obj->bss->page_size = sysconf(_SC_PAGESIZE);
337 
338 	/* Attach getsockopt that gets previously set errno. Assert that the
339 	 * error from kernel is in both ctx_retval_value and retval_value.
340 	 */
341 	link_get_retval = bpf_program__attach_cgroup(obj->progs.get_retval,
342 						     cgroup_fd);
343 	if (!ASSERT_OK_PTR(link_get_retval, "cg-attach-get_retval"))
344 		goto close_bpf_object;
345 
346 	if (!ASSERT_ERR(getsockopt(sock_fd, SOL_CUSTOM, 0,
347 				   &buf, &optlen), "getsockopt"))
348 		goto close_bpf_object;
349 	if (!ASSERT_EQ(errno, EOPNOTSUPP, "getsockopt-errno"))
350 		goto close_bpf_object;
351 
352 	if (!ASSERT_EQ(obj->bss->invocations, 1, "invocations"))
353 		goto close_bpf_object;
354 	if (!ASSERT_FALSE(obj->bss->assertion_error, "assertion_error"))
355 		goto close_bpf_object;
356 	if (!ASSERT_EQ(obj->bss->retval_value, -EOPNOTSUPP, "retval_value"))
357 		goto close_bpf_object;
358 	if (!ASSERT_EQ(obj->bss->ctx_retval_value, -EOPNOTSUPP, "ctx_retval_value"))
359 		goto close_bpf_object;
360 
361 close_bpf_object:
362 	bpf_link__destroy(link_get_retval);
363 
364 	cgroup_getset_retval_getsockopt__destroy(obj);
365 }
366 
test_getsockopt_override(int cgroup_fd,int sock_fd)367 static void test_getsockopt_override(int cgroup_fd, int sock_fd)
368 {
369 	struct cgroup_getset_retval_getsockopt *obj;
370 	struct bpf_link *link_set_eisconn = NULL;
371 	int buf;
372 	socklen_t optlen = sizeof(buf);
373 
374 	obj = cgroup_getset_retval_getsockopt__open_and_load();
375 	if (!ASSERT_OK_PTR(obj, "skel-load"))
376 		return;
377 
378 	obj->bss->page_size = sysconf(_SC_PAGESIZE);
379 
380 	/* Attach getsockopt that sets retval to -EISCONN. Assert that this
381 	 * overrides the value from kernel.
382 	 */
383 	link_set_eisconn = bpf_program__attach_cgroup(obj->progs.set_eisconn,
384 						      cgroup_fd);
385 	if (!ASSERT_OK_PTR(link_set_eisconn, "cg-attach-set_eisconn"))
386 		goto close_bpf_object;
387 
388 	if (!ASSERT_ERR(getsockopt(sock_fd, SOL_CUSTOM, 0,
389 				   &buf, &optlen), "getsockopt"))
390 		goto close_bpf_object;
391 	if (!ASSERT_EQ(errno, EISCONN, "getsockopt-errno"))
392 		goto close_bpf_object;
393 
394 	if (!ASSERT_EQ(obj->bss->invocations, 1, "invocations"))
395 		goto close_bpf_object;
396 	if (!ASSERT_FALSE(obj->bss->assertion_error, "assertion_error"))
397 		goto close_bpf_object;
398 
399 close_bpf_object:
400 	bpf_link__destroy(link_set_eisconn);
401 
402 	cgroup_getset_retval_getsockopt__destroy(obj);
403 }
404 
test_getsockopt_retval_sync(int cgroup_fd,int sock_fd)405 static void test_getsockopt_retval_sync(int cgroup_fd, int sock_fd)
406 {
407 	struct cgroup_getset_retval_getsockopt *obj;
408 	struct bpf_link *link_set_eisconn = NULL, *link_clear_retval = NULL;
409 	struct bpf_link *link_get_retval = NULL;
410 	int buf;
411 	socklen_t optlen = sizeof(buf);
412 
413 	obj = cgroup_getset_retval_getsockopt__open_and_load();
414 	if (!ASSERT_OK_PTR(obj, "skel-load"))
415 		return;
416 
417 	obj->bss->page_size = sysconf(_SC_PAGESIZE);
418 
419 	/* Attach getsockopt that sets retval to -EISCONN, and one that clears
420 	 * ctx retval. Assert that the clearing ctx retval is synced to helper
421 	 * and clears any errors both from kernel and BPF..
422 	 */
423 	link_set_eisconn = bpf_program__attach_cgroup(obj->progs.set_eisconn,
424 						      cgroup_fd);
425 	if (!ASSERT_OK_PTR(link_set_eisconn, "cg-attach-set_eisconn"))
426 		goto close_bpf_object;
427 	link_clear_retval = bpf_program__attach_cgroup(obj->progs.clear_retval,
428 						       cgroup_fd);
429 	if (!ASSERT_OK_PTR(link_clear_retval, "cg-attach-clear_retval"))
430 		goto close_bpf_object;
431 	link_get_retval = bpf_program__attach_cgroup(obj->progs.get_retval,
432 						     cgroup_fd);
433 	if (!ASSERT_OK_PTR(link_get_retval, "cg-attach-get_retval"))
434 		goto close_bpf_object;
435 
436 	if (!ASSERT_OK(getsockopt(sock_fd, SOL_CUSTOM, 0,
437 				  &buf, &optlen), "getsockopt"))
438 		goto close_bpf_object;
439 
440 	if (!ASSERT_EQ(obj->bss->invocations, 3, "invocations"))
441 		goto close_bpf_object;
442 	if (!ASSERT_FALSE(obj->bss->assertion_error, "assertion_error"))
443 		goto close_bpf_object;
444 	if (!ASSERT_EQ(obj->bss->retval_value, 0, "retval_value"))
445 		goto close_bpf_object;
446 	if (!ASSERT_EQ(obj->bss->ctx_retval_value, 0, "ctx_retval_value"))
447 		goto close_bpf_object;
448 
449 close_bpf_object:
450 	bpf_link__destroy(link_set_eisconn);
451 	bpf_link__destroy(link_clear_retval);
452 	bpf_link__destroy(link_get_retval);
453 
454 	cgroup_getset_retval_getsockopt__destroy(obj);
455 }
456 
457 struct exposed_hook {
458 	const char *name;
459 	int expected_err;
460 } exposed_hooks[] = {
461 
462 #define BPF_RETVAL_HOOK(NAME, SECTION, CTX, EXPECTED_ERR) \
463 	{ \
464 		.name = #NAME, \
465 		.expected_err = EXPECTED_ERR, \
466 	},
467 
468 #include "cgroup_getset_retval_hooks.h"
469 
470 #undef BPF_RETVAL_HOOK
471 };
472 
test_exposed_hooks(int cgroup_fd,int sock_fd)473 static void test_exposed_hooks(int cgroup_fd, int sock_fd)
474 {
475 	struct cgroup_getset_retval_hooks *skel;
476 	struct bpf_program *prog;
477 	int err;
478 	int i;
479 
480 	for (i = 0; i < ARRAY_SIZE(exposed_hooks); i++) {
481 		skel = cgroup_getset_retval_hooks__open();
482 		if (!ASSERT_OK_PTR(skel, "cgroup_getset_retval_hooks__open"))
483 			continue;
484 
485 		prog = bpf_object__find_program_by_name(skel->obj, exposed_hooks[i].name);
486 		if (!ASSERT_NEQ(prog, NULL, "bpf_object__find_program_by_name"))
487 			goto close_skel;
488 
489 		err = bpf_program__set_autoload(prog, true);
490 		if (!ASSERT_OK(err, "bpf_program__set_autoload"))
491 			goto close_skel;
492 
493 		err = cgroup_getset_retval_hooks__load(skel);
494 		ASSERT_EQ(err, exposed_hooks[i].expected_err, "expected_err");
495 
496 close_skel:
497 		cgroup_getset_retval_hooks__destroy(skel);
498 	}
499 }
500 
test_cgroup_getset_retval(void)501 void test_cgroup_getset_retval(void)
502 {
503 	int cgroup_fd = -1;
504 	int sock_fd = -1;
505 
506 	cgroup_fd = test__join_cgroup("/cgroup_getset_retval");
507 	if (!ASSERT_GE(cgroup_fd, 0, "cg-create"))
508 		goto close_fd;
509 
510 	sock_fd = start_server(AF_INET, SOCK_DGRAM, NULL, 0, 0);
511 	if (!ASSERT_GE(sock_fd, 0, "start-server"))
512 		goto close_fd;
513 
514 	if (test__start_subtest("setsockopt-set"))
515 		test_setsockopt_set(cgroup_fd, sock_fd);
516 
517 	if (test__start_subtest("setsockopt-set_and_get"))
518 		test_setsockopt_set_and_get(cgroup_fd, sock_fd);
519 
520 	if (test__start_subtest("setsockopt-default_zero"))
521 		test_setsockopt_default_zero(cgroup_fd, sock_fd);
522 
523 	if (test__start_subtest("setsockopt-default_zero_and_set"))
524 		test_setsockopt_default_zero_and_set(cgroup_fd, sock_fd);
525 
526 	if (test__start_subtest("setsockopt-override"))
527 		test_setsockopt_override(cgroup_fd, sock_fd);
528 
529 	if (test__start_subtest("setsockopt-legacy_eperm"))
530 		test_setsockopt_legacy_eperm(cgroup_fd, sock_fd);
531 
532 	if (test__start_subtest("setsockopt-legacy_no_override"))
533 		test_setsockopt_legacy_no_override(cgroup_fd, sock_fd);
534 
535 	if (test__start_subtest("getsockopt-get"))
536 		test_getsockopt_get(cgroup_fd, sock_fd);
537 
538 	if (test__start_subtest("getsockopt-override"))
539 		test_getsockopt_override(cgroup_fd, sock_fd);
540 
541 	if (test__start_subtest("getsockopt-retval_sync"))
542 		test_getsockopt_retval_sync(cgroup_fd, sock_fd);
543 
544 	if (test__start_subtest("exposed_hooks"))
545 		test_exposed_hooks(cgroup_fd, sock_fd);
546 
547 close_fd:
548 	close(cgroup_fd);
549 }
550