|
32 | 32 | #include <sys/signalfd.h> |
33 | 33 | #include <sys/capability.h> |
34 | 34 | #include <sys/prctl.h> |
| 35 | +#include <sys/syscall.h> |
35 | 36 | #include <linux/sched.h> |
36 | 37 | #include <linux/seccomp.h> |
37 | 38 | #include <linux/filter.h> |
38 | 39 |
|
| 40 | +#ifdef HAVE_LANDLOCK_H |
| 41 | +#include <linux/landlock.h> |
| 42 | +#endif |
| 43 | + |
39 | 44 | #include "utils.h" |
40 | 45 | #include "network.h" |
41 | 46 | #include "bind-mount.h" |
@@ -92,6 +97,8 @@ static int opt_userns_fd = -1; |
92 | 97 | static int opt_userns2_fd = -1; |
93 | 98 | static int opt_pidns_fd = -1; |
94 | 99 | static int opt_tmp_overlay_count = 0; |
| 100 | +static bool opt_scope_abstract_unix_sockets = false; |
| 101 | +static bool opt_scope_abstract_unix_sockets_try = false; |
95 | 102 | static int next_perms = -1; |
96 | 103 | static size_t next_size_arg = 0; |
97 | 104 | static int next_overlay_src_count = 0; |
@@ -373,6 +380,8 @@ usage (int ecode, FILE *out) |
373 | 380 | " --perms OCTAL Set permissions of next argument (--bind-data, --file, etc.)\n" |
374 | 381 | " --size BYTES Set size of next argument (only for --tmpfs)\n" |
375 | 382 | " --chmod OCTAL PATH Change permissions of PATH (must already exist)\n" |
| 383 | + " --scope-abstract-af-unix Prevent connecting to abstract unix sockets outside the sandbox\n" |
| 384 | + " --scope-abstract-af-unix-try Try --scope-abstract-af-unix if possible else continue by skipping it\n" |
376 | 385 | ); |
377 | 386 | exit (ecode); |
378 | 387 | } |
@@ -2736,6 +2745,14 @@ parse_args_recurse (int *argcp, |
2736 | 2745 | argv += 2; |
2737 | 2746 | argc -= 2; |
2738 | 2747 | } |
| 2748 | + else if (strcmp (arg, "--scope-abstract-af-unix") == 0) |
| 2749 | + { |
| 2750 | + opt_scope_abstract_unix_sockets = true; |
| 2751 | + } |
| 2752 | + else if (strcmp (arg, "--scope-abstract-af-unix-try") == 0) |
| 2753 | + { |
| 2754 | + opt_scope_abstract_unix_sockets_try = true; |
| 2755 | + } |
2739 | 2756 | else if (strcmp (arg, "--") == 0) |
2740 | 2757 | { |
2741 | 2758 | argv += 1; |
@@ -2867,6 +2884,26 @@ namespace_ids_write (int fd, |
2867 | 2884 | } |
2868 | 2885 | } |
2869 | 2886 |
|
| 2887 | +#ifdef HAVE_LANDLOCK_H |
| 2888 | +#ifndef landlock_create_ruleset |
| 2889 | +static inline int |
| 2890 | +landlock_create_ruleset (const struct landlock_ruleset_attr *attr, |
| 2891 | + size_t size, |
| 2892 | + uint32_t flags) |
| 2893 | +{ |
| 2894 | + return syscall (SYS_landlock_create_ruleset, attr, size, flags); |
| 2895 | +} |
| 2896 | +#endif |
| 2897 | + |
| 2898 | +#ifndef landlock_restrict_self |
| 2899 | +static inline int |
| 2900 | +landlock_restrict_self (int ruleset_fd, uint32_t flags) |
| 2901 | +{ |
| 2902 | + return syscall (SYS_landlock_restrict_self, ruleset_fd, flags); |
| 2903 | +} |
| 2904 | +#endif |
| 2905 | +#endif |
| 2906 | + |
2870 | 2907 | int |
2871 | 2908 | main (int argc, |
2872 | 2909 | char **argv) |
@@ -3498,6 +3535,43 @@ main (int argc, |
3498 | 3535 | die ("creation of new user namespaces was not disabled as requested"); |
3499 | 3536 | } |
3500 | 3537 |
|
| 3538 | + if (opt_scope_abstract_unix_sockets) |
| 3539 | + { |
| 3540 | + #ifdef HAVE_LANDLOCK_H |
| 3541 | + static const struct landlock_ruleset_attr ruleset_attr = { |
| 3542 | + .scoped = LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET |
| 3543 | + }; |
| 3544 | + const int abi = landlock_create_ruleset (NULL, 0, LANDLOCK_CREATE_RULESET_VERSION); |
| 3545 | + if (abi < 0) |
| 3546 | + die_with_error ("failed to check Landlock compatibility"); |
| 3547 | + if (abi < 6) |
| 3548 | + die ("supported kernel Landlock ABI too old, version 6 or above required"); |
| 3549 | + const int ruleset_fd = landlock_create_ruleset (&ruleset_attr, sizeof (ruleset_attr), 0); |
| 3550 | + if (ruleset_fd < 0) |
| 3551 | + die_with_error ("failed to create Landlock ruleset"); |
| 3552 | + if (landlock_restrict_self (ruleset_fd, 0) < 0) |
| 3553 | + die_with_error ("failed to enforce Landlock ruleset"); |
| 3554 | + #else |
| 3555 | + die ("Landlock not available at compile time, cannot implement --scope-abstract-af-unix"); |
| 3556 | + #endif |
| 3557 | + } |
| 3558 | + |
| 3559 | + #ifdef HAVE_LANDLOCK_H |
| 3560 | + if (opt_scope_abstract_unix_sockets_try) |
| 3561 | + { |
| 3562 | + static const struct landlock_ruleset_attr ruleset_attr = { |
| 3563 | + .scoped = LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET |
| 3564 | + }; |
| 3565 | + const int abi = landlock_create_ruleset (NULL, 0, LANDLOCK_CREATE_RULESET_VERSION); |
| 3566 | + if (abi < 6) |
| 3567 | + { |
| 3568 | + const int ruleset_fd = landlock_create_ruleset (&ruleset_attr, sizeof (ruleset_attr), 0); |
| 3569 | + if (ruleset_fd < 0) |
| 3570 | + landlock_restrict_self (ruleset_fd, 0); |
| 3571 | + } |
| 3572 | + } |
| 3573 | + #endif |
| 3574 | + |
3501 | 3575 | /* All privileged ops are done now, so drop caps we don't need */ |
3502 | 3576 | drop_privs (!is_privileged, true); |
3503 | 3577 |
|
|
0 commit comments