~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/landlock/scoped_abstract_unix_test.c

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 "common.h"
 24 #include "scoped_common.h"
 25 
 26 /* Number of pending connections queue to be hold. */
 27 const short backlog = 10;
 28 
 29 static void create_fs_domain(struct __test_metadata *const _metadata)
 30 {
 31         int ruleset_fd;
 32         struct landlock_ruleset_attr ruleset_attr = {
 33                 .handled_access_fs = LANDLOCK_ACCESS_FS_READ_DIR,
 34         };
 35 
 36         ruleset_fd =
 37                 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
 38         EXPECT_LE(0, ruleset_fd)
 39         {
 40                 TH_LOG("Failed to create a ruleset: %s", strerror(errno));
 41         }
 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));
 45 }
 46 
 47 FIXTURE(scoped_domains)
 48 {
 49         struct service_fixture stream_address, dgram_address;
 50 };
 51 
 52 #include "scoped_base_variants.h"
 53 
 54 FIXTURE_SETUP(scoped_domains)
 55 {
 56         drop_caps(_metadata);
 57 
 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);
 62 }
 63 
 64 FIXTURE_TEARDOWN(scoped_domains)
 65 {
 66 }
 67 
 68 /*
 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.
 71  */
 72 TEST_F(scoped_domains, connect_to_parent)
 73 {
 74         pid_t child;
 75         bool can_connect_to_parent;
 76         int status;
 77         int pipe_parent[2];
 78         int stream_server, dgram_server;
 79 
 80         /*
 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.
 84          */
 85         can_connect_to_parent = !variant->domain_child;
 86 
 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))
 92                         return;
 93         }
 94 
 95         child = fork();
 96         ASSERT_LE(0, child);
 97         if (child == 0) {
 98                 int err;
 99                 int stream_client, dgram_client;
100                 char buf_child;
101 
102                 EXPECT_EQ(0, close(pipe_parent[1]));
103                 if (variant->domain_child)
104                         create_scoped_domain(
105                                 _metadata, LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET);
106 
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);
111 
112                 /* Waits for the server. */
113                 ASSERT_EQ(1, read(pipe_parent[0], &buf_child, 1));
114 
115                 err = connect(stream_client, &self->stream_address.unix_addr,
116                               self->stream_address.unix_addr_len);
117                 if (can_connect_to_parent) {
118                         EXPECT_EQ(0, err);
119                 } else {
120                         EXPECT_EQ(-1, err);
121                         EXPECT_EQ(EPERM, errno);
122                 }
123                 EXPECT_EQ(0, close(stream_client));
124 
125                 err = connect(dgram_client, &self->dgram_address.unix_addr,
126                               self->dgram_address.unix_addr_len);
127                 if (can_connect_to_parent) {
128                         EXPECT_EQ(0, err);
129                 } else {
130                         EXPECT_EQ(-1, err);
131                         EXPECT_EQ(EPERM, errno);
132                 }
133                 EXPECT_EQ(0, close(dgram_client));
134                 _exit(_metadata->exit_code);
135                 return;
136         }
137         EXPECT_EQ(0, close(pipe_parent[0]));
138         if (variant->domain_parent)
139                 create_scoped_domain(_metadata,
140                                      LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET);
141 
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));
151 
152         /* Signals to child that the parent is listening. */
153         ASSERT_EQ(1, write(pipe_parent[1], ".", 1));
154 
155         ASSERT_EQ(child, waitpid(child, &status, 0));
156         EXPECT_EQ(0, close(stream_server));
157         EXPECT_EQ(0, close(dgram_server));
158 
159         if (WIFSIGNALED(status) || !WIFEXITED(status) ||
160             WEXITSTATUS(status) != EXIT_SUCCESS)
161                 _metadata->exit_code = KSFT_FAIL;
162 }
163 
164 /*
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.
167  */
168 TEST_F(scoped_domains, connect_to_child)
169 {
170         pid_t 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];
174         char buf;
175         int stream_client, dgram_client;
176 
177         /*
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.
181          */
182         can_connect_to_child = !variant->domain_parent;
183 
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))
190                         return;
191         }
192 
193         child = fork();
194         ASSERT_LE(0, child);
195         if (child == 0) {
196                 int stream_server, dgram_server;
197 
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);
203 
204                 /* Waits for the parent to be in a domain, if any. */
205                 ASSERT_EQ(1, read(pipe_parent[0], &buf, 1));
206 
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);
211                 ASSERT_EQ(0,
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));
217 
218                 /* Signals to the parent that child is listening. */
219                 ASSERT_EQ(1, write(pipe_child[1], ".", 1));
220 
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);
226                 return;
227         }
228         EXPECT_EQ(0, close(pipe_child[1]));
229         EXPECT_EQ(0, close(pipe_parent[0]));
230 
231         if (variant->domain_parent)
232                 create_scoped_domain(_metadata,
233                                      LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET);
234 
235         /* Signals that the parent is in a domain, if any. */
236         ASSERT_EQ(1, write(pipe_parent[1], ".", 1));
237 
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);
242 
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);
250         errno_dgram = errno;
251         if (can_connect_to_child) {
252                 EXPECT_EQ(0, err_stream);
253                 EXPECT_EQ(0, err_dgram);
254         } else {
255                 EXPECT_EQ(-1, err_stream);
256                 EXPECT_EQ(-1, err_dgram);
257                 EXPECT_EQ(EPERM, errno_stream);
258                 EXPECT_EQ(EPERM, errno_dgram);
259         }
260         ASSERT_EQ(1, write(pipe_parent[1], ".", 1));
261         EXPECT_EQ(0, close(stream_client));
262         EXPECT_EQ(0, close(dgram_client));
263 
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;
268 }
269 
270 FIXTURE(scoped_vs_unscoped)
271 {
272         struct service_fixture parent_stream_address, parent_dgram_address,
273                 child_stream_address, child_dgram_address;
274 };
275 
276 #include "scoped_multiple_domain_variants.h"
277 
278 FIXTURE_SETUP(scoped_vs_unscoped)
279 {
280         drop_caps(_metadata);
281 
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);
294 }
295 
296 FIXTURE_TEARDOWN(scoped_vs_unscoped)
297 {
298 }
299 
300 /*
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.
303  */
304 TEST_F(scoped_vs_unscoped, unix_scoping)
305 {
306         pid_t child;
307         int status;
308         bool can_connect_to_parent, can_connect_to_child;
309         int pipe_parent[2];
310         int stream_server_parent, dgram_server_parent;
311 
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));
315 
316         ASSERT_EQ(0, pipe2(pipe_parent, O_CLOEXEC));
317 
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);
323 
324         child = fork();
325         ASSERT_LE(0, child);
326         if (child == 0) {
327                 int stream_server_child, dgram_server_child;
328                 int pipe_child[2];
329                 pid_t grand_child;
330 
331                 ASSERT_EQ(0, pipe2(pipe_child, O_CLOEXEC));
332 
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);
338 
339                 grand_child = fork();
340                 ASSERT_LE(0, grand_child);
341                 if (grand_child == 0) {
342                         char buf;
343                         int stream_err, dgram_err, stream_errno, dgram_errno;
344                         int stream_client, dgram_client;
345 
346                         EXPECT_EQ(0, close(pipe_parent[1]));
347                         EXPECT_EQ(0, close(pipe_child[1]));
348 
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(
353                                         _metadata,
354                                         LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET);
355 
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);
360 
361                         ASSERT_EQ(1, read(pipe_child[0], &buf, 1));
362                         stream_err = connect(
363                                 stream_client,
364                                 &self->child_stream_address.unix_addr,
365                                 self->child_stream_address.unix_addr_len);
366                         stream_errno = errno;
367                         dgram_err = connect(
368                                 dgram_client,
369                                 &self->child_dgram_address.unix_addr,
370                                 self->child_dgram_address.unix_addr_len);
371                         dgram_errno = errno;
372                         if (can_connect_to_child) {
373                                 EXPECT_EQ(0, stream_err);
374                                 EXPECT_EQ(0, dgram_err);
375                         } else {
376                                 EXPECT_EQ(-1, stream_err);
377                                 EXPECT_EQ(-1, dgram_err);
378                                 EXPECT_EQ(EPERM, stream_errno);
379                                 EXPECT_EQ(EPERM, dgram_errno);
380                         }
381 
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". */
386 
387                         ASSERT_EQ(1, read(pipe_parent[0], &buf, 1));
388                         stream_err = connect(
389                                 stream_client,
390                                 &self->parent_stream_address.unix_addr,
391                                 self->parent_stream_address.unix_addr_len);
392                         stream_errno = errno;
393                         dgram_err = connect(
394                                 dgram_client,
395                                 &self->parent_dgram_address.unix_addr,
396                                 self->parent_dgram_address.unix_addr_len);
397                         dgram_errno = errno;
398                         if (can_connect_to_parent) {
399                                 EXPECT_EQ(0, stream_err);
400                                 EXPECT_EQ(0, dgram_err);
401                         } else {
402                                 EXPECT_EQ(-1, stream_err);
403                                 EXPECT_EQ(-1, dgram_err);
404                                 EXPECT_EQ(EPERM, stream_errno);
405                                 EXPECT_EQ(EPERM, dgram_errno);
406                         }
407                         EXPECT_EQ(0, close(stream_client));
408                         EXPECT_EQ(0, close(dgram_client));
409 
410                         _exit(_metadata->exit_code);
411                         return;
412                 }
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);
419 
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);
424 
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));
432 
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));
437                 return;
438         }
439         EXPECT_EQ(0, close(pipe_parent[0]));
440 
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);
446 
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));
457 
458         ASSERT_EQ(0, listen(stream_server_parent, backlog));
459 
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));
464 
465         if (WIFSIGNALED(status) || !WIFEXITED(status) ||
466             WEXITSTATUS(status) != EXIT_SUCCESS)
467                 _metadata->exit_code = KSFT_FAIL;
468 }
469 
470 FIXTURE(outside_socket)
471 {
472         struct service_fixture address, transit_address;
473 };
474 
475 FIXTURE_VARIANT(outside_socket)
476 {
477         const bool child_socket;
478         const int type;
479 };
480 
481 /* clang-format off */
482 FIXTURE_VARIANT_ADD(outside_socket, allow_dgram_child) {
483         /* clang-format on */
484         .child_socket = true,
485         .type = SOCK_DGRAM,
486 };
487 
488 /* clang-format off */
489 FIXTURE_VARIANT_ADD(outside_socket, deny_dgram_server) {
490         /* clang-format on */
491         .child_socket = false,
492         .type = SOCK_DGRAM,
493 };
494 
495 /* clang-format off */
496 FIXTURE_VARIANT_ADD(outside_socket, allow_stream_child) {
497         /* clang-format on */
498         .child_socket = true,
499         .type = SOCK_STREAM,
500 };
501 
502 /* clang-format off */
503 FIXTURE_VARIANT_ADD(outside_socket, deny_stream_server) {
504         /* clang-format on */
505         .child_socket = false,
506         .type = SOCK_STREAM,
507 };
508 
509 FIXTURE_SETUP(outside_socket)
510 {
511         drop_caps(_metadata);
512 
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);
517 }
518 
519 FIXTURE_TEARDOWN(outside_socket)
520 {
521 }
522 
523 /*
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.
526  */
527 TEST_F(outside_socket, socket_with_different_domain)
528 {
529         pid_t child;
530         int err, status;
531         int pipe_child[2], pipe_parent[2];
532         char buf_parent;
533         int server_socket;
534 
535         ASSERT_EQ(0, pipe2(pipe_child, O_CLOEXEC));
536         ASSERT_EQ(0, pipe2(pipe_parent, O_CLOEXEC));
537 
538         child = fork();
539         ASSERT_LE(0, child);
540         if (child == 0) {
541                 int client_socket;
542                 char buf_child;
543 
544                 EXPECT_EQ(0, close(pipe_parent[1]));
545                 EXPECT_EQ(0, close(pipe_child[0]));
546 
547                 /* Client always has a domain. */
548                 create_scoped_domain(_metadata,
549                                      LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET);
550 
551                 if (variant->child_socket) {
552                         int data_socket, passed_socket, stream_server;
553 
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));
568                 }
569 
570                 client_socket = socket(AF_UNIX, variant->type, 0);
571                 ASSERT_LE(0, client_socket);
572 
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) {
578                         EXPECT_EQ(0, err);
579                 } else {
580                         EXPECT_EQ(-1, err);
581                         EXPECT_EQ(EPERM, errno);
582                 }
583                 EXPECT_EQ(0, close(client_socket));
584                 _exit(_metadata->exit_code);
585                 return;
586         }
587         EXPECT_EQ(0, close(pipe_child[1]));
588         EXPECT_EQ(0, close(pipe_parent[0]));
589 
590         if (variant->child_socket) {
591                 int client_child = socket(AF_UNIX, SOCK_STREAM, 0);
592 
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));
600         } else {
601                 server_socket = socket(AF_UNIX, variant->type, 0);
602         }
603         ASSERT_LE(0, server_socket);
604 
605         /* Server always has a domain. */
606         create_scoped_domain(_metadata, LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET);
607 
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));
612 
613         /* Signals to child that the parent is listening. */
614         ASSERT_EQ(1, write(pipe_parent[1], ".", 1));
615 
616         ASSERT_EQ(child, waitpid(child, &status, 0));
617         EXPECT_EQ(0, close(server_socket));
618 
619         if (WIFSIGNALED(status) || !WIFEXITED(status) ||
620             WEXITSTATUS(status) != EXIT_SUCCESS)
621                 _metadata->exit_code = KSFT_FAIL;
622 }
623 
624 static const char stream_path[] = TMP_DIR "/stream.sock";
625 static const char dgram_path[] = TMP_DIR "/dgram.sock";
626 
627 /* clang-format off */
628 FIXTURE(various_address_sockets) {};
629 /* clang-format on */
630 
631 FIXTURE_VARIANT(various_address_sockets)
632 {
633         const int domain;
634 };
635 
636 /* clang-format off */
637 FIXTURE_VARIANT_ADD(various_address_sockets, pathname_socket_scoped_domain) {
638         /* clang-format on */
639         .domain = SCOPE_SANDBOX,
640 };
641 
642 /* clang-format off */
643 FIXTURE_VARIANT_ADD(various_address_sockets, pathname_socket_other_domain) {
644         /* clang-format on */
645         .domain = OTHER_SANDBOX,
646 };
647 
648 /* clang-format off */
649 FIXTURE_VARIANT_ADD(various_address_sockets, pathname_socket_no_domain) {
650         /* clang-format on */
651         .domain = NO_SANDBOX,
652 };
653 
654 FIXTURE_SETUP(various_address_sockets)
655 {
656         drop_caps(_metadata);
657 
658         umask(0077);
659         ASSERT_EQ(0, mkdir(TMP_DIR, 0700));
660 }
661 
662 FIXTURE_TEARDOWN(various_address_sockets)
663 {
664         EXPECT_EQ(0, unlink(stream_path));
665         EXPECT_EQ(0, unlink(dgram_path));
666         EXPECT_EQ(0, rmdir(TMP_DIR));
667 }
668 
669 TEST_F(various_address_sockets, scoped_pathname_sockets)
670 {
671         socklen_t size_stream, size_dgram;
672         pid_t child;
673         int status;
674         char buf_child, buf_parent;
675         int pipe_parent[2];
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,
682         };
683         struct sockaddr_un dgram_pathname_addr = {
684                 .sun_family = AF_UNIX,
685         };
686 
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);
696 
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);
702 
703         /* Unnamed address for datagram socket. */
704         ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_DGRAM, 0, unnamed_sockets));
705 
706         ASSERT_EQ(0, pipe2(pipe_parent, O_CLOEXEC));
707 
708         child = fork();
709         ASSERT_LE(0, child);
710         if (child == 0) {
711                 int err;
712 
713                 EXPECT_EQ(0, close(pipe_parent[1]));
714                 EXPECT_EQ(0, close(unnamed_sockets[1]));
715 
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);
721 
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]));
725 
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]));
729 
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));
737 
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);
743                 EXPECT_EQ(1, err);
744 
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));
750 
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) {
758                         EXPECT_EQ(-1, err);
759                         EXPECT_EQ(EPERM, errno);
760                 } else {
761                         EXPECT_EQ(0, err);
762                         ASSERT_EQ(1, write(stream_abstract_socket, "e", 1));
763                 }
764                 EXPECT_EQ(0, close(stream_abstract_socket));
765 
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) {
773                         EXPECT_EQ(-1, err);
774                         EXPECT_EQ(EPERM, errno);
775                 } else {
776                         EXPECT_EQ(1, err);
777                 }
778 
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) {
784                         EXPECT_EQ(-1, err);
785                         EXPECT_EQ(EPERM, errno);
786                 } else {
787                         EXPECT_EQ(0, err);
788                         ASSERT_EQ(1, write(dgram_abstract_socket, "g", 1));
789                 }
790                 EXPECT_EQ(0, close(dgram_abstract_socket));
791 
792                 _exit(_metadata->exit_code);
793                 return;
794         }
795         EXPECT_EQ(0, close(pipe_parent[0]));
796         EXPECT_EQ(0, close(unnamed_sockets[0]));
797 
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,
802                           size_stream));
803         ASSERT_EQ(0, listen(stream_pathname_socket, backlog));
804 
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,
808                           size_dgram));
809 
810         /* Sets up abstract servers. */
811         stream_abstract_socket = socket(AF_UNIX, SOCK_STREAM, 0);
812         ASSERT_LE(0, stream_abstract_socket);
813         ASSERT_EQ(0,
814                   bind(stream_abstract_socket, &stream_abstract_addr.unix_addr,
815                        stream_abstract_addr.unix_addr_len));
816 
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));
822 
823         ASSERT_EQ(1, write(pipe_parent[1], ".", 1));
824         EXPECT_EQ(0, close(pipe_parent[1]));
825 
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]));
830 
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));
838 
839         ASSERT_EQ(1,
840                   read(dgram_pathname_socket, &buf_parent, sizeof(buf_parent)));
841         ASSERT_EQ('c', buf_parent);
842         ASSERT_EQ(1,
843                   read(dgram_pathname_socket, &buf_parent, sizeof(buf_parent)));
844         ASSERT_EQ('d', buf_parent);
845         EXPECT_EQ(0, close(dgram_pathname_socket));
846 
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);
851                 ASSERT_EQ(1,
852                           read(data_socket, &buf_parent, sizeof(buf_parent)));
853                 ASSERT_EQ('e', buf_parent);
854                 EXPECT_EQ(0, close(data_socket));
855 
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);
862         }
863 
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));
868 
869         if (WIFSIGNALED(status) || !WIFEXITED(status) ||
870             WEXITSTATUS(status) != EXIT_SUCCESS)
871                 _metadata->exit_code = KSFT_FAIL;
872 }
873 
874 TEST(datagram_sockets)
875 {
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];
879         int status;
880         char buf;
881         pid_t child;
882 
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);
888 
889         ASSERT_EQ(0, pipe2(pipe_parent, O_CLOEXEC));
890         ASSERT_EQ(0, pipe2(pipe_child, O_CLOEXEC));
891 
892         child = fork();
893         ASSERT_LE(0, child);
894         if (child == 0) {
895                 int client_conn_socket, client_unconn_socket;
896 
897                 EXPECT_EQ(0, close(pipe_parent[1]));
898                 EXPECT_EQ(0, close(pipe_child[0]));
899 
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);
904 
905                 /* Waits for parent to listen. */
906                 ASSERT_EQ(1, read(pipe_parent[0], &buf, 1));
907                 ASSERT_EQ(0,
908                           connect(client_conn_socket, &connected_addr.unix_addr,
909                                   connected_addr.unix_addr_len));
910 
911                 /*
912                  * Both connected and non-connected sockets can send data when
913                  * the domain is not scoped.
914                  */
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));
920 
921                 /* Scopes the domain. */
922                 create_scoped_domain(_metadata,
923                                      LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET);
924 
925                 /*
926                  * Connected socket sends data to the receiver, but the
927                  * non-connected socket must fail to send data.
928                  */
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));
935 
936                 EXPECT_EQ(0, close(client_conn_socket));
937                 EXPECT_EQ(0, close(client_unconn_socket));
938                 _exit(_metadata->exit_code);
939                 return;
940         }
941         EXPECT_EQ(0, close(pipe_parent[0]));
942         EXPECT_EQ(0, close(pipe_child[1]));
943 
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);
948 
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));
954 
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));
959 
960         /*
961          * Connected datagram socket will receive data, but
962          * non-connected datagram socket does not receive data.
963          */
964         ASSERT_EQ(1, read(pipe_child[0], &buf, 1));
965         ASSERT_EQ(1, recv(server_conn_socket, &buf, 1, 0));
966 
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));
971 
972         if (WIFSIGNALED(status) || !WIFEXITED(status) ||
973             WEXITSTATUS(status) != EXIT_SUCCESS)
974                 _metadata->exit_code = KSFT_FAIL;
975 }
976 
977 TEST(self_connect)
978 {
979         struct service_fixture connected_addr, non_connected_addr;
980         int connected_socket, non_connected_socket, status;
981         pid_t child;
982 
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);
988 
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);
993 
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));
998 
999         child = fork();
1000         ASSERT_LE(0, child);
1001         if (child == 0) {
1002                 /* Child's domain is scoped. */
1003                 create_scoped_domain(_metadata,
1004                                      LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET);
1005 
1006                 /*
1007                  * The child inherits the sockets, and cannot connect or
1008                  * send data to them.
1009                  */
1010                 ASSERT_EQ(-1,
1011                           connect(connected_socket, &connected_addr.unix_addr,
1012                                   connected_addr.unix_addr_len));
1013                 ASSERT_EQ(EPERM, errno);
1014 
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);
1019 
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);
1024 
1025                 EXPECT_EQ(0, close(connected_socket));
1026                 EXPECT_EQ(0, close(non_connected_socket));
1027                 _exit(_metadata->exit_code);
1028                 return;
1029         }
1030 
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));
1035 
1036         if (WIFSIGNALED(status) || !WIFEXITED(status) ||
1037             WEXITSTATUS(status) != EXIT_SUCCESS)
1038                 _metadata->exit_code = KSFT_FAIL;
1039 }
1040 
1041 TEST_HARNESS_MAIN
1042 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php