Skip to content

Commit 9086767

Browse files
committed
Support scoping abstract unix sockets
It's desirable in many cases to be able to allow a sandboxed program to exist with the current network namespace without permitting it access to all abstract unix sockets in said namespace. For example, X11 has an abstract unix socket @/tmp/.X11-unix/X0, which, using the abs scoping options this patch introduces, would be inaccessible to a sandboxed client that resides in the same network namespace as the X11 server. As we are relied on by various higher level sandboxing frameworks, such as Glycin and Flatpak, also introduce a `-try` variant that does not simply bail if unable to restrict access to said unix sockets. Closes: #330 Signed-off-by: Rahul Sandhu <nvraxn@gmail.com>
1 parent 5352384 commit 9086767

File tree

5 files changed

+103
-0
lines changed

5 files changed

+103
-0
lines changed

bubblewrap.c

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,15 @@
3232
#include <sys/signalfd.h>
3333
#include <sys/capability.h>
3434
#include <sys/prctl.h>
35+
#include <sys/syscall.h>
3536
#include <linux/sched.h>
3637
#include <linux/seccomp.h>
3738
#include <linux/filter.h>
3839

40+
#ifdef HAVE_LANDLOCK_H
41+
#include <linux/landlock.h>
42+
#endif
43+
3944
#include "utils.h"
4045
#include "network.h"
4146
#include "bind-mount.h"
@@ -92,6 +97,8 @@ static int opt_userns_fd = -1;
9297
static int opt_userns2_fd = -1;
9398
static int opt_pidns_fd = -1;
9499
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;
95102
static int next_perms = -1;
96103
static size_t next_size_arg = 0;
97104
static int next_overlay_src_count = 0;
@@ -373,6 +380,8 @@ usage (int ecode, FILE *out)
373380
" --perms OCTAL Set permissions of next argument (--bind-data, --file, etc.)\n"
374381
" --size BYTES Set size of next argument (only for --tmpfs)\n"
375382
" --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"
376385
);
377386
exit (ecode);
378387
}
@@ -2736,6 +2745,14 @@ parse_args_recurse (int *argcp,
27362745
argv += 2;
27372746
argc -= 2;
27382747
}
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+
}
27392756
else if (strcmp (arg, "--") == 0)
27402757
{
27412758
argv += 1;
@@ -2867,6 +2884,26 @@ namespace_ids_write (int fd,
28672884
}
28682885
}
28692886

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+
28702907
int
28712908
main (int argc,
28722909
char **argv)
@@ -3498,6 +3535,43 @@ main (int argc,
34983535
die ("creation of new user namespaces was not disabled as requested");
34993536
}
35003537

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+
35013575
/* All privileged ops are done now, so drop caps we don't need */
35023576
drop_privs (!is_privileged, true);
35033577

bwrap.xml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -617,6 +617,27 @@
617617
command line. Please be careful to the order they are specified.
618618
</para></listitem>
619619
</varlistentry>
620+
<varlistentry>
621+
<term><option>--scope-abstract-af-unix</option></term>
622+
<listitem><para>
623+
Scope access to abstract <citerefentry><refentrytitle>unix</refentrytitle><manvolnum>7</manvolnum></citerefentry> sockets.
624+
625+
This option will prevent the newly created sandbox from connecting to abstract AF_UNIX sockets
626+
created outside the sandbox,
627+
for example the X11 socket <literal>@/tmp/.X11-unix/X0</literal>,
628+
even if the network namespace is the same.
629+
630+
This has the same behaviour as LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET: see
631+
<citerefentry><refentrytitle>landlock</refentrytitle><manvolnum>7</manvolnum></citerefentry> for details.
632+
</para></listitem>
633+
</varlistentry>
634+
<varlistentry>
635+
<term><option>--scope-abstract-af-unix-try</option></term>
636+
<listitem><para>
637+
Try to do the same as <option>--scope-abstract-af-unix</option>,
638+
but if that isn't possible, continue without that restriction.
639+
</para></listitem>
640+
</varlistentry>
620641
</variablelist>
621642
</refsect1>
622643

completions/bash/bwrap

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ _bwrap() {
1515
--disable-userns
1616
--help
1717
--new-session
18+
--scope-abstract-af-unix
19+
--scope-abstract-af-unix-try
1820
--unshare-all
1921
--unshare-cgroup
2022
--unshare-cgroup-try

completions/zsh/_bwrap

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ _bwrap_args=(
6060
'--remount-ro[Remount DEST as readonly; does not recursively remount]:mount point to remount read-only:_files'
6161
'--ro-bind-try[Equal to --ro-bind but ignores non-existent SRC]:source:_files:destination:_files'
6262
'--ro-bind[Bind mount the host path SRC readonly on DEST]:source:_files:destination:_files'
63+
'--scope-abstract-af-unix[Prevent connecting to abstract unix sockets outside the sandbox]'
64+
'--scope-abstract-af-unix-try[Try --scope-abstract-af-unix if possible else continue by skipping it]'
6365
'--seccomp[Load and use seccomp rules from FD]: :_guard "[0-9]#" "file descriptor to read seccomp rules from"'
6466
'--setenv[Set an environment variable]:variable to set:_parameters -g "*export*":value of variable: :'
6567
'--size[Set size in bytes for next action argument]: :->after_size'

meson.build

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ if (
5757
], language : 'c')
5858
endif
5959

60+
if cc.check_header('linux/landlock.h')
61+
add_project_arguments('-DHAVE_LANDLOCK_H', language : 'c')
62+
endif
63+
6064
bash = find_program('bash', required : false)
6165

6266
if get_option('python') == ''

0 commit comments

Comments
 (0)