1 // SPDX-License-Identifier: GPL-2.0
3 * Landlock tests - Abstract UNIX socket
5 * Copyright © 2024 Tahera Fahimi <fahimitahera@gmail.com>
11 #include <linux/landlock.h>
15 #include <sys/prctl.h>
16 #include <sys/socket.h>
18 #include <sys/types.h>
24 #include "scoped_common.h"
26 /* Number of pending connections queue to be hold. */
27 const short backlog
= 10;
29 static void create_fs_domain(struct __test_metadata
*const _metadata
)
32 struct landlock_ruleset_attr ruleset_attr
= {
33 .handled_access_fs
= LANDLOCK_ACCESS_FS_READ_DIR
,
37 landlock_create_ruleset(&ruleset_attr
, sizeof(ruleset_attr
), 0);
38 EXPECT_LE(0, ruleset_fd
)
40 TH_LOG("Failed to create a ruleset: %s", strerror(errno
));
42 EXPECT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS
, 1, 0, 0, 0));
43 EXPECT_EQ(0, landlock_restrict_self(ruleset_fd
, 0));
44 EXPECT_EQ(0, close(ruleset_fd
));
47 FIXTURE(scoped_domains
)
49 struct service_fixture stream_address
, dgram_address
;
52 #include "scoped_base_variants.h"
54 FIXTURE_SETUP(scoped_domains
)
58 memset(&self
->stream_address
, 0, sizeof(self
->stream_address
));
59 memset(&self
->dgram_address
, 0, sizeof(self
->dgram_address
));
60 set_unix_address(&self
->stream_address
, 0);
61 set_unix_address(&self
->dgram_address
, 1);
64 FIXTURE_TEARDOWN(scoped_domains
)
69 * Test unix_stream_connect() and unix_may_send() for a child connecting to its
70 * parent, when they have scoped domain or no domain.
72 TEST_F(scoped_domains
, connect_to_parent
)
75 bool can_connect_to_parent
;
78 int stream_server
, dgram_server
;
81 * can_connect_to_parent is true if a child process can connect to its
82 * parent process. This depends on the child process not being isolated
83 * from the parent with a dedicated Landlock domain.
85 can_connect_to_parent
= !variant
->domain_child
;
87 ASSERT_EQ(0, pipe2(pipe_parent
, O_CLOEXEC
));
88 if (variant
->domain_both
) {
89 create_scoped_domain(_metadata
,
90 LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET
);
91 if (!__test_passed(_metadata
))
99 int stream_client
, dgram_client
;
102 EXPECT_EQ(0, close(pipe_parent
[1]));
103 if (variant
->domain_child
)
104 create_scoped_domain(
105 _metadata
, LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET
);
107 stream_client
= socket(AF_UNIX
, SOCK_STREAM
, 0);
108 ASSERT_LE(0, stream_client
);
109 dgram_client
= socket(AF_UNIX
, SOCK_DGRAM
, 0);
110 ASSERT_LE(0, dgram_client
);
112 /* Waits for the server. */
113 ASSERT_EQ(1, read(pipe_parent
[0], &buf_child
, 1));
115 err
= connect(stream_client
, &self
->stream_address
.unix_addr
,
116 self
->stream_address
.unix_addr_len
);
117 if (can_connect_to_parent
) {
121 EXPECT_EQ(EPERM
, errno
);
123 EXPECT_EQ(0, close(stream_client
));
125 err
= connect(dgram_client
, &self
->dgram_address
.unix_addr
,
126 self
->dgram_address
.unix_addr_len
);
127 if (can_connect_to_parent
) {
131 EXPECT_EQ(EPERM
, errno
);
133 EXPECT_EQ(0, close(dgram_client
));
134 _exit(_metadata
->exit_code
);
137 EXPECT_EQ(0, close(pipe_parent
[0]));
138 if (variant
->domain_parent
)
139 create_scoped_domain(_metadata
,
140 LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET
);
142 stream_server
= socket(AF_UNIX
, SOCK_STREAM
, 0);
143 ASSERT_LE(0, stream_server
);
144 dgram_server
= socket(AF_UNIX
, SOCK_DGRAM
, 0);
145 ASSERT_LE(0, dgram_server
);
146 ASSERT_EQ(0, bind(stream_server
, &self
->stream_address
.unix_addr
,
147 self
->stream_address
.unix_addr_len
));
148 ASSERT_EQ(0, bind(dgram_server
, &self
->dgram_address
.unix_addr
,
149 self
->dgram_address
.unix_addr_len
));
150 ASSERT_EQ(0, listen(stream_server
, backlog
));
152 /* Signals to child that the parent is listening. */
153 ASSERT_EQ(1, write(pipe_parent
[1], ".", 1));
155 ASSERT_EQ(child
, waitpid(child
, &status
, 0));
156 EXPECT_EQ(0, close(stream_server
));
157 EXPECT_EQ(0, close(dgram_server
));
159 if (WIFSIGNALED(status
) || !WIFEXITED(status
) ||
160 WEXITSTATUS(status
) != EXIT_SUCCESS
)
161 _metadata
->exit_code
= KSFT_FAIL
;
165 * Test unix_stream_connect() and unix_may_send() for a parent connecting to
166 * its child, when they have scoped domain or no domain.
168 TEST_F(scoped_domains
, connect_to_child
)
171 bool can_connect_to_child
;
172 int err_stream
, err_dgram
, errno_stream
, errno_dgram
, status
;
173 int pipe_child
[2], pipe_parent
[2];
175 int stream_client
, dgram_client
;
178 * can_connect_to_child is true if a parent process can connect to its
179 * child process. The parent process is not isolated from the child
180 * with a dedicated Landlock domain.
182 can_connect_to_child
= !variant
->domain_parent
;
184 ASSERT_EQ(0, pipe2(pipe_child
, O_CLOEXEC
));
185 ASSERT_EQ(0, pipe2(pipe_parent
, O_CLOEXEC
));
186 if (variant
->domain_both
) {
187 create_scoped_domain(_metadata
,
188 LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET
);
189 if (!__test_passed(_metadata
))
196 int stream_server
, dgram_server
;
198 EXPECT_EQ(0, close(pipe_parent
[1]));
199 EXPECT_EQ(0, close(pipe_child
[0]));
200 if (variant
->domain_child
)
201 create_scoped_domain(
202 _metadata
, LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET
);
204 /* Waits for the parent to be in a domain, if any. */
205 ASSERT_EQ(1, read(pipe_parent
[0], &buf
, 1));
207 stream_server
= socket(AF_UNIX
, SOCK_STREAM
, 0);
208 ASSERT_LE(0, stream_server
);
209 dgram_server
= socket(AF_UNIX
, SOCK_DGRAM
, 0);
210 ASSERT_LE(0, dgram_server
);
212 bind(stream_server
, &self
->stream_address
.unix_addr
,
213 self
->stream_address
.unix_addr_len
));
214 ASSERT_EQ(0, bind(dgram_server
, &self
->dgram_address
.unix_addr
,
215 self
->dgram_address
.unix_addr_len
));
216 ASSERT_EQ(0, listen(stream_server
, backlog
));
218 /* Signals to the parent that child is listening. */
219 ASSERT_EQ(1, write(pipe_child
[1], ".", 1));
221 /* Waits to connect. */
222 ASSERT_EQ(1, read(pipe_parent
[0], &buf
, 1));
223 EXPECT_EQ(0, close(stream_server
));
224 EXPECT_EQ(0, close(dgram_server
));
225 _exit(_metadata
->exit_code
);
228 EXPECT_EQ(0, close(pipe_child
[1]));
229 EXPECT_EQ(0, close(pipe_parent
[0]));
231 if (variant
->domain_parent
)
232 create_scoped_domain(_metadata
,
233 LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET
);
235 /* Signals that the parent is in a domain, if any. */
236 ASSERT_EQ(1, write(pipe_parent
[1], ".", 1));
238 stream_client
= socket(AF_UNIX
, SOCK_STREAM
, 0);
239 ASSERT_LE(0, stream_client
);
240 dgram_client
= socket(AF_UNIX
, SOCK_DGRAM
, 0);
241 ASSERT_LE(0, dgram_client
);
243 /* Waits for the child to listen */
244 ASSERT_EQ(1, read(pipe_child
[0], &buf
, 1));
245 err_stream
= connect(stream_client
, &self
->stream_address
.unix_addr
,
246 self
->stream_address
.unix_addr_len
);
247 errno_stream
= errno
;
248 err_dgram
= connect(dgram_client
, &self
->dgram_address
.unix_addr
,
249 self
->dgram_address
.unix_addr_len
);
251 if (can_connect_to_child
) {
252 EXPECT_EQ(0, err_stream
);
253 EXPECT_EQ(0, err_dgram
);
255 EXPECT_EQ(-1, err_stream
);
256 EXPECT_EQ(-1, err_dgram
);
257 EXPECT_EQ(EPERM
, errno_stream
);
258 EXPECT_EQ(EPERM
, errno_dgram
);
260 ASSERT_EQ(1, write(pipe_parent
[1], ".", 1));
261 EXPECT_EQ(0, close(stream_client
));
262 EXPECT_EQ(0, close(dgram_client
));
264 ASSERT_EQ(child
, waitpid(child
, &status
, 0));
265 if (WIFSIGNALED(status
) || !WIFEXITED(status
) ||
266 WEXITSTATUS(status
) != EXIT_SUCCESS
)
267 _metadata
->exit_code
= KSFT_FAIL
;
270 FIXTURE(scoped_vs_unscoped
)
272 struct service_fixture parent_stream_address
, parent_dgram_address
,
273 child_stream_address
, child_dgram_address
;
276 #include "scoped_multiple_domain_variants.h"
278 FIXTURE_SETUP(scoped_vs_unscoped
)
280 drop_caps(_metadata
);
282 memset(&self
->parent_stream_address
, 0,
283 sizeof(self
->parent_stream_address
));
284 set_unix_address(&self
->parent_stream_address
, 0);
285 memset(&self
->parent_dgram_address
, 0,
286 sizeof(self
->parent_dgram_address
));
287 set_unix_address(&self
->parent_dgram_address
, 1);
288 memset(&self
->child_stream_address
, 0,
289 sizeof(self
->child_stream_address
));
290 set_unix_address(&self
->child_stream_address
, 2);
291 memset(&self
->child_dgram_address
, 0,
292 sizeof(self
->child_dgram_address
));
293 set_unix_address(&self
->child_dgram_address
, 3);
296 FIXTURE_TEARDOWN(scoped_vs_unscoped
)
301 * Test unix_stream_connect and unix_may_send for parent, child and
302 * grand child processes when they can have scoped or non-scoped domains.
304 TEST_F(scoped_vs_unscoped
, unix_scoping
)
308 bool can_connect_to_parent
, can_connect_to_child
;
310 int stream_server_parent
, dgram_server_parent
;
312 can_connect_to_child
= (variant
->domain_grand_child
!= SCOPE_SANDBOX
);
313 can_connect_to_parent
= (can_connect_to_child
&&
314 (variant
->domain_children
!= SCOPE_SANDBOX
));
316 ASSERT_EQ(0, pipe2(pipe_parent
, O_CLOEXEC
));
318 if (variant
->domain_all
== OTHER_SANDBOX
)
319 create_fs_domain(_metadata
);
320 else if (variant
->domain_all
== SCOPE_SANDBOX
)
321 create_scoped_domain(_metadata
,
322 LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET
);
327 int stream_server_child
, dgram_server_child
;
331 ASSERT_EQ(0, pipe2(pipe_child
, O_CLOEXEC
));
333 if (variant
->domain_children
== OTHER_SANDBOX
)
334 create_fs_domain(_metadata
);
335 else if (variant
->domain_children
== SCOPE_SANDBOX
)
336 create_scoped_domain(
337 _metadata
, LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET
);
339 grand_child
= fork();
340 ASSERT_LE(0, grand_child
);
341 if (grand_child
== 0) {
343 int stream_err
, dgram_err
, stream_errno
, dgram_errno
;
344 int stream_client
, dgram_client
;
346 EXPECT_EQ(0, close(pipe_parent
[1]));
347 EXPECT_EQ(0, close(pipe_child
[1]));
349 if (variant
->domain_grand_child
== OTHER_SANDBOX
)
350 create_fs_domain(_metadata
);
351 else if (variant
->domain_grand_child
== SCOPE_SANDBOX
)
352 create_scoped_domain(
354 LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET
);
356 stream_client
= socket(AF_UNIX
, SOCK_STREAM
, 0);
357 ASSERT_LE(0, stream_client
);
358 dgram_client
= socket(AF_UNIX
, SOCK_DGRAM
, 0);
359 ASSERT_LE(0, dgram_client
);
361 ASSERT_EQ(1, read(pipe_child
[0], &buf
, 1));
362 stream_err
= connect(
364 &self
->child_stream_address
.unix_addr
,
365 self
->child_stream_address
.unix_addr_len
);
366 stream_errno
= errno
;
369 &self
->child_dgram_address
.unix_addr
,
370 self
->child_dgram_address
.unix_addr_len
);
372 if (can_connect_to_child
) {
373 EXPECT_EQ(0, stream_err
);
374 EXPECT_EQ(0, dgram_err
);
376 EXPECT_EQ(-1, stream_err
);
377 EXPECT_EQ(-1, dgram_err
);
378 EXPECT_EQ(EPERM
, stream_errno
);
379 EXPECT_EQ(EPERM
, dgram_errno
);
382 EXPECT_EQ(0, close(stream_client
));
383 stream_client
= socket(AF_UNIX
, SOCK_STREAM
, 0);
384 ASSERT_LE(0, stream_client
);
385 /* Datagram sockets can "reconnect". */
387 ASSERT_EQ(1, read(pipe_parent
[0], &buf
, 1));
388 stream_err
= connect(
390 &self
->parent_stream_address
.unix_addr
,
391 self
->parent_stream_address
.unix_addr_len
);
392 stream_errno
= errno
;
395 &self
->parent_dgram_address
.unix_addr
,
396 self
->parent_dgram_address
.unix_addr_len
);
398 if (can_connect_to_parent
) {
399 EXPECT_EQ(0, stream_err
);
400 EXPECT_EQ(0, dgram_err
);
402 EXPECT_EQ(-1, stream_err
);
403 EXPECT_EQ(-1, dgram_err
);
404 EXPECT_EQ(EPERM
, stream_errno
);
405 EXPECT_EQ(EPERM
, dgram_errno
);
407 EXPECT_EQ(0, close(stream_client
));
408 EXPECT_EQ(0, close(dgram_client
));
410 _exit(_metadata
->exit_code
);
413 EXPECT_EQ(0, close(pipe_child
[0]));
414 if (variant
->domain_child
== OTHER_SANDBOX
)
415 create_fs_domain(_metadata
);
416 else if (variant
->domain_child
== SCOPE_SANDBOX
)
417 create_scoped_domain(
418 _metadata
, LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET
);
420 stream_server_child
= socket(AF_UNIX
, SOCK_STREAM
, 0);
421 ASSERT_LE(0, stream_server_child
);
422 dgram_server_child
= socket(AF_UNIX
, SOCK_DGRAM
, 0);
423 ASSERT_LE(0, dgram_server_child
);
425 ASSERT_EQ(0, bind(stream_server_child
,
426 &self
->child_stream_address
.unix_addr
,
427 self
->child_stream_address
.unix_addr_len
));
428 ASSERT_EQ(0, bind(dgram_server_child
,
429 &self
->child_dgram_address
.unix_addr
,
430 self
->child_dgram_address
.unix_addr_len
));
431 ASSERT_EQ(0, listen(stream_server_child
, backlog
));
433 ASSERT_EQ(1, write(pipe_child
[1], ".", 1));
434 ASSERT_EQ(grand_child
, waitpid(grand_child
, &status
, 0));
435 EXPECT_EQ(0, close(stream_server_child
))
436 EXPECT_EQ(0, close(dgram_server_child
));
439 EXPECT_EQ(0, close(pipe_parent
[0]));
441 if (variant
->domain_parent
== OTHER_SANDBOX
)
442 create_fs_domain(_metadata
);
443 else if (variant
->domain_parent
== SCOPE_SANDBOX
)
444 create_scoped_domain(_metadata
,
445 LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET
);
447 stream_server_parent
= socket(AF_UNIX
, SOCK_STREAM
, 0);
448 ASSERT_LE(0, stream_server_parent
);
449 dgram_server_parent
= socket(AF_UNIX
, SOCK_DGRAM
, 0);
450 ASSERT_LE(0, dgram_server_parent
);
451 ASSERT_EQ(0, bind(stream_server_parent
,
452 &self
->parent_stream_address
.unix_addr
,
453 self
->parent_stream_address
.unix_addr_len
));
454 ASSERT_EQ(0, bind(dgram_server_parent
,
455 &self
->parent_dgram_address
.unix_addr
,
456 self
->parent_dgram_address
.unix_addr_len
));
458 ASSERT_EQ(0, listen(stream_server_parent
, backlog
));
460 ASSERT_EQ(1, write(pipe_parent
[1], ".", 1));
461 ASSERT_EQ(child
, waitpid(child
, &status
, 0));
462 EXPECT_EQ(0, close(stream_server_parent
));
463 EXPECT_EQ(0, close(dgram_server_parent
));
465 if (WIFSIGNALED(status
) || !WIFEXITED(status
) ||
466 WEXITSTATUS(status
) != EXIT_SUCCESS
)
467 _metadata
->exit_code
= KSFT_FAIL
;
470 FIXTURE(outside_socket
)
472 struct service_fixture address
, transit_address
;
475 FIXTURE_VARIANT(outside_socket
)
477 const bool child_socket
;
481 /* clang-format off */
482 FIXTURE_VARIANT_ADD(outside_socket
, allow_dgram_child
) {
483 /* clang-format on */
484 .child_socket
= true,
488 /* clang-format off */
489 FIXTURE_VARIANT_ADD(outside_socket
, deny_dgram_server
) {
490 /* clang-format on */
491 .child_socket
= false,
495 /* clang-format off */
496 FIXTURE_VARIANT_ADD(outside_socket
, allow_stream_child
) {
497 /* clang-format on */
498 .child_socket
= true,
502 /* clang-format off */
503 FIXTURE_VARIANT_ADD(outside_socket
, deny_stream_server
) {
504 /* clang-format on */
505 .child_socket
= false,
509 FIXTURE_SETUP(outside_socket
)
511 drop_caps(_metadata
);
513 memset(&self
->transit_address
, 0, sizeof(self
->transit_address
));
514 set_unix_address(&self
->transit_address
, 0);
515 memset(&self
->address
, 0, sizeof(self
->address
));
516 set_unix_address(&self
->address
, 1);
519 FIXTURE_TEARDOWN(outside_socket
)
524 * Test unix_stream_connect and unix_may_send for parent and child processes
525 * when connecting socket has different domain than the process using it.
527 TEST_F(outside_socket
, socket_with_different_domain
)
531 int pipe_child
[2], pipe_parent
[2];
535 ASSERT_EQ(0, pipe2(pipe_child
, O_CLOEXEC
));
536 ASSERT_EQ(0, pipe2(pipe_parent
, O_CLOEXEC
));
544 EXPECT_EQ(0, close(pipe_parent
[1]));
545 EXPECT_EQ(0, close(pipe_child
[0]));
547 /* Client always has a domain. */
548 create_scoped_domain(_metadata
,
549 LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET
);
551 if (variant
->child_socket
) {
552 int data_socket
, passed_socket
, stream_server
;
554 passed_socket
= socket(AF_UNIX
, variant
->type
, 0);
555 ASSERT_LE(0, passed_socket
);
556 stream_server
= socket(AF_UNIX
, SOCK_STREAM
, 0);
557 ASSERT_LE(0, stream_server
);
558 ASSERT_EQ(0, bind(stream_server
,
559 &self
->transit_address
.unix_addr
,
560 self
->transit_address
.unix_addr_len
));
561 ASSERT_EQ(0, listen(stream_server
, backlog
));
562 ASSERT_EQ(1, write(pipe_child
[1], ".", 1));
563 data_socket
= accept(stream_server
, NULL
, NULL
);
564 ASSERT_LE(0, data_socket
);
565 ASSERT_EQ(0, send_fd(data_socket
, passed_socket
));
566 EXPECT_EQ(0, close(passed_socket
));
567 EXPECT_EQ(0, close(stream_server
));
570 client_socket
= socket(AF_UNIX
, variant
->type
, 0);
571 ASSERT_LE(0, client_socket
);
573 /* Waits for parent signal for connection. */
574 ASSERT_EQ(1, read(pipe_parent
[0], &buf_child
, 1));
575 err
= connect(client_socket
, &self
->address
.unix_addr
,
576 self
->address
.unix_addr_len
);
577 if (variant
->child_socket
) {
581 EXPECT_EQ(EPERM
, errno
);
583 EXPECT_EQ(0, close(client_socket
));
584 _exit(_metadata
->exit_code
);
587 EXPECT_EQ(0, close(pipe_child
[1]));
588 EXPECT_EQ(0, close(pipe_parent
[0]));
590 if (variant
->child_socket
) {
591 int client_child
= socket(AF_UNIX
, SOCK_STREAM
, 0);
593 ASSERT_LE(0, client_child
);
594 ASSERT_EQ(1, read(pipe_child
[0], &buf_parent
, 1));
595 ASSERT_EQ(0, connect(client_child
,
596 &self
->transit_address
.unix_addr
,
597 self
->transit_address
.unix_addr_len
));
598 server_socket
= recv_fd(client_child
);
599 EXPECT_EQ(0, close(client_child
));
601 server_socket
= socket(AF_UNIX
, variant
->type
, 0);
603 ASSERT_LE(0, server_socket
);
605 /* Server always has a domain. */
606 create_scoped_domain(_metadata
, LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET
);
608 ASSERT_EQ(0, bind(server_socket
, &self
->address
.unix_addr
,
609 self
->address
.unix_addr_len
));
610 if (variant
->type
== SOCK_STREAM
)
611 ASSERT_EQ(0, listen(server_socket
, backlog
));
613 /* Signals to child that the parent is listening. */
614 ASSERT_EQ(1, write(pipe_parent
[1], ".", 1));
616 ASSERT_EQ(child
, waitpid(child
, &status
, 0));
617 EXPECT_EQ(0, close(server_socket
));
619 if (WIFSIGNALED(status
) || !WIFEXITED(status
) ||
620 WEXITSTATUS(status
) != EXIT_SUCCESS
)
621 _metadata
->exit_code
= KSFT_FAIL
;
624 static const char stream_path
[] = TMP_DIR
"/stream.sock";
625 static const char dgram_path
[] = TMP_DIR
"/dgram.sock";
627 /* clang-format off */
628 FIXTURE(various_address_sockets
) {};
629 /* clang-format on */
631 FIXTURE_VARIANT(various_address_sockets
)
636 /* clang-format off */
637 FIXTURE_VARIANT_ADD(various_address_sockets
, pathname_socket_scoped_domain
) {
638 /* clang-format on */
639 .domain
= SCOPE_SANDBOX
,
642 /* clang-format off */
643 FIXTURE_VARIANT_ADD(various_address_sockets
, pathname_socket_other_domain
) {
644 /* clang-format on */
645 .domain
= OTHER_SANDBOX
,
648 /* clang-format off */
649 FIXTURE_VARIANT_ADD(various_address_sockets
, pathname_socket_no_domain
) {
650 /* clang-format on */
651 .domain
= NO_SANDBOX
,
654 FIXTURE_SETUP(various_address_sockets
)
656 drop_caps(_metadata
);
659 ASSERT_EQ(0, mkdir(TMP_DIR
, 0700));
662 FIXTURE_TEARDOWN(various_address_sockets
)
664 EXPECT_EQ(0, unlink(stream_path
));
665 EXPECT_EQ(0, unlink(dgram_path
));
666 EXPECT_EQ(0, rmdir(TMP_DIR
));
669 TEST_F(various_address_sockets
, scoped_pathname_sockets
)
671 socklen_t size_stream
, size_dgram
;
674 char buf_child
, buf_parent
;
676 int unnamed_sockets
[2];
677 int stream_pathname_socket
, dgram_pathname_socket
,
678 stream_abstract_socket
, dgram_abstract_socket
, data_socket
;
679 struct service_fixture stream_abstract_addr
, dgram_abstract_addr
;
680 struct sockaddr_un stream_pathname_addr
= {
681 .sun_family
= AF_UNIX
,
683 struct sockaddr_un dgram_pathname_addr
= {
684 .sun_family
= AF_UNIX
,
687 /* Pathname address. */
688 snprintf(stream_pathname_addr
.sun_path
,
689 sizeof(stream_pathname_addr
.sun_path
), "%s", stream_path
);
690 size_stream
= offsetof(struct sockaddr_un
, sun_path
) +
691 strlen(stream_pathname_addr
.sun_path
);
692 snprintf(dgram_pathname_addr
.sun_path
,
693 sizeof(dgram_pathname_addr
.sun_path
), "%s", dgram_path
);
694 size_dgram
= offsetof(struct sockaddr_un
, sun_path
) +
695 strlen(dgram_pathname_addr
.sun_path
);
697 /* Abstract address. */
698 memset(&stream_abstract_addr
, 0, sizeof(stream_abstract_addr
));
699 set_unix_address(&stream_abstract_addr
, 0);
700 memset(&dgram_abstract_addr
, 0, sizeof(dgram_abstract_addr
));
701 set_unix_address(&dgram_abstract_addr
, 1);
703 /* Unnamed address for datagram socket. */
704 ASSERT_EQ(0, socketpair(AF_UNIX
, SOCK_DGRAM
, 0, unnamed_sockets
));
706 ASSERT_EQ(0, pipe2(pipe_parent
, O_CLOEXEC
));
713 EXPECT_EQ(0, close(pipe_parent
[1]));
714 EXPECT_EQ(0, close(unnamed_sockets
[1]));
716 if (variant
->domain
== SCOPE_SANDBOX
)
717 create_scoped_domain(
718 _metadata
, LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET
);
719 else if (variant
->domain
== OTHER_SANDBOX
)
720 create_fs_domain(_metadata
);
722 /* Waits for parent to listen. */
723 ASSERT_EQ(1, read(pipe_parent
[0], &buf_child
, 1));
724 EXPECT_EQ(0, close(pipe_parent
[0]));
726 /* Checks that we can send data through a datagram socket. */
727 ASSERT_EQ(1, write(unnamed_sockets
[0], "a", 1));
728 EXPECT_EQ(0, close(unnamed_sockets
[0]));
730 /* Connects with pathname sockets. */
731 stream_pathname_socket
= socket(AF_UNIX
, SOCK_STREAM
, 0);
732 ASSERT_LE(0, stream_pathname_socket
);
733 ASSERT_EQ(0, connect(stream_pathname_socket
,
734 &stream_pathname_addr
, size_stream
));
735 ASSERT_EQ(1, write(stream_pathname_socket
, "b", 1));
736 EXPECT_EQ(0, close(stream_pathname_socket
));
738 /* Sends without connection. */
739 dgram_pathname_socket
= socket(AF_UNIX
, SOCK_DGRAM
, 0);
740 ASSERT_LE(0, dgram_pathname_socket
);
741 err
= sendto(dgram_pathname_socket
, "c", 1, 0,
742 &dgram_pathname_addr
, size_dgram
);
745 /* Sends with connection. */
746 ASSERT_EQ(0, connect(dgram_pathname_socket
,
747 &dgram_pathname_addr
, size_dgram
));
748 ASSERT_EQ(1, write(dgram_pathname_socket
, "d", 1));
749 EXPECT_EQ(0, close(dgram_pathname_socket
));
751 /* Connects with abstract sockets. */
752 stream_abstract_socket
= socket(AF_UNIX
, SOCK_STREAM
, 0);
753 ASSERT_LE(0, stream_abstract_socket
);
754 err
= connect(stream_abstract_socket
,
755 &stream_abstract_addr
.unix_addr
,
756 stream_abstract_addr
.unix_addr_len
);
757 if (variant
->domain
== SCOPE_SANDBOX
) {
759 EXPECT_EQ(EPERM
, errno
);
762 ASSERT_EQ(1, write(stream_abstract_socket
, "e", 1));
764 EXPECT_EQ(0, close(stream_abstract_socket
));
766 /* Sends without connection. */
767 dgram_abstract_socket
= socket(AF_UNIX
, SOCK_DGRAM
, 0);
768 ASSERT_LE(0, dgram_abstract_socket
);
769 err
= sendto(dgram_abstract_socket
, "f", 1, 0,
770 &dgram_abstract_addr
.unix_addr
,
771 dgram_abstract_addr
.unix_addr_len
);
772 if (variant
->domain
== SCOPE_SANDBOX
) {
774 EXPECT_EQ(EPERM
, errno
);
779 /* Sends with connection. */
780 err
= connect(dgram_abstract_socket
,
781 &dgram_abstract_addr
.unix_addr
,
782 dgram_abstract_addr
.unix_addr_len
);
783 if (variant
->domain
== SCOPE_SANDBOX
) {
785 EXPECT_EQ(EPERM
, errno
);
788 ASSERT_EQ(1, write(dgram_abstract_socket
, "g", 1));
790 EXPECT_EQ(0, close(dgram_abstract_socket
));
792 _exit(_metadata
->exit_code
);
795 EXPECT_EQ(0, close(pipe_parent
[0]));
796 EXPECT_EQ(0, close(unnamed_sockets
[0]));
798 /* Sets up pathname servers. */
799 stream_pathname_socket
= socket(AF_UNIX
, SOCK_STREAM
, 0);
800 ASSERT_LE(0, stream_pathname_socket
);
801 ASSERT_EQ(0, bind(stream_pathname_socket
, &stream_pathname_addr
,
803 ASSERT_EQ(0, listen(stream_pathname_socket
, backlog
));
805 dgram_pathname_socket
= socket(AF_UNIX
, SOCK_DGRAM
, 0);
806 ASSERT_LE(0, dgram_pathname_socket
);
807 ASSERT_EQ(0, bind(dgram_pathname_socket
, &dgram_pathname_addr
,
810 /* Sets up abstract servers. */
811 stream_abstract_socket
= socket(AF_UNIX
, SOCK_STREAM
, 0);
812 ASSERT_LE(0, stream_abstract_socket
);
814 bind(stream_abstract_socket
, &stream_abstract_addr
.unix_addr
,
815 stream_abstract_addr
.unix_addr_len
));
817 dgram_abstract_socket
= socket(AF_UNIX
, SOCK_DGRAM
, 0);
818 ASSERT_LE(0, dgram_abstract_socket
);
819 ASSERT_EQ(0, bind(dgram_abstract_socket
, &dgram_abstract_addr
.unix_addr
,
820 dgram_abstract_addr
.unix_addr_len
));
821 ASSERT_EQ(0, listen(stream_abstract_socket
, backlog
));
823 ASSERT_EQ(1, write(pipe_parent
[1], ".", 1));
824 EXPECT_EQ(0, close(pipe_parent
[1]));
826 /* Reads from unnamed socket. */
827 ASSERT_EQ(1, read(unnamed_sockets
[1], &buf_parent
, sizeof(buf_parent
)));
828 ASSERT_EQ('a', buf_parent
);
829 EXPECT_LE(0, close(unnamed_sockets
[1]));
831 /* Reads from pathname sockets. */
832 data_socket
= accept(stream_pathname_socket
, NULL
, NULL
);
833 ASSERT_LE(0, data_socket
);
834 ASSERT_EQ(1, read(data_socket
, &buf_parent
, sizeof(buf_parent
)));
835 ASSERT_EQ('b', buf_parent
);
836 EXPECT_EQ(0, close(data_socket
));
837 EXPECT_EQ(0, close(stream_pathname_socket
));
840 read(dgram_pathname_socket
, &buf_parent
, sizeof(buf_parent
)));
841 ASSERT_EQ('c', buf_parent
);
843 read(dgram_pathname_socket
, &buf_parent
, sizeof(buf_parent
)));
844 ASSERT_EQ('d', buf_parent
);
845 EXPECT_EQ(0, close(dgram_pathname_socket
));
847 if (variant
->domain
!= SCOPE_SANDBOX
) {
848 /* Reads from abstract sockets if allowed to send. */
849 data_socket
= accept(stream_abstract_socket
, NULL
, NULL
);
850 ASSERT_LE(0, data_socket
);
852 read(data_socket
, &buf_parent
, sizeof(buf_parent
)));
853 ASSERT_EQ('e', buf_parent
);
854 EXPECT_EQ(0, close(data_socket
));
856 ASSERT_EQ(1, read(dgram_abstract_socket
, &buf_parent
,
857 sizeof(buf_parent
)));
858 ASSERT_EQ('f', buf_parent
);
859 ASSERT_EQ(1, read(dgram_abstract_socket
, &buf_parent
,
860 sizeof(buf_parent
)));
861 ASSERT_EQ('g', buf_parent
);
864 /* Waits for all abstract socket tests. */
865 ASSERT_EQ(child
, waitpid(child
, &status
, 0));
866 EXPECT_EQ(0, close(stream_abstract_socket
));
867 EXPECT_EQ(0, close(dgram_abstract_socket
));
869 if (WIFSIGNALED(status
) || !WIFEXITED(status
) ||
870 WEXITSTATUS(status
) != EXIT_SUCCESS
)
871 _metadata
->exit_code
= KSFT_FAIL
;
874 TEST(datagram_sockets
)
876 struct service_fixture connected_addr
, non_connected_addr
;
877 int server_conn_socket
, server_unconn_socket
;
878 int pipe_parent
[2], pipe_child
[2];
883 drop_caps(_metadata
);
884 memset(&connected_addr
, 0, sizeof(connected_addr
));
885 set_unix_address(&connected_addr
, 0);
886 memset(&non_connected_addr
, 0, sizeof(non_connected_addr
));
887 set_unix_address(&non_connected_addr
, 1);
889 ASSERT_EQ(0, pipe2(pipe_parent
, O_CLOEXEC
));
890 ASSERT_EQ(0, pipe2(pipe_child
, O_CLOEXEC
));
895 int client_conn_socket
, client_unconn_socket
;
897 EXPECT_EQ(0, close(pipe_parent
[1]));
898 EXPECT_EQ(0, close(pipe_child
[0]));
900 client_conn_socket
= socket(AF_UNIX
, SOCK_DGRAM
, 0);
901 client_unconn_socket
= socket(AF_UNIX
, SOCK_DGRAM
, 0);
902 ASSERT_LE(0, client_conn_socket
);
903 ASSERT_LE(0, client_unconn_socket
);
905 /* Waits for parent to listen. */
906 ASSERT_EQ(1, read(pipe_parent
[0], &buf
, 1));
908 connect(client_conn_socket
, &connected_addr
.unix_addr
,
909 connected_addr
.unix_addr_len
));
912 * Both connected and non-connected sockets can send data when
913 * the domain is not scoped.
915 ASSERT_EQ(1, send(client_conn_socket
, ".", 1, 0));
916 ASSERT_EQ(1, sendto(client_unconn_socket
, ".", 1, 0,
917 &non_connected_addr
.unix_addr
,
918 non_connected_addr
.unix_addr_len
));
919 ASSERT_EQ(1, write(pipe_child
[1], ".", 1));
921 /* Scopes the domain. */
922 create_scoped_domain(_metadata
,
923 LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET
);
926 * Connected socket sends data to the receiver, but the
927 * non-connected socket must fail to send data.
929 ASSERT_EQ(1, send(client_conn_socket
, ".", 1, 0));
930 ASSERT_EQ(-1, sendto(client_unconn_socket
, ".", 1, 0,
931 &non_connected_addr
.unix_addr
,
932 non_connected_addr
.unix_addr_len
));
933 ASSERT_EQ(EPERM
, errno
);
934 ASSERT_EQ(1, write(pipe_child
[1], ".", 1));
936 EXPECT_EQ(0, close(client_conn_socket
));
937 EXPECT_EQ(0, close(client_unconn_socket
));
938 _exit(_metadata
->exit_code
);
941 EXPECT_EQ(0, close(pipe_parent
[0]));
942 EXPECT_EQ(0, close(pipe_child
[1]));
944 server_conn_socket
= socket(AF_UNIX
, SOCK_DGRAM
, 0);
945 server_unconn_socket
= socket(AF_UNIX
, SOCK_DGRAM
, 0);
946 ASSERT_LE(0, server_conn_socket
);
947 ASSERT_LE(0, server_unconn_socket
);
949 ASSERT_EQ(0, bind(server_conn_socket
, &connected_addr
.unix_addr
,
950 connected_addr
.unix_addr_len
));
951 ASSERT_EQ(0, bind(server_unconn_socket
, &non_connected_addr
.unix_addr
,
952 non_connected_addr
.unix_addr_len
));
953 ASSERT_EQ(1, write(pipe_parent
[1], ".", 1));
955 /* Waits for child to test. */
956 ASSERT_EQ(1, read(pipe_child
[0], &buf
, 1));
957 ASSERT_EQ(1, recv(server_conn_socket
, &buf
, 1, 0));
958 ASSERT_EQ(1, recv(server_unconn_socket
, &buf
, 1, 0));
961 * Connected datagram socket will receive data, but
962 * non-connected datagram socket does not receive data.
964 ASSERT_EQ(1, read(pipe_child
[0], &buf
, 1));
965 ASSERT_EQ(1, recv(server_conn_socket
, &buf
, 1, 0));
967 /* Waits for all tests to finish. */
968 ASSERT_EQ(child
, waitpid(child
, &status
, 0));
969 EXPECT_EQ(0, close(server_conn_socket
));
970 EXPECT_EQ(0, close(server_unconn_socket
));
972 if (WIFSIGNALED(status
) || !WIFEXITED(status
) ||
973 WEXITSTATUS(status
) != EXIT_SUCCESS
)
974 _metadata
->exit_code
= KSFT_FAIL
;
979 struct service_fixture connected_addr
, non_connected_addr
;
980 int connected_socket
, non_connected_socket
, status
;
983 drop_caps(_metadata
);
984 memset(&connected_addr
, 0, sizeof(connected_addr
));
985 set_unix_address(&connected_addr
, 0);
986 memset(&non_connected_addr
, 0, sizeof(non_connected_addr
));
987 set_unix_address(&non_connected_addr
, 1);
989 connected_socket
= socket(AF_UNIX
, SOCK_DGRAM
, 0);
990 non_connected_socket
= socket(AF_UNIX
, SOCK_DGRAM
, 0);
991 ASSERT_LE(0, connected_socket
);
992 ASSERT_LE(0, non_connected_socket
);
994 ASSERT_EQ(0, bind(connected_socket
, &connected_addr
.unix_addr
,
995 connected_addr
.unix_addr_len
));
996 ASSERT_EQ(0, bind(non_connected_socket
, &non_connected_addr
.unix_addr
,
997 non_connected_addr
.unix_addr_len
));
1000 ASSERT_LE(0, child
);
1002 /* Child's domain is scoped. */
1003 create_scoped_domain(_metadata
,
1004 LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET
);
1007 * The child inherits the sockets, and cannot connect or
1008 * send data to them.
1011 connect(connected_socket
, &connected_addr
.unix_addr
,
1012 connected_addr
.unix_addr_len
));
1013 ASSERT_EQ(EPERM
, errno
);
1015 ASSERT_EQ(-1, sendto(connected_socket
, ".", 1, 0,
1016 &connected_addr
.unix_addr
,
1017 connected_addr
.unix_addr_len
));
1018 ASSERT_EQ(EPERM
, errno
);
1020 ASSERT_EQ(-1, sendto(non_connected_socket
, ".", 1, 0,
1021 &non_connected_addr
.unix_addr
,
1022 non_connected_addr
.unix_addr_len
));
1023 ASSERT_EQ(EPERM
, errno
);
1025 EXPECT_EQ(0, close(connected_socket
));
1026 EXPECT_EQ(0, close(non_connected_socket
));
1027 _exit(_metadata
->exit_code
);
1031 /* Waits for all tests to finish. */
1032 ASSERT_EQ(child
, waitpid(child
, &status
, 0));
1033 EXPECT_EQ(0, close(connected_socket
));
1034 EXPECT_EQ(0, close(non_connected_socket
));
1036 if (WIFSIGNALED(status
) || !WIFEXITED(status
) ||
1037 WEXITSTATUS(status
) != EXIT_SUCCESS
)
1038 _metadata
->exit_code
= KSFT_FAIL
;