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