1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Landlock tests - Abstract UNIX socket
4 *
5 * Copyright © 2024 Tahera Fahimi <fahimitahera@gmail.com>
6 */
7
8 #define _GNU_SOURCE
9 #include <errno.h>
10 #include <fcntl.h>
11 #include <linux/landlock.h>
12 #include <sched.h>
13 #include <signal.h>
14 #include <stddef.h>
15 #include <sys/prctl.h>
16 #include <sys/socket.h>
17 #include <sys/stat.h>
18 #include <sys/types.h>
19 #include <sys/un.h>
20 #include <sys/wait.h>
21 #include <unistd.h>
22
23 #include "audit.h"
24 #include "common.h"
25 #include "scoped_common.h"
26
27 /* Number of pending connections queue to be hold. */
28 const short backlog = 10;
29
create_fs_domain(struct __test_metadata * const _metadata)30 static void create_fs_domain(struct __test_metadata *const _metadata)
31 {
32 int ruleset_fd;
33 struct landlock_ruleset_attr ruleset_attr = {
34 .handled_access_fs = LANDLOCK_ACCESS_FS_READ_DIR,
35 };
36
37 ruleset_fd =
38 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
39 EXPECT_LE(0, ruleset_fd)
40 {
41 TH_LOG("Failed to create a ruleset: %s", strerror(errno));
42 }
43 EXPECT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));
44 EXPECT_EQ(0, landlock_restrict_self(ruleset_fd, 0));
45 EXPECT_EQ(0, close(ruleset_fd));
46 }
47
FIXTURE(scoped_domains)48 FIXTURE(scoped_domains)
49 {
50 struct service_fixture stream_address, dgram_address;
51 };
52
53 #include "scoped_base_variants.h"
54
FIXTURE_SETUP(scoped_domains)55 FIXTURE_SETUP(scoped_domains)
56 {
57 drop_caps(_metadata);
58
59 memset(&self->stream_address, 0, sizeof(self->stream_address));
60 memset(&self->dgram_address, 0, sizeof(self->dgram_address));
61 set_unix_address(&self->stream_address, 0);
62 set_unix_address(&self->dgram_address, 1);
63 }
64
FIXTURE_TEARDOWN(scoped_domains)65 FIXTURE_TEARDOWN(scoped_domains)
66 {
67 }
68
69 /*
70 * Test unix_stream_connect() and unix_may_send() for a child connecting to its
71 * parent, when they have scoped domain or no domain.
72 */
TEST_F(scoped_domains,connect_to_parent)73 TEST_F(scoped_domains, connect_to_parent)
74 {
75 pid_t child;
76 bool can_connect_to_parent;
77 int status;
78 int pipe_parent[2];
79 int stream_server, dgram_server;
80
81 /*
82 * can_connect_to_parent is true if a child process can connect to its
83 * parent process. This depends on the child process not being isolated
84 * from the parent with a dedicated Landlock domain.
85 */
86 can_connect_to_parent = !variant->domain_child;
87
88 ASSERT_EQ(0, pipe2(pipe_parent, O_CLOEXEC));
89 if (variant->domain_both) {
90 create_scoped_domain(_metadata,
91 LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET);
92 if (!__test_passed(_metadata))
93 return;
94 }
95
96 child = fork();
97 ASSERT_LE(0, child);
98 if (child == 0) {
99 int err;
100 int stream_client, dgram_client;
101 char buf_child;
102
103 EXPECT_EQ(0, close(pipe_parent[1]));
104 if (variant->domain_child)
105 create_scoped_domain(
106 _metadata, LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET);
107
108 stream_client = socket(AF_UNIX, SOCK_STREAM, 0);
109 ASSERT_LE(0, stream_client);
110 dgram_client = socket(AF_UNIX, SOCK_DGRAM, 0);
111 ASSERT_LE(0, dgram_client);
112
113 /* Waits for the server. */
114 ASSERT_EQ(1, read(pipe_parent[0], &buf_child, 1));
115
116 err = connect(stream_client, &self->stream_address.unix_addr,
117 self->stream_address.unix_addr_len);
118 if (can_connect_to_parent) {
119 EXPECT_EQ(0, err);
120 } else {
121 EXPECT_EQ(-1, err);
122 EXPECT_EQ(EPERM, errno);
123 }
124 EXPECT_EQ(0, close(stream_client));
125
126 err = connect(dgram_client, &self->dgram_address.unix_addr,
127 self->dgram_address.unix_addr_len);
128 if (can_connect_to_parent) {
129 EXPECT_EQ(0, err);
130 } else {
131 EXPECT_EQ(-1, err);
132 EXPECT_EQ(EPERM, errno);
133 }
134 EXPECT_EQ(0, close(dgram_client));
135 _exit(_metadata->exit_code);
136 return;
137 }
138 EXPECT_EQ(0, close(pipe_parent[0]));
139 if (variant->domain_parent)
140 create_scoped_domain(_metadata,
141 LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET);
142
143 stream_server = socket(AF_UNIX, SOCK_STREAM, 0);
144 ASSERT_LE(0, stream_server);
145 dgram_server = socket(AF_UNIX, SOCK_DGRAM, 0);
146 ASSERT_LE(0, dgram_server);
147 ASSERT_EQ(0, bind(stream_server, &self->stream_address.unix_addr,
148 self->stream_address.unix_addr_len));
149 ASSERT_EQ(0, bind(dgram_server, &self->dgram_address.unix_addr,
150 self->dgram_address.unix_addr_len));
151 ASSERT_EQ(0, listen(stream_server, backlog));
152
153 /* Signals to child that the parent is listening. */
154 ASSERT_EQ(1, write(pipe_parent[1], ".", 1));
155
156 ASSERT_EQ(child, waitpid(child, &status, 0));
157 EXPECT_EQ(0, close(stream_server));
158 EXPECT_EQ(0, close(dgram_server));
159
160 if (WIFSIGNALED(status) || !WIFEXITED(status) ||
161 WEXITSTATUS(status) != EXIT_SUCCESS)
162 _metadata->exit_code = KSFT_FAIL;
163 }
164
165 /*
166 * Test unix_stream_connect() and unix_may_send() for a parent connecting to
167 * its child, when they have scoped domain or no domain.
168 */
TEST_F(scoped_domains,connect_to_child)169 TEST_F(scoped_domains, connect_to_child)
170 {
171 pid_t child;
172 bool can_connect_to_child;
173 int err_stream, err_dgram, errno_stream, errno_dgram, status;
174 int pipe_child[2], pipe_parent[2];
175 char buf;
176 int stream_client, dgram_client;
177
178 /*
179 * can_connect_to_child is true if a parent process can connect to its
180 * child process. The parent process is not isolated from the child
181 * with a dedicated Landlock domain.
182 */
183 can_connect_to_child = !variant->domain_parent;
184
185 ASSERT_EQ(0, pipe2(pipe_child, O_CLOEXEC));
186 ASSERT_EQ(0, pipe2(pipe_parent, O_CLOEXEC));
187 if (variant->domain_both) {
188 create_scoped_domain(_metadata,
189 LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET);
190 if (!__test_passed(_metadata))
191 return;
192 }
193
194 child = fork();
195 ASSERT_LE(0, child);
196 if (child == 0) {
197 int stream_server, dgram_server;
198
199 EXPECT_EQ(0, close(pipe_parent[1]));
200 EXPECT_EQ(0, close(pipe_child[0]));
201 if (variant->domain_child)
202 create_scoped_domain(
203 _metadata, LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET);
204
205 /* Waits for the parent to be in a domain, if any. */
206 ASSERT_EQ(1, read(pipe_parent[0], &buf, 1));
207
208 stream_server = socket(AF_UNIX, SOCK_STREAM, 0);
209 ASSERT_LE(0, stream_server);
210 dgram_server = socket(AF_UNIX, SOCK_DGRAM, 0);
211 ASSERT_LE(0, dgram_server);
212 ASSERT_EQ(0,
213 bind(stream_server, &self->stream_address.unix_addr,
214 self->stream_address.unix_addr_len));
215 ASSERT_EQ(0, bind(dgram_server, &self->dgram_address.unix_addr,
216 self->dgram_address.unix_addr_len));
217 ASSERT_EQ(0, listen(stream_server, backlog));
218
219 /* Signals to the parent that child is listening. */
220 ASSERT_EQ(1, write(pipe_child[1], ".", 1));
221
222 /* Waits to connect. */
223 ASSERT_EQ(1, read(pipe_parent[0], &buf, 1));
224 EXPECT_EQ(0, close(stream_server));
225 EXPECT_EQ(0, close(dgram_server));
226 _exit(_metadata->exit_code);
227 return;
228 }
229 EXPECT_EQ(0, close(pipe_child[1]));
230 EXPECT_EQ(0, close(pipe_parent[0]));
231
232 if (variant->domain_parent)
233 create_scoped_domain(_metadata,
234 LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET);
235
236 /* Signals that the parent is in a domain, if any. */
237 ASSERT_EQ(1, write(pipe_parent[1], ".", 1));
238
239 stream_client = socket(AF_UNIX, SOCK_STREAM, 0);
240 ASSERT_LE(0, stream_client);
241 dgram_client = socket(AF_UNIX, SOCK_DGRAM, 0);
242 ASSERT_LE(0, dgram_client);
243
244 /* Waits for the child to listen */
245 ASSERT_EQ(1, read(pipe_child[0], &buf, 1));
246 err_stream = connect(stream_client, &self->stream_address.unix_addr,
247 self->stream_address.unix_addr_len);
248 errno_stream = errno;
249 err_dgram = connect(dgram_client, &self->dgram_address.unix_addr,
250 self->dgram_address.unix_addr_len);
251 errno_dgram = errno;
252 if (can_connect_to_child) {
253 EXPECT_EQ(0, err_stream);
254 EXPECT_EQ(0, err_dgram);
255 } else {
256 EXPECT_EQ(-1, err_stream);
257 EXPECT_EQ(-1, err_dgram);
258 EXPECT_EQ(EPERM, errno_stream);
259 EXPECT_EQ(EPERM, errno_dgram);
260 }
261 ASSERT_EQ(1, write(pipe_parent[1], ".", 1));
262 EXPECT_EQ(0, close(stream_client));
263 EXPECT_EQ(0, close(dgram_client));
264
265 ASSERT_EQ(child, waitpid(child, &status, 0));
266 if (WIFSIGNALED(status) || !WIFEXITED(status) ||
267 WEXITSTATUS(status) != EXIT_SUCCESS)
268 _metadata->exit_code = KSFT_FAIL;
269 }
270
FIXTURE(scoped_audit)271 FIXTURE(scoped_audit)
272 {
273 struct service_fixture dgram_address;
274 struct audit_filter audit_filter;
275 int audit_fd;
276 };
277
FIXTURE_SETUP(scoped_audit)278 FIXTURE_SETUP(scoped_audit)
279 {
280 disable_caps(_metadata);
281
282 memset(&self->dgram_address, 0, sizeof(self->dgram_address));
283 set_unix_address(&self->dgram_address, 1);
284
285 set_cap(_metadata, CAP_AUDIT_CONTROL);
286 self->audit_fd = audit_init_with_exe_filter(&self->audit_filter);
287 EXPECT_LE(0, self->audit_fd);
288 drop_caps(_metadata);
289 }
290
FIXTURE_TEARDOWN_PARENT(scoped_audit)291 FIXTURE_TEARDOWN_PARENT(scoped_audit)
292 {
293 EXPECT_EQ(0, audit_cleanup(-1, NULL));
294 }
295
296 /* python -c 'print(b"\0selftests-landlock-abstract-unix-".hex().upper())' */
297 #define ABSTRACT_SOCKET_PATH_PREFIX \
298 "0073656C6674657374732D6C616E646C6F636B2D61627374726163742D756E69782D"
299
300 /*
301 * Simpler version of scoped_domains.connect_to_child, but with audit tests.
302 */
TEST_F(scoped_audit,connect_to_child)303 TEST_F(scoped_audit, connect_to_child)
304 {
305 pid_t child;
306 int err_dgram, status;
307 int pipe_child[2], pipe_parent[2];
308 char buf;
309 int dgram_client;
310 struct audit_records records;
311
312 /* Makes sure there is no superfluous logged records. */
313 EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
314 EXPECT_EQ(0, records.access);
315 EXPECT_EQ(0, records.domain);
316
317 ASSERT_EQ(0, pipe2(pipe_child, O_CLOEXEC));
318 ASSERT_EQ(0, pipe2(pipe_parent, O_CLOEXEC));
319
320 child = fork();
321 ASSERT_LE(0, child);
322 if (child == 0) {
323 int dgram_server;
324
325 EXPECT_EQ(0, close(pipe_parent[1]));
326 EXPECT_EQ(0, close(pipe_child[0]));
327
328 /* Waits for the parent to be in a domain. */
329 ASSERT_EQ(1, read(pipe_parent[0], &buf, 1));
330
331 dgram_server = socket(AF_UNIX, SOCK_DGRAM, 0);
332 ASSERT_LE(0, dgram_server);
333 ASSERT_EQ(0, bind(dgram_server, &self->dgram_address.unix_addr,
334 self->dgram_address.unix_addr_len));
335
336 /* Signals to the parent that child is listening. */
337 ASSERT_EQ(1, write(pipe_child[1], ".", 1));
338
339 /* Waits to connect. */
340 ASSERT_EQ(1, read(pipe_parent[0], &buf, 1));
341 EXPECT_EQ(0, close(dgram_server));
342 _exit(_metadata->exit_code);
343 return;
344 }
345 EXPECT_EQ(0, close(pipe_child[1]));
346 EXPECT_EQ(0, close(pipe_parent[0]));
347
348 create_scoped_domain(_metadata, LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET);
349
350 /* Signals that the parent is in a domain, if any. */
351 ASSERT_EQ(1, write(pipe_parent[1], ".", 1));
352
353 dgram_client = socket(AF_UNIX, SOCK_DGRAM, 0);
354 ASSERT_LE(0, dgram_client);
355
356 /* Waits for the child to listen */
357 ASSERT_EQ(1, read(pipe_child[0], &buf, 1));
358 err_dgram = connect(dgram_client, &self->dgram_address.unix_addr,
359 self->dgram_address.unix_addr_len);
360 EXPECT_EQ(-1, err_dgram);
361 EXPECT_EQ(EPERM, errno);
362
363 EXPECT_EQ(
364 0,
365 audit_match_record(
366 self->audit_fd, AUDIT_LANDLOCK_ACCESS,
367 REGEX_LANDLOCK_PREFIX
368 " blockers=scope\\.abstract_unix_socket path=" ABSTRACT_SOCKET_PATH_PREFIX
369 "[0-9A-F]\\+$",
370 NULL));
371
372 ASSERT_EQ(1, write(pipe_parent[1], ".", 1));
373 EXPECT_EQ(0, close(dgram_client));
374
375 ASSERT_EQ(child, waitpid(child, &status, 0));
376 if (WIFSIGNALED(status) || !WIFEXITED(status) ||
377 WEXITSTATUS(status) != EXIT_SUCCESS)
378 _metadata->exit_code = KSFT_FAIL;
379 }
380
FIXTURE(scoped_vs_unscoped)381 FIXTURE(scoped_vs_unscoped)
382 {
383 struct service_fixture parent_stream_address, parent_dgram_address,
384 child_stream_address, child_dgram_address;
385 };
386
387 #include "scoped_multiple_domain_variants.h"
388
FIXTURE_SETUP(scoped_vs_unscoped)389 FIXTURE_SETUP(scoped_vs_unscoped)
390 {
391 drop_caps(_metadata);
392
393 memset(&self->parent_stream_address, 0,
394 sizeof(self->parent_stream_address));
395 set_unix_address(&self->parent_stream_address, 0);
396 memset(&self->parent_dgram_address, 0,
397 sizeof(self->parent_dgram_address));
398 set_unix_address(&self->parent_dgram_address, 1);
399 memset(&self->child_stream_address, 0,
400 sizeof(self->child_stream_address));
401 set_unix_address(&self->child_stream_address, 2);
402 memset(&self->child_dgram_address, 0,
403 sizeof(self->child_dgram_address));
404 set_unix_address(&self->child_dgram_address, 3);
405 }
406
FIXTURE_TEARDOWN(scoped_vs_unscoped)407 FIXTURE_TEARDOWN(scoped_vs_unscoped)
408 {
409 }
410
411 /*
412 * Test unix_stream_connect and unix_may_send for parent, child and
413 * grand child processes when they can have scoped or non-scoped domains.
414 */
TEST_F(scoped_vs_unscoped,unix_scoping)415 TEST_F(scoped_vs_unscoped, unix_scoping)
416 {
417 pid_t child;
418 int status;
419 bool can_connect_to_parent, can_connect_to_child;
420 int pipe_parent[2];
421 int stream_server_parent, dgram_server_parent;
422
423 can_connect_to_child = (variant->domain_grand_child != SCOPE_SANDBOX);
424 can_connect_to_parent = (can_connect_to_child &&
425 (variant->domain_children != SCOPE_SANDBOX));
426
427 ASSERT_EQ(0, pipe2(pipe_parent, O_CLOEXEC));
428
429 if (variant->domain_all == OTHER_SANDBOX)
430 create_fs_domain(_metadata);
431 else if (variant->domain_all == SCOPE_SANDBOX)
432 create_scoped_domain(_metadata,
433 LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET);
434
435 child = fork();
436 ASSERT_LE(0, child);
437 if (child == 0) {
438 int stream_server_child, dgram_server_child;
439 int pipe_child[2];
440 pid_t grand_child;
441
442 ASSERT_EQ(0, pipe2(pipe_child, O_CLOEXEC));
443
444 if (variant->domain_children == OTHER_SANDBOX)
445 create_fs_domain(_metadata);
446 else if (variant->domain_children == SCOPE_SANDBOX)
447 create_scoped_domain(
448 _metadata, LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET);
449
450 grand_child = fork();
451 ASSERT_LE(0, grand_child);
452 if (grand_child == 0) {
453 char buf;
454 int stream_err, dgram_err, stream_errno, dgram_errno;
455 int stream_client, dgram_client;
456
457 EXPECT_EQ(0, close(pipe_parent[1]));
458 EXPECT_EQ(0, close(pipe_child[1]));
459
460 if (variant->domain_grand_child == OTHER_SANDBOX)
461 create_fs_domain(_metadata);
462 else if (variant->domain_grand_child == SCOPE_SANDBOX)
463 create_scoped_domain(
464 _metadata,
465 LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET);
466
467 stream_client = socket(AF_UNIX, SOCK_STREAM, 0);
468 ASSERT_LE(0, stream_client);
469 dgram_client = socket(AF_UNIX, SOCK_DGRAM, 0);
470 ASSERT_LE(0, dgram_client);
471
472 ASSERT_EQ(1, read(pipe_child[0], &buf, 1));
473 stream_err = connect(
474 stream_client,
475 &self->child_stream_address.unix_addr,
476 self->child_stream_address.unix_addr_len);
477 stream_errno = errno;
478 dgram_err = connect(
479 dgram_client,
480 &self->child_dgram_address.unix_addr,
481 self->child_dgram_address.unix_addr_len);
482 dgram_errno = errno;
483 if (can_connect_to_child) {
484 EXPECT_EQ(0, stream_err);
485 EXPECT_EQ(0, dgram_err);
486 } else {
487 EXPECT_EQ(-1, stream_err);
488 EXPECT_EQ(-1, dgram_err);
489 EXPECT_EQ(EPERM, stream_errno);
490 EXPECT_EQ(EPERM, dgram_errno);
491 }
492
493 EXPECT_EQ(0, close(stream_client));
494 stream_client = socket(AF_UNIX, SOCK_STREAM, 0);
495 ASSERT_LE(0, stream_client);
496 /* Datagram sockets can "reconnect". */
497
498 ASSERT_EQ(1, read(pipe_parent[0], &buf, 1));
499 stream_err = connect(
500 stream_client,
501 &self->parent_stream_address.unix_addr,
502 self->parent_stream_address.unix_addr_len);
503 stream_errno = errno;
504 dgram_err = connect(
505 dgram_client,
506 &self->parent_dgram_address.unix_addr,
507 self->parent_dgram_address.unix_addr_len);
508 dgram_errno = errno;
509 if (can_connect_to_parent) {
510 EXPECT_EQ(0, stream_err);
511 EXPECT_EQ(0, dgram_err);
512 } else {
513 EXPECT_EQ(-1, stream_err);
514 EXPECT_EQ(-1, dgram_err);
515 EXPECT_EQ(EPERM, stream_errno);
516 EXPECT_EQ(EPERM, dgram_errno);
517 }
518 EXPECT_EQ(0, close(stream_client));
519 EXPECT_EQ(0, close(dgram_client));
520
521 _exit(_metadata->exit_code);
522 return;
523 }
524 EXPECT_EQ(0, close(pipe_child[0]));
525 if (variant->domain_child == OTHER_SANDBOX)
526 create_fs_domain(_metadata);
527 else if (variant->domain_child == SCOPE_SANDBOX)
528 create_scoped_domain(
529 _metadata, LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET);
530
531 stream_server_child = socket(AF_UNIX, SOCK_STREAM, 0);
532 ASSERT_LE(0, stream_server_child);
533 dgram_server_child = socket(AF_UNIX, SOCK_DGRAM, 0);
534 ASSERT_LE(0, dgram_server_child);
535
536 ASSERT_EQ(0, bind(stream_server_child,
537 &self->child_stream_address.unix_addr,
538 self->child_stream_address.unix_addr_len));
539 ASSERT_EQ(0, bind(dgram_server_child,
540 &self->child_dgram_address.unix_addr,
541 self->child_dgram_address.unix_addr_len));
542 ASSERT_EQ(0, listen(stream_server_child, backlog));
543
544 ASSERT_EQ(1, write(pipe_child[1], ".", 1));
545 ASSERT_EQ(grand_child, waitpid(grand_child, &status, 0));
546 EXPECT_EQ(0, close(stream_server_child))
547 EXPECT_EQ(0, close(dgram_server_child));
548 return;
549 }
550 EXPECT_EQ(0, close(pipe_parent[0]));
551
552 if (variant->domain_parent == OTHER_SANDBOX)
553 create_fs_domain(_metadata);
554 else if (variant->domain_parent == SCOPE_SANDBOX)
555 create_scoped_domain(_metadata,
556 LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET);
557
558 stream_server_parent = socket(AF_UNIX, SOCK_STREAM, 0);
559 ASSERT_LE(0, stream_server_parent);
560 dgram_server_parent = socket(AF_UNIX, SOCK_DGRAM, 0);
561 ASSERT_LE(0, dgram_server_parent);
562 ASSERT_EQ(0, bind(stream_server_parent,
563 &self->parent_stream_address.unix_addr,
564 self->parent_stream_address.unix_addr_len));
565 ASSERT_EQ(0, bind(dgram_server_parent,
566 &self->parent_dgram_address.unix_addr,
567 self->parent_dgram_address.unix_addr_len));
568
569 ASSERT_EQ(0, listen(stream_server_parent, backlog));
570
571 ASSERT_EQ(1, write(pipe_parent[1], ".", 1));
572 ASSERT_EQ(child, waitpid(child, &status, 0));
573 EXPECT_EQ(0, close(stream_server_parent));
574 EXPECT_EQ(0, close(dgram_server_parent));
575
576 if (WIFSIGNALED(status) || !WIFEXITED(status) ||
577 WEXITSTATUS(status) != EXIT_SUCCESS)
578 _metadata->exit_code = KSFT_FAIL;
579 }
580
FIXTURE(outside_socket)581 FIXTURE(outside_socket)
582 {
583 struct service_fixture address, transit_address;
584 };
585
FIXTURE_VARIANT(outside_socket)586 FIXTURE_VARIANT(outside_socket)
587 {
588 const bool child_socket;
589 const int type;
590 };
591
592 /* clang-format off */
FIXTURE_VARIANT_ADD(outside_socket,allow_dgram_child)593 FIXTURE_VARIANT_ADD(outside_socket, allow_dgram_child) {
594 /* clang-format on */
595 .child_socket = true,
596 .type = SOCK_DGRAM,
597 };
598
599 /* clang-format off */
FIXTURE_VARIANT_ADD(outside_socket,deny_dgram_server)600 FIXTURE_VARIANT_ADD(outside_socket, deny_dgram_server) {
601 /* clang-format on */
602 .child_socket = false,
603 .type = SOCK_DGRAM,
604 };
605
606 /* clang-format off */
FIXTURE_VARIANT_ADD(outside_socket,allow_stream_child)607 FIXTURE_VARIANT_ADD(outside_socket, allow_stream_child) {
608 /* clang-format on */
609 .child_socket = true,
610 .type = SOCK_STREAM,
611 };
612
613 /* clang-format off */
FIXTURE_VARIANT_ADD(outside_socket,deny_stream_server)614 FIXTURE_VARIANT_ADD(outside_socket, deny_stream_server) {
615 /* clang-format on */
616 .child_socket = false,
617 .type = SOCK_STREAM,
618 };
619
FIXTURE_SETUP(outside_socket)620 FIXTURE_SETUP(outside_socket)
621 {
622 drop_caps(_metadata);
623
624 memset(&self->transit_address, 0, sizeof(self->transit_address));
625 set_unix_address(&self->transit_address, 0);
626 memset(&self->address, 0, sizeof(self->address));
627 set_unix_address(&self->address, 1);
628 }
629
FIXTURE_TEARDOWN(outside_socket)630 FIXTURE_TEARDOWN(outside_socket)
631 {
632 }
633
634 /*
635 * Test unix_stream_connect and unix_may_send for parent and child processes
636 * when connecting socket has different domain than the process using it.
637 */
TEST_F(outside_socket,socket_with_different_domain)638 TEST_F(outside_socket, socket_with_different_domain)
639 {
640 pid_t child;
641 int err, status;
642 int pipe_child[2], pipe_parent[2];
643 char buf_parent;
644 int server_socket;
645
646 ASSERT_EQ(0, pipe2(pipe_child, O_CLOEXEC));
647 ASSERT_EQ(0, pipe2(pipe_parent, O_CLOEXEC));
648
649 child = fork();
650 ASSERT_LE(0, child);
651 if (child == 0) {
652 int client_socket;
653 char buf_child;
654
655 EXPECT_EQ(0, close(pipe_parent[1]));
656 EXPECT_EQ(0, close(pipe_child[0]));
657
658 /* Client always has a domain. */
659 create_scoped_domain(_metadata,
660 LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET);
661
662 if (variant->child_socket) {
663 int data_socket, passed_socket, stream_server;
664
665 passed_socket = socket(AF_UNIX, variant->type, 0);
666 ASSERT_LE(0, passed_socket);
667 stream_server = socket(AF_UNIX, SOCK_STREAM, 0);
668 ASSERT_LE(0, stream_server);
669 ASSERT_EQ(0, bind(stream_server,
670 &self->transit_address.unix_addr,
671 self->transit_address.unix_addr_len));
672 ASSERT_EQ(0, listen(stream_server, backlog));
673 ASSERT_EQ(1, write(pipe_child[1], ".", 1));
674 data_socket = accept(stream_server, NULL, NULL);
675 ASSERT_LE(0, data_socket);
676 ASSERT_EQ(0, send_fd(data_socket, passed_socket));
677 EXPECT_EQ(0, close(passed_socket));
678 EXPECT_EQ(0, close(stream_server));
679 }
680
681 client_socket = socket(AF_UNIX, variant->type, 0);
682 ASSERT_LE(0, client_socket);
683
684 /* Waits for parent signal for connection. */
685 ASSERT_EQ(1, read(pipe_parent[0], &buf_child, 1));
686 err = connect(client_socket, &self->address.unix_addr,
687 self->address.unix_addr_len);
688 if (variant->child_socket) {
689 EXPECT_EQ(0, err);
690 } else {
691 EXPECT_EQ(-1, err);
692 EXPECT_EQ(EPERM, errno);
693 }
694 EXPECT_EQ(0, close(client_socket));
695 _exit(_metadata->exit_code);
696 return;
697 }
698 EXPECT_EQ(0, close(pipe_child[1]));
699 EXPECT_EQ(0, close(pipe_parent[0]));
700
701 if (variant->child_socket) {
702 int client_child = socket(AF_UNIX, SOCK_STREAM, 0);
703
704 ASSERT_LE(0, client_child);
705 ASSERT_EQ(1, read(pipe_child[0], &buf_parent, 1));
706 ASSERT_EQ(0, connect(client_child,
707 &self->transit_address.unix_addr,
708 self->transit_address.unix_addr_len));
709 server_socket = recv_fd(client_child);
710 EXPECT_EQ(0, close(client_child));
711 } else {
712 server_socket = socket(AF_UNIX, variant->type, 0);
713 }
714 ASSERT_LE(0, server_socket);
715
716 /* Server always has a domain. */
717 create_scoped_domain(_metadata, LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET);
718
719 ASSERT_EQ(0, bind(server_socket, &self->address.unix_addr,
720 self->address.unix_addr_len));
721 if (variant->type == SOCK_STREAM)
722 ASSERT_EQ(0, listen(server_socket, backlog));
723
724 /* Signals to child that the parent is listening. */
725 ASSERT_EQ(1, write(pipe_parent[1], ".", 1));
726
727 ASSERT_EQ(child, waitpid(child, &status, 0));
728 EXPECT_EQ(0, close(server_socket));
729
730 if (WIFSIGNALED(status) || !WIFEXITED(status) ||
731 WEXITSTATUS(status) != EXIT_SUCCESS)
732 _metadata->exit_code = KSFT_FAIL;
733 }
734
735 static const char stream_path[] = TMP_DIR "/stream.sock";
736 static const char dgram_path[] = TMP_DIR "/dgram.sock";
737
738 /* clang-format off */
FIXTURE(various_address_sockets)739 FIXTURE(various_address_sockets) {};
740 /* clang-format on */
741
FIXTURE_VARIANT(various_address_sockets)742 FIXTURE_VARIANT(various_address_sockets)
743 {
744 const int domain;
745 };
746
747 /* clang-format off */
FIXTURE_VARIANT_ADD(various_address_sockets,pathname_socket_scoped_domain)748 FIXTURE_VARIANT_ADD(various_address_sockets, pathname_socket_scoped_domain) {
749 /* clang-format on */
750 .domain = SCOPE_SANDBOX,
751 };
752
753 /* clang-format off */
FIXTURE_VARIANT_ADD(various_address_sockets,pathname_socket_other_domain)754 FIXTURE_VARIANT_ADD(various_address_sockets, pathname_socket_other_domain) {
755 /* clang-format on */
756 .domain = OTHER_SANDBOX,
757 };
758
759 /* clang-format off */
FIXTURE_VARIANT_ADD(various_address_sockets,pathname_socket_no_domain)760 FIXTURE_VARIANT_ADD(various_address_sockets, pathname_socket_no_domain) {
761 /* clang-format on */
762 .domain = NO_SANDBOX,
763 };
764
FIXTURE_SETUP(various_address_sockets)765 FIXTURE_SETUP(various_address_sockets)
766 {
767 drop_caps(_metadata);
768
769 umask(0077);
770 ASSERT_EQ(0, mkdir(TMP_DIR, 0700));
771 }
772
FIXTURE_TEARDOWN(various_address_sockets)773 FIXTURE_TEARDOWN(various_address_sockets)
774 {
775 EXPECT_EQ(0, unlink(stream_path));
776 EXPECT_EQ(0, unlink(dgram_path));
777 EXPECT_EQ(0, rmdir(TMP_DIR));
778 }
779
TEST_F(various_address_sockets,scoped_pathname_sockets)780 TEST_F(various_address_sockets, scoped_pathname_sockets)
781 {
782 socklen_t size_stream, size_dgram;
783 pid_t child;
784 int status;
785 char buf_child, buf_parent;
786 int pipe_parent[2];
787 int unnamed_sockets[2];
788 int stream_pathname_socket, dgram_pathname_socket,
789 stream_abstract_socket, dgram_abstract_socket, data_socket;
790 struct service_fixture stream_abstract_addr, dgram_abstract_addr;
791 struct sockaddr_un stream_pathname_addr = {
792 .sun_family = AF_UNIX,
793 };
794 struct sockaddr_un dgram_pathname_addr = {
795 .sun_family = AF_UNIX,
796 };
797
798 /* Pathname address. */
799 snprintf(stream_pathname_addr.sun_path,
800 sizeof(stream_pathname_addr.sun_path), "%s", stream_path);
801 size_stream = offsetof(struct sockaddr_un, sun_path) +
802 strlen(stream_pathname_addr.sun_path);
803 snprintf(dgram_pathname_addr.sun_path,
804 sizeof(dgram_pathname_addr.sun_path), "%s", dgram_path);
805 size_dgram = offsetof(struct sockaddr_un, sun_path) +
806 strlen(dgram_pathname_addr.sun_path);
807
808 /* Abstract address. */
809 memset(&stream_abstract_addr, 0, sizeof(stream_abstract_addr));
810 set_unix_address(&stream_abstract_addr, 0);
811 memset(&dgram_abstract_addr, 0, sizeof(dgram_abstract_addr));
812 set_unix_address(&dgram_abstract_addr, 1);
813
814 /* Unnamed address for datagram socket. */
815 ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_DGRAM, 0, unnamed_sockets));
816
817 ASSERT_EQ(0, pipe2(pipe_parent, O_CLOEXEC));
818
819 child = fork();
820 ASSERT_LE(0, child);
821 if (child == 0) {
822 int err;
823
824 EXPECT_EQ(0, close(pipe_parent[1]));
825 EXPECT_EQ(0, close(unnamed_sockets[1]));
826
827 if (variant->domain == SCOPE_SANDBOX)
828 create_scoped_domain(
829 _metadata, LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET);
830 else if (variant->domain == OTHER_SANDBOX)
831 create_fs_domain(_metadata);
832
833 /* Waits for parent to listen. */
834 ASSERT_EQ(1, read(pipe_parent[0], &buf_child, 1));
835 EXPECT_EQ(0, close(pipe_parent[0]));
836
837 /* Checks that we can send data through a datagram socket. */
838 ASSERT_EQ(1, write(unnamed_sockets[0], "a", 1));
839 EXPECT_EQ(0, close(unnamed_sockets[0]));
840
841 /* Connects with pathname sockets. */
842 stream_pathname_socket = socket(AF_UNIX, SOCK_STREAM, 0);
843 ASSERT_LE(0, stream_pathname_socket);
844 ASSERT_EQ(0, connect(stream_pathname_socket,
845 &stream_pathname_addr, size_stream));
846 ASSERT_EQ(1, write(stream_pathname_socket, "b", 1));
847 EXPECT_EQ(0, close(stream_pathname_socket));
848
849 /* Sends without connection. */
850 dgram_pathname_socket = socket(AF_UNIX, SOCK_DGRAM, 0);
851 ASSERT_LE(0, dgram_pathname_socket);
852 err = sendto(dgram_pathname_socket, "c", 1, 0,
853 &dgram_pathname_addr, size_dgram);
854 EXPECT_EQ(1, err);
855
856 /* Sends with connection. */
857 ASSERT_EQ(0, connect(dgram_pathname_socket,
858 &dgram_pathname_addr, size_dgram));
859 ASSERT_EQ(1, write(dgram_pathname_socket, "d", 1));
860 EXPECT_EQ(0, close(dgram_pathname_socket));
861
862 /* Connects with abstract sockets. */
863 stream_abstract_socket = socket(AF_UNIX, SOCK_STREAM, 0);
864 ASSERT_LE(0, stream_abstract_socket);
865 err = connect(stream_abstract_socket,
866 &stream_abstract_addr.unix_addr,
867 stream_abstract_addr.unix_addr_len);
868 if (variant->domain == SCOPE_SANDBOX) {
869 EXPECT_EQ(-1, err);
870 EXPECT_EQ(EPERM, errno);
871 } else {
872 EXPECT_EQ(0, err);
873 ASSERT_EQ(1, write(stream_abstract_socket, "e", 1));
874 }
875 EXPECT_EQ(0, close(stream_abstract_socket));
876
877 /* Sends without connection. */
878 dgram_abstract_socket = socket(AF_UNIX, SOCK_DGRAM, 0);
879 ASSERT_LE(0, dgram_abstract_socket);
880 err = sendto(dgram_abstract_socket, "f", 1, 0,
881 &dgram_abstract_addr.unix_addr,
882 dgram_abstract_addr.unix_addr_len);
883 if (variant->domain == SCOPE_SANDBOX) {
884 EXPECT_EQ(-1, err);
885 EXPECT_EQ(EPERM, errno);
886 } else {
887 EXPECT_EQ(1, err);
888 }
889
890 /* Sends with connection. */
891 err = connect(dgram_abstract_socket,
892 &dgram_abstract_addr.unix_addr,
893 dgram_abstract_addr.unix_addr_len);
894 if (variant->domain == SCOPE_SANDBOX) {
895 EXPECT_EQ(-1, err);
896 EXPECT_EQ(EPERM, errno);
897 } else {
898 EXPECT_EQ(0, err);
899 ASSERT_EQ(1, write(dgram_abstract_socket, "g", 1));
900 }
901 EXPECT_EQ(0, close(dgram_abstract_socket));
902
903 _exit(_metadata->exit_code);
904 return;
905 }
906 EXPECT_EQ(0, close(pipe_parent[0]));
907 EXPECT_EQ(0, close(unnamed_sockets[0]));
908
909 /* Sets up pathname servers. */
910 stream_pathname_socket = socket(AF_UNIX, SOCK_STREAM, 0);
911 ASSERT_LE(0, stream_pathname_socket);
912 ASSERT_EQ(0, bind(stream_pathname_socket, &stream_pathname_addr,
913 size_stream));
914 ASSERT_EQ(0, listen(stream_pathname_socket, backlog));
915
916 dgram_pathname_socket = socket(AF_UNIX, SOCK_DGRAM, 0);
917 ASSERT_LE(0, dgram_pathname_socket);
918 ASSERT_EQ(0, bind(dgram_pathname_socket, &dgram_pathname_addr,
919 size_dgram));
920
921 /* Sets up abstract servers. */
922 stream_abstract_socket = socket(AF_UNIX, SOCK_STREAM, 0);
923 ASSERT_LE(0, stream_abstract_socket);
924 ASSERT_EQ(0,
925 bind(stream_abstract_socket, &stream_abstract_addr.unix_addr,
926 stream_abstract_addr.unix_addr_len));
927
928 dgram_abstract_socket = socket(AF_UNIX, SOCK_DGRAM, 0);
929 ASSERT_LE(0, dgram_abstract_socket);
930 ASSERT_EQ(0, bind(dgram_abstract_socket, &dgram_abstract_addr.unix_addr,
931 dgram_abstract_addr.unix_addr_len));
932 ASSERT_EQ(0, listen(stream_abstract_socket, backlog));
933
934 ASSERT_EQ(1, write(pipe_parent[1], ".", 1));
935 EXPECT_EQ(0, close(pipe_parent[1]));
936
937 /* Reads from unnamed socket. */
938 ASSERT_EQ(1, read(unnamed_sockets[1], &buf_parent, sizeof(buf_parent)));
939 ASSERT_EQ('a', buf_parent);
940 EXPECT_LE(0, close(unnamed_sockets[1]));
941
942 /* Reads from pathname sockets. */
943 data_socket = accept(stream_pathname_socket, NULL, NULL);
944 ASSERT_LE(0, data_socket);
945 ASSERT_EQ(1, read(data_socket, &buf_parent, sizeof(buf_parent)));
946 ASSERT_EQ('b', buf_parent);
947 EXPECT_EQ(0, close(data_socket));
948 EXPECT_EQ(0, close(stream_pathname_socket));
949
950 ASSERT_EQ(1,
951 read(dgram_pathname_socket, &buf_parent, sizeof(buf_parent)));
952 ASSERT_EQ('c', buf_parent);
953 ASSERT_EQ(1,
954 read(dgram_pathname_socket, &buf_parent, sizeof(buf_parent)));
955 ASSERT_EQ('d', buf_parent);
956 EXPECT_EQ(0, close(dgram_pathname_socket));
957
958 if (variant->domain != SCOPE_SANDBOX) {
959 /* Reads from abstract sockets if allowed to send. */
960 data_socket = accept(stream_abstract_socket, NULL, NULL);
961 ASSERT_LE(0, data_socket);
962 ASSERT_EQ(1,
963 read(data_socket, &buf_parent, sizeof(buf_parent)));
964 ASSERT_EQ('e', buf_parent);
965 EXPECT_EQ(0, close(data_socket));
966
967 ASSERT_EQ(1, read(dgram_abstract_socket, &buf_parent,
968 sizeof(buf_parent)));
969 ASSERT_EQ('f', buf_parent);
970 ASSERT_EQ(1, read(dgram_abstract_socket, &buf_parent,
971 sizeof(buf_parent)));
972 ASSERT_EQ('g', buf_parent);
973 }
974
975 /* Waits for all abstract socket tests. */
976 ASSERT_EQ(child, waitpid(child, &status, 0));
977 EXPECT_EQ(0, close(stream_abstract_socket));
978 EXPECT_EQ(0, close(dgram_abstract_socket));
979
980 if (WIFSIGNALED(status) || !WIFEXITED(status) ||
981 WEXITSTATUS(status) != EXIT_SUCCESS)
982 _metadata->exit_code = KSFT_FAIL;
983 }
984
TEST(datagram_sockets)985 TEST(datagram_sockets)
986 {
987 struct service_fixture connected_addr, non_connected_addr;
988 int server_conn_socket, server_unconn_socket;
989 int pipe_parent[2], pipe_child[2];
990 int status;
991 char buf;
992 pid_t child;
993
994 drop_caps(_metadata);
995 memset(&connected_addr, 0, sizeof(connected_addr));
996 set_unix_address(&connected_addr, 0);
997 memset(&non_connected_addr, 0, sizeof(non_connected_addr));
998 set_unix_address(&non_connected_addr, 1);
999
1000 ASSERT_EQ(0, pipe2(pipe_parent, O_CLOEXEC));
1001 ASSERT_EQ(0, pipe2(pipe_child, O_CLOEXEC));
1002
1003 child = fork();
1004 ASSERT_LE(0, child);
1005 if (child == 0) {
1006 int client_conn_socket, client_unconn_socket;
1007
1008 EXPECT_EQ(0, close(pipe_parent[1]));
1009 EXPECT_EQ(0, close(pipe_child[0]));
1010
1011 client_conn_socket = socket(AF_UNIX, SOCK_DGRAM, 0);
1012 client_unconn_socket = socket(AF_UNIX, SOCK_DGRAM, 0);
1013 ASSERT_LE(0, client_conn_socket);
1014 ASSERT_LE(0, client_unconn_socket);
1015
1016 /* Waits for parent to listen. */
1017 ASSERT_EQ(1, read(pipe_parent[0], &buf, 1));
1018 ASSERT_EQ(0,
1019 connect(client_conn_socket, &connected_addr.unix_addr,
1020 connected_addr.unix_addr_len));
1021
1022 /*
1023 * Both connected and non-connected sockets can send data when
1024 * the domain is not scoped.
1025 */
1026 ASSERT_EQ(1, send(client_conn_socket, ".", 1, 0));
1027 ASSERT_EQ(1, sendto(client_unconn_socket, ".", 1, 0,
1028 &non_connected_addr.unix_addr,
1029 non_connected_addr.unix_addr_len));
1030 ASSERT_EQ(1, write(pipe_child[1], ".", 1));
1031
1032 /* Scopes the domain. */
1033 create_scoped_domain(_metadata,
1034 LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET);
1035
1036 /*
1037 * Connected socket sends data to the receiver, but the
1038 * non-connected socket must fail to send data.
1039 */
1040 ASSERT_EQ(1, send(client_conn_socket, ".", 1, 0));
1041 ASSERT_EQ(-1, sendto(client_unconn_socket, ".", 1, 0,
1042 &non_connected_addr.unix_addr,
1043 non_connected_addr.unix_addr_len));
1044 ASSERT_EQ(EPERM, errno);
1045 ASSERT_EQ(1, write(pipe_child[1], ".", 1));
1046
1047 EXPECT_EQ(0, close(client_conn_socket));
1048 EXPECT_EQ(0, close(client_unconn_socket));
1049 _exit(_metadata->exit_code);
1050 return;
1051 }
1052 EXPECT_EQ(0, close(pipe_parent[0]));
1053 EXPECT_EQ(0, close(pipe_child[1]));
1054
1055 server_conn_socket = socket(AF_UNIX, SOCK_DGRAM, 0);
1056 server_unconn_socket = socket(AF_UNIX, SOCK_DGRAM, 0);
1057 ASSERT_LE(0, server_conn_socket);
1058 ASSERT_LE(0, server_unconn_socket);
1059
1060 ASSERT_EQ(0, bind(server_conn_socket, &connected_addr.unix_addr,
1061 connected_addr.unix_addr_len));
1062 ASSERT_EQ(0, bind(server_unconn_socket, &non_connected_addr.unix_addr,
1063 non_connected_addr.unix_addr_len));
1064 ASSERT_EQ(1, write(pipe_parent[1], ".", 1));
1065
1066 /* Waits for child to test. */
1067 ASSERT_EQ(1, read(pipe_child[0], &buf, 1));
1068 ASSERT_EQ(1, recv(server_conn_socket, &buf, 1, 0));
1069 ASSERT_EQ(1, recv(server_unconn_socket, &buf, 1, 0));
1070
1071 /*
1072 * Connected datagram socket will receive data, but
1073 * non-connected datagram socket does not receive data.
1074 */
1075 ASSERT_EQ(1, read(pipe_child[0], &buf, 1));
1076 ASSERT_EQ(1, recv(server_conn_socket, &buf, 1, 0));
1077
1078 /* Waits for all tests to finish. */
1079 ASSERT_EQ(child, waitpid(child, &status, 0));
1080 EXPECT_EQ(0, close(server_conn_socket));
1081 EXPECT_EQ(0, close(server_unconn_socket));
1082
1083 if (WIFSIGNALED(status) || !WIFEXITED(status) ||
1084 WEXITSTATUS(status) != EXIT_SUCCESS)
1085 _metadata->exit_code = KSFT_FAIL;
1086 }
1087
TEST(self_connect)1088 TEST(self_connect)
1089 {
1090 struct service_fixture connected_addr, non_connected_addr;
1091 int connected_socket, non_connected_socket, status;
1092 pid_t child;
1093
1094 drop_caps(_metadata);
1095 memset(&connected_addr, 0, sizeof(connected_addr));
1096 set_unix_address(&connected_addr, 0);
1097 memset(&non_connected_addr, 0, sizeof(non_connected_addr));
1098 set_unix_address(&non_connected_addr, 1);
1099
1100 connected_socket = socket(AF_UNIX, SOCK_DGRAM, 0);
1101 non_connected_socket = socket(AF_UNIX, SOCK_DGRAM, 0);
1102 ASSERT_LE(0, connected_socket);
1103 ASSERT_LE(0, non_connected_socket);
1104
1105 ASSERT_EQ(0, bind(connected_socket, &connected_addr.unix_addr,
1106 connected_addr.unix_addr_len));
1107 ASSERT_EQ(0, bind(non_connected_socket, &non_connected_addr.unix_addr,
1108 non_connected_addr.unix_addr_len));
1109
1110 child = fork();
1111 ASSERT_LE(0, child);
1112 if (child == 0) {
1113 /* Child's domain is scoped. */
1114 create_scoped_domain(_metadata,
1115 LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET);
1116
1117 /*
1118 * The child inherits the sockets, and cannot connect or
1119 * send data to them.
1120 */
1121 ASSERT_EQ(-1,
1122 connect(connected_socket, &connected_addr.unix_addr,
1123 connected_addr.unix_addr_len));
1124 ASSERT_EQ(EPERM, errno);
1125
1126 ASSERT_EQ(-1, sendto(connected_socket, ".", 1, 0,
1127 &connected_addr.unix_addr,
1128 connected_addr.unix_addr_len));
1129 ASSERT_EQ(EPERM, errno);
1130
1131 ASSERT_EQ(-1, sendto(non_connected_socket, ".", 1, 0,
1132 &non_connected_addr.unix_addr,
1133 non_connected_addr.unix_addr_len));
1134 ASSERT_EQ(EPERM, errno);
1135
1136 EXPECT_EQ(0, close(connected_socket));
1137 EXPECT_EQ(0, close(non_connected_socket));
1138 _exit(_metadata->exit_code);
1139 return;
1140 }
1141
1142 /* Waits for all tests to finish. */
1143 ASSERT_EQ(child, waitpid(child, &status, 0));
1144 EXPECT_EQ(0, close(connected_socket));
1145 EXPECT_EQ(0, close(non_connected_socket));
1146
1147 if (WIFSIGNALED(status) || !WIFEXITED(status) ||
1148 WEXITSTATUS(status) != EXIT_SUCCESS)
1149 _metadata->exit_code = KSFT_FAIL;
1150 }
1151
1152 TEST_HARNESS_MAIN
1153