-
Notifications
You must be signed in to change notification settings - Fork 273
Support scoping abstract unix sockets #704
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -32,10 +32,15 @@ | |
| #include <sys/signalfd.h> | ||
| #include <sys/capability.h> | ||
| #include <sys/prctl.h> | ||
| #include <sys/syscall.h> | ||
| #include <linux/sched.h> | ||
| #include <linux/seccomp.h> | ||
| #include <linux/filter.h> | ||
|
|
||
| #ifdef HAVE_LANDLOCK_H | ||
| #include <linux/landlock.h> | ||
| #endif | ||
|
|
||
| #include "utils.h" | ||
| #include "network.h" | ||
| #include "bind-mount.h" | ||
|
|
@@ -92,6 +97,8 @@ static int opt_userns_fd = -1; | |
| static int opt_userns2_fd = -1; | ||
| static int opt_pidns_fd = -1; | ||
| static int opt_tmp_overlay_count = 0; | ||
| static bool opt_scope_abstract_unix_sockets = false; | ||
| static bool opt_scope_abstract_unix_sockets_try = false; | ||
| static int next_perms = -1; | ||
| static size_t next_size_arg = 0; | ||
| static int next_overlay_src_count = 0; | ||
|
|
@@ -373,6 +380,8 @@ usage (int ecode, FILE *out) | |
| " --perms OCTAL Set permissions of next argument (--bind-data, --file, etc.)\n" | ||
| " --size BYTES Set size of next argument (only for --tmpfs)\n" | ||
| " --chmod OCTAL PATH Change permissions of PATH (must already exist)\n" | ||
| " --scope-abstract-af-unix Prevent connecting to abstract unix sockets outside the sandbox\n" | ||
| " --scope-abstract-af-unix-try Try --scope-abstract-af-unix if possible else continue by skipping it\n" | ||
| ); | ||
| exit (ecode); | ||
| } | ||
|
|
@@ -2736,6 +2745,14 @@ parse_args_recurse (int *argcp, | |
| argv += 2; | ||
| argc -= 2; | ||
| } | ||
| else if (strcmp (arg, "--scope-abstract-af-unix") == 0) | ||
| { | ||
| opt_scope_abstract_unix_sockets = true; | ||
| } | ||
| else if (strcmp (arg, "--scope-abstract-af-unix-try") == 0) | ||
| { | ||
| opt_scope_abstract_unix_sockets_try = true; | ||
| } | ||
| else if (strcmp (arg, "--") == 0) | ||
| { | ||
| argv += 1; | ||
|
|
@@ -2867,6 +2884,26 @@ namespace_ids_write (int fd, | |
| } | ||
| } | ||
|
|
||
| #ifdef HAVE_LANDLOCK_H | ||
| #ifndef landlock_create_ruleset | ||
| static inline int | ||
| landlock_create_ruleset (const struct landlock_ruleset_attr *attr, | ||
| size_t size, | ||
| uint32_t flags) | ||
| { | ||
| return syscall (SYS_landlock_create_ruleset, attr, size, flags); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This might need some adjustment if there are glibc/kernel combinations where |
||
| } | ||
| #endif | ||
|
|
||
| #ifndef landlock_restrict_self | ||
| static inline int | ||
| landlock_restrict_self (int ruleset_fd, uint32_t flags) | ||
| { | ||
| return syscall (SYS_landlock_restrict_self, ruleset_fd, flags); | ||
| } | ||
| #endif | ||
| #endif | ||
|
|
||
| int | ||
| main (int argc, | ||
| char **argv) | ||
|
|
@@ -3498,6 +3535,43 @@ main (int argc, | |
| die ("creation of new user namespaces was not disabled as requested"); | ||
| } | ||
|
|
||
| if (opt_scope_abstract_unix_sockets) | ||
| { | ||
| #ifdef HAVE_LANDLOCK_H | ||
| static const struct landlock_ruleset_attr ruleset_attr = { | ||
| .scoped = LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET | ||
| }; | ||
| const int abi = landlock_create_ruleset (NULL, 0, LANDLOCK_CREATE_RULESET_VERSION); | ||
| if (abi < 0) | ||
| die_with_error ("failed to check Landlock compatibility"); | ||
| if (abi < 6) | ||
| die ("supported kernel Landlock ABI too old, version 6 or above required"); | ||
| const int ruleset_fd = landlock_create_ruleset (&ruleset_attr, sizeof (ruleset_attr), 0); | ||
| if (ruleset_fd < 0) | ||
| die_with_error ("failed to create Landlock ruleset"); | ||
| if (landlock_restrict_self (ruleset_fd, 0) < 0) | ||
| die_with_error ("failed to enforce Landlock ruleset"); | ||
| #else | ||
| die ("Landlock not available at compile time, cannot implement --scope-abstract-af-unix"); | ||
| #endif | ||
| } | ||
|
|
||
| #ifdef HAVE_LANDLOCK_H | ||
| if (opt_scope_abstract_unix_sockets_try) | ||
| { | ||
| static const struct landlock_ruleset_attr ruleset_attr = { | ||
| .scoped = LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET | ||
| }; | ||
| const int abi = landlock_create_ruleset (NULL, 0, LANDLOCK_CREATE_RULESET_VERSION); | ||
| if (abi < 6) | ||
| { | ||
| const int ruleset_fd = landlock_create_ruleset (&ruleset_attr, sizeof (ruleset_attr), 0); | ||
| if (ruleset_fd < 0) | ||
| landlock_restrict_self (ruleset_fd, 0); | ||
| } | ||
| } | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This duplicates the logic for actually applying the restriction between the fail-open and fail-closed branches, which is unfortunate. In the places that already set errno, you don't need to set it again. In places that fail but don't set errno (I think this is just the "Function not implemented" seems like a reasonable least-bad representation for "your kernel is too old" (it's also the error code we would get from these syscalls if glibc knows about Landlock but the running kernel does not), but I could also see an argument for using And then its caller can look more like this (untested): (Or the function could return NULL on success and a non-NULL error message on failure, but I think a boolean result is more obvious, even if strictly speaking it's redundant.) Unfortunately bubblewrap doesn't depend on any useful libraries like GLib or libdbus (by policy, because it's sometimes setuid root, so every dependency adds attack surface), so we have to reinvent error-reporting.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's worth keeping in mind how this function could be structured so that if we use more Landlock features in future, it can cope with that. For instance we might eventually want to change it from to something more like But we can cross that bridge when we come to it. |
||
| #endif | ||
|
|
||
| /* All privileged ops are done now, so drop caps we don't need */ | ||
| drop_privs (!is_privileged, true); | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -57,6 +57,10 @@ if ( | |
| ], language : 'c') | ||
| endif | ||
|
|
||
| if cc.check_header('linux/landlock.h') | ||
| add_project_arguments('-DHAVE_LANDLOCK_H', language : 'c') | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When using Autotools-style Also please move this below the creation of Many projects do something like this (adapted from https://gitlab.freedesktop.org/dbus/dbus/-/blob/main/meson.build?ref_type=heads, untested): I agree that it probably it isn't worth doing that yet, but let's choose our naming so that it would be possible to do that in future. |
||
| endif | ||
|
|
||
| bash = find_program('bash', required : false) | ||
|
|
||
| if get_option('python') == '' | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.