Skip to content

Commit 948bcbb

Browse files
committed
Support scoping abstract unix sockets
Closes: #330 Signed-off-by: Rahul Sandhu <nvraxn@gmail.com>
1 parent d6180f2 commit 948bcbb

1 file changed

Lines changed: 111 additions & 68 deletions

File tree

bubblewrap.c

Lines changed: 111 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,11 @@
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>
39+
#include <linux/landlock.h>
3840

3941
#include "utils.h"
4042
#include "network.h"
@@ -92,6 +94,7 @@ static int opt_userns_fd = -1;
9294
static int opt_userns2_fd = -1;
9395
static int opt_pidns_fd = -1;
9496
static int opt_tmp_overlay_count = 0;
97+
static bool opt_scope_abs_unix_sockets = false;
9598
static int next_perms = -1;
9699
static size_t next_size_arg = 0;
97100
static int next_overlay_src_count = 0;
@@ -305,74 +308,75 @@ usage (int ecode, FILE *out)
305308
fprintf (out, "usage: %s [OPTIONS...] [--] COMMAND [ARGS...]\n\n", argv0 ? argv0 : "bwrap");
306309

307310
fprintf (out,
308-
" --help Print this help\n"
309-
" --version Print version\n"
310-
" --args FD Parse NUL-separated args from FD\n"
311-
" --argv0 VALUE Set argv[0] to the value VALUE before running the program\n"
312-
" --level-prefix Prepend e.g. <3> to diagnostic messages\n"
313-
" --unshare-all Unshare every namespace we support by default\n"
314-
" --share-net Retain the network namespace (can only combine with --unshare-all)\n"
315-
" --unshare-user Create new user namespace (may be automatically implied if not setuid)\n"
316-
" --unshare-user-try Create new user namespace if possible else continue by skipping it\n"
317-
" --unshare-ipc Create new ipc namespace\n"
318-
" --unshare-pid Create new pid namespace\n"
319-
" --unshare-net Create new network namespace\n"
320-
" --unshare-uts Create new uts namespace\n"
321-
" --unshare-cgroup Create new cgroup namespace\n"
322-
" --unshare-cgroup-try Create new cgroup namespace if possible else continue by skipping it\n"
323-
" --userns FD Use this user namespace (cannot combine with --unshare-user)\n"
324-
" --userns2 FD After setup switch to this user namespace, only useful with --userns\n"
325-
" --disable-userns Disable further use of user namespaces inside sandbox\n"
326-
" --assert-userns-disabled Fail unless further use of user namespace inside sandbox is disabled\n"
327-
" --pidns FD Use this pid namespace (as parent namespace if using --unshare-pid)\n"
328-
" --uid UID Custom uid in the sandbox (requires --unshare-user or --userns)\n"
329-
" --gid GID Custom gid in the sandbox (requires --unshare-user or --userns)\n"
330-
" --hostname NAME Custom hostname in the sandbox (requires --unshare-uts)\n"
331-
" --chdir DIR Change directory to DIR\n"
332-
" --clearenv Unset all environment variables\n"
333-
" --setenv VAR VALUE Set an environment variable\n"
334-
" --unsetenv VAR Unset an environment variable\n"
335-
" --lock-file DEST Take a lock on DEST while sandbox is running\n"
336-
" --sync-fd FD Keep this fd open while sandbox is running\n"
337-
" --bind SRC DEST Bind mount the host path SRC on DEST\n"
338-
" --bind-try SRC DEST Equal to --bind but ignores non-existent SRC\n"
339-
" --dev-bind SRC DEST Bind mount the host path SRC on DEST, allowing device access\n"
340-
" --dev-bind-try SRC DEST Equal to --dev-bind but ignores non-existent SRC\n"
341-
" --ro-bind SRC DEST Bind mount the host path SRC readonly on DEST\n"
342-
" --ro-bind-try SRC DEST Equal to --ro-bind but ignores non-existent SRC\n"
343-
" --bind-fd FD DEST Bind open directory or path fd on DEST\n"
344-
" --ro-bind-fd FD DEST Bind open directory or path fd read-only on DEST\n"
345-
" --remount-ro DEST Remount DEST as readonly; does not recursively remount\n"
346-
" --overlay-src SRC Read files from SRC in the following overlay\n"
347-
" --overlay RWSRC WORKDIR DEST Mount overlayfs on DEST, with RWSRC as the host path for writes and\n"
348-
" WORKDIR an empty directory on the same filesystem as RWSRC\n"
349-
" --tmp-overlay DEST Mount overlayfs on DEST, with writes going to an invisible tmpfs\n"
350-
" --ro-overlay DEST Mount overlayfs read-only on DEST\n"
351-
" --exec-label LABEL Exec label for the sandbox\n"
352-
" --file-label LABEL File label for temporary sandbox content\n"
353-
" --proc DEST Mount new procfs on DEST\n"
354-
" --dev DEST Mount new dev on DEST\n"
355-
" --tmpfs DEST Mount new tmpfs on DEST\n"
356-
" --mqueue DEST Mount new mqueue on DEST\n"
357-
" --dir DEST Create dir at DEST\n"
358-
" --file FD DEST Copy from FD to destination DEST\n"
359-
" --bind-data FD DEST Copy from FD to file which is bind-mounted on DEST\n"
360-
" --ro-bind-data FD DEST Copy from FD to file which is readonly bind-mounted on DEST\n"
361-
" --symlink SRC DEST Create symlink at DEST with target SRC\n"
362-
" --seccomp FD Load and use seccomp rules from FD (not repeatable)\n"
363-
" --add-seccomp-fd FD Load and use seccomp rules from FD (repeatable)\n"
364-
" --block-fd FD Block on FD until some data to read is available\n"
365-
" --userns-block-fd FD Block on FD until the user namespace is ready\n"
366-
" --info-fd FD Write information about the running container to FD\n"
367-
" --json-status-fd FD Write container status to FD as multiple JSON documents\n"
368-
" --new-session Create a new terminal session\n"
369-
" --die-with-parent Kills with SIGKILL child process (COMMAND) when bwrap or bwrap's parent dies.\n"
370-
" --as-pid-1 Do not install a reaper process with PID=1\n"
371-
" --cap-add CAP Add cap CAP when running as privileged user\n"
372-
" --cap-drop CAP Drop cap CAP when running as privileged user\n"
373-
" --perms OCTAL Set permissions of next argument (--bind-data, --file, etc.)\n"
374-
" --size BYTES Set size of next argument (only for --tmpfs)\n"
375-
" --chmod OCTAL PATH Change permissions of PATH (must already exist)\n"
311+
" --help Print this help\n"
312+
" --version Print version\n"
313+
" --args FD Parse NUL-separated args from FD\n"
314+
" --argv0 VALUE Set argv[0] to the value VALUE before running the program\n"
315+
" --level-prefix Prepend e.g. <3> to diagnostic messages\n"
316+
" --unshare-all Unshare every namespace we support by default\n"
317+
" --share-net Retain the network namespace (can only combine with --unshare-all)\n"
318+
" --unshare-user Create new user namespace (may be automatically implied if not setuid)\n"
319+
" --unshare-user-try Create new user namespace if possible else continue by skipping it\n"
320+
" --unshare-ipc Create new ipc namespace\n"
321+
" --unshare-pid Create new pid namespace\n"
322+
" --unshare-net Create new network namespace\n"
323+
" --unshare-uts Create new uts namespace\n"
324+
" --unshare-cgroup Create new cgroup namespace\n"
325+
" --unshare-cgroup-try Create new cgroup namespace if possible else continue by skipping it\n"
326+
" --userns FD Use this user namespace (cannot combine with --unshare-user)\n"
327+
" --userns2 FD After setup switch to this user namespace, only useful with --userns\n"
328+
" --disable-userns Disable further use of user namespaces inside sandbox\n"
329+
" --assert-userns-disabled Fail unless further use of user namespace inside sandbox is disabled\n"
330+
" --pidns FD Use this pid namespace (as parent namespace if using --unshare-pid)\n"
331+
" --uid UID Custom uid in the sandbox (requires --unshare-user or --userns)\n"
332+
" --gid GID Custom gid in the sandbox (requires --unshare-user or --userns)\n"
333+
" --hostname NAME Custom hostname in the sandbox (requires --unshare-uts)\n"
334+
" --chdir DIR Change directory to DIR\n"
335+
" --clearenv Unset all environment variables\n"
336+
" --setenv VAR VALUE Set an environment variable\n"
337+
" --unsetenv VAR Unset an environment variable\n"
338+
" --lock-file DEST Take a lock on DEST while sandbox is running\n"
339+
" --sync-fd FD Keep this fd open while sandbox is running\n"
340+
" --bind SRC DEST Bind mount the host path SRC on DEST\n"
341+
" --bind-try SRC DEST Equal to --bind but ignores non-existent SRC\n"
342+
" --dev-bind SRC DEST Bind mount the host path SRC on DEST, allowing device access\n"
343+
" --dev-bind-try SRC DEST Equal to --dev-bind but ignores non-existent SRC\n"
344+
" --ro-bind SRC DEST Bind mount the host path SRC readonly on DEST\n"
345+
" --ro-bind-try SRC DEST Equal to --ro-bind but ignores non-existent SRC\n"
346+
" --bind-fd FD DEST Bind open directory or path fd on DEST\n"
347+
" --ro-bind-fd FD DEST Bind open directory or path fd read-only on DEST\n"
348+
" --remount-ro DEST Remount DEST as readonly; does not recursively remount\n"
349+
" --overlay-src SRC Read files from SRC in the following overlay\n"
350+
" --overlay RWSRC WORKDIR DEST Mount overlayfs on DEST, with RWSRC as the host path for writes and\n"
351+
" WORKDIR an empty directory on the same filesystem as RWSRC\n"
352+
" --tmp-overlay DEST Mount overlayfs on DEST, with writes going to an invisible tmpfs\n"
353+
" --ro-overlay DEST Mount overlayfs read-only on DEST\n"
354+
" --exec-label LABEL Exec label for the sandbox\n"
355+
" --file-label LABEL File label for temporary sandbox content\n"
356+
" --proc DEST Mount new procfs on DEST\n"
357+
" --dev DEST Mount new dev on DEST\n"
358+
" --tmpfs DEST Mount new tmpfs on DEST\n"
359+
" --mqueue DEST Mount new mqueue on DEST\n"
360+
" --dir DEST Create dir at DEST\n"
361+
" --file FD DEST Copy from FD to destination DEST\n"
362+
" --bind-data FD DEST Copy from FD to file which is bind-mounted on DEST\n"
363+
" --ro-bind-data FD DEST Copy from FD to file which is readonly bind-mounted on DEST\n"
364+
" --symlink SRC DEST Create symlink at DEST with target SRC\n"
365+
" --seccomp FD Load and use seccomp rules from FD (not repeatable)\n"
366+
" --add-seccomp-fd FD Load and use seccomp rules from FD (repeatable)\n"
367+
" --block-fd FD Block on FD until some data to read is available\n"
368+
" --userns-block-fd FD Block on FD until the user namespace is ready\n"
369+
" --info-fd FD Write information about the running container to FD\n"
370+
" --json-status-fd FD Write container status to FD as multiple JSON documents\n"
371+
" --new-session Create a new terminal session\n"
372+
" --die-with-parent Kills with SIGKILL child process (COMMAND) when bwrap or bwrap's parent dies.\n"
373+
" --as-pid-1 Do not install a reaper process with PID=1\n"
374+
" --cap-add CAP Add cap CAP when running as privileged user\n"
375+
" --cap-drop CAP Drop cap CAP when running as privileged user\n"
376+
" --perms OCTAL Set permissions of next argument (--bind-data, --file, etc.)\n"
377+
" --size BYTES Set size of next argument (only for --tmpfs)\n"
378+
" --chmod OCTAL PATH Change permissions of PATH (must already exist)\n"
379+
" --scope-abstract-unix-sockets Scope access to abstract unix sockets to within in the sandbox\n"
376380
);
377381
exit (ecode);
378382
}
@@ -2736,6 +2740,10 @@ parse_args_recurse (int *argcp,
27362740
argv += 2;
27372741
argc -= 2;
27382742
}
2743+
else if (strcmp (arg, "--scope-abstract-unix-sockets") == 0)
2744+
{
2745+
opt_scope_abs_unix_sockets = true;
2746+
}
27392747
else if (strcmp (arg, "--") == 0)
27402748
{
27412749
argv += 1;
@@ -2867,6 +2875,24 @@ namespace_ids_write (int fd,
28672875
}
28682876
}
28692877

2878+
#ifndef landlock_create_ruleset
2879+
static inline int
2880+
landlock_create_ruleset (const struct landlock_ruleset_attr *attr,
2881+
size_t size,
2882+
uint32_t flags)
2883+
{
2884+
return syscall (SYS_landlock_create_ruleset, attr, size, flags);
2885+
}
2886+
#endif
2887+
2888+
#ifndef landlock_restrict_self
2889+
static inline int
2890+
landlock_restrict_self (int ruleset_fd, uint32_t flags)
2891+
{
2892+
return syscall (SYS_landlock_restrict_self, ruleset_fd, flags);
2893+
}
2894+
#endif
2895+
28702896
int
28712897
main (int argc,
28722898
char **argv)
@@ -3491,6 +3517,23 @@ main (int argc,
34913517
die ("creation of new user namespaces was not disabled as requested");
34923518
}
34933519

3520+
if (opt_scope_abs_unix_sockets)
3521+
{
3522+
static const struct landlock_ruleset_attr ruleset_attr = {
3523+
.scoped = LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET
3524+
};
3525+
const int abi = landlock_create_ruleset (NULL, 0, LANDLOCK_CREATE_RULESET_VERSION);
3526+
if (abi < 0)
3527+
die_with_error ("failed to check Landlock compatibility");
3528+
if (abi < 6)
3529+
die ("supported kernel Landlock ABI too old, version 6 or above required");
3530+
const int ruleset_fd = landlock_create_ruleset (&ruleset_attr, sizeof (ruleset_attr), 0);
3531+
if (ruleset_fd < 0)
3532+
die_with_error ("failed to create Landlock ruleset");
3533+
if (landlock_restrict_self (ruleset_fd, 0) < 0)
3534+
die_with_error ("failed to enforce Landlock ruleset");
3535+
}
3536+
34943537
/* All privileged ops are done now, so drop caps we don't need */
34953538
drop_privs (!is_privileged, true);
34963539

0 commit comments

Comments
 (0)