Skip to content

Commit 2f55bae

Browse files
ao2smcv
authored andcommitted
bubblewrap: Add --not-a-security-boundary flag to enable fail-open behavior
Some callers of bwrap (e.g. xdg-dbus-proxy, Steam Runtime) use it purely to adjust filesystem layout, without any expectation of a security boundary between the sandbox and the host. For these callers, hard failures during sandbox setup (such as a subdirectory remount failing because an automounter did not respond in time) are unnecessarily fatal. So add a new `--not-a-security-boundary` option that can be used to relax the bubblewrap behavior in these specific cases, and allow it to "fail-open". The behavior can be tested by setting up an unavailable automount and check that: 1. bubblewrap succeeds even when accessing the unavailable automount fails; 2. remount flags like `nosuid,nodev` are not applied to the unavailable automount. ``` $ sudo sh -c 'echo "UUID=00000000-0000-0000-0000-000000000000 /mnt/bad ext4 defaults,noatime,nofail,inode_readahead_blks=64,nobarrier,x-systemd.automount 0 1" >> /etc/fstab' $ sudo systemctl daemon-reload $ sudo systemctl restart mnt-bad.automount $ mount | grep /mnt/bad systemd-1 on /mnt/bad type autofs (rw,relatime,fd=76,pgrp=1,timeout=0,minproto=5,maxproto=5,direct,pipe_ino=15854) $ ls /mnt/bad &>/dev/null & $ ./_build/bwrap --not-a-security-boundary --bind / / grep /mnt /proc/self/mountinfo bwrap: Can't remount /newroot/mnt/bad submount (No such device), ignoring error 860 769 0:41 / /mnt/bad rw,relatime master:45 - autofs systemd-1 rw,fd=107,pgrp=1,timeout=0,minproto=5,maxproto=5,direct,pipe_ino=144522 ``` steamrt/tasks#535 Resolves: #653 Helps: flatpak/flatpak#5112 Helps: ValveSoftware/steam-for-linux#10571 Helps: ValveSoftware/steam-runtime#766 Signed-off-by: Antonio Ospite <antonio.ospite@collabora.com>
1 parent 3d8b666 commit 2f55bae

5 files changed

Lines changed: 61 additions & 0 deletions

File tree

bind-mount.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,15 @@ bind_mount (int proc_fd,
476476
be safe to ignore because its not something the user can access. */
477477
if (errno != EACCES)
478478
{
479+
/* And if we don't need a security boundary, we can also
480+
* ignore other remount errors for submounts. */
481+
if (options & BIND_FAIL_OPEN)
482+
{
483+
warn ("Can't remount %s submount (%s), ignoring error",
484+
mount_tab[i].mountpoint, strerror (errno));
485+
continue;
486+
}
487+
479488
if (failing_path != NULL)
480489
*failing_path = xstrdup (mount_tab[i].mountpoint);
481490

bind-mount.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ typedef enum {
2525
BIND_READONLY = (1 << 0),
2626
BIND_DEVICES = (1 << 2),
2727
BIND_RECURSIVE = (1 << 3),
28+
BIND_FAIL_OPEN = (1 << 4),
2829
} bind_option_t;
2930

3031
typedef enum

bubblewrap.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ static int opt_tmp_overlay_count = 0;
9494
static int next_perms = -1;
9595
static size_t next_size_arg = 0;
9696
static int next_overlay_src_count = 0;
97+
static bool opt_not_a_security_boundary = false;
9798

9899
#define CAP_TO_MASK_0(x) (1L << ((x) & 31))
99100
#define CAP_TO_MASK_1(x) CAP_TO_MASK_0(x - 32)
@@ -350,6 +351,8 @@ usage (int ecode, FILE *out)
350351
" --perms OCTAL Set permissions of next argument (--bind-data, --file, etc.)\n"
351352
" --size BYTES Set size of next argument (only for --tmpfs)\n"
352353
" --chmod OCTAL PATH Change permissions of PATH (must already exist)\n"
354+
" --not-a-security-boundary Do not fail hard when some sandbox setup steps fail;\n"
355+
" use only when the sandbox is not a security boundary\n"
353356
);
354357
exit (ecode);
355358
}
@@ -1005,6 +1008,9 @@ setup_newroot (bool unshare_pid)
10051008

10061009
bind_option_t bind_flags = 0;
10071010

1011+
if (opt_not_a_security_boundary)
1012+
bind_flags |= BIND_FAIL_OPEN;
1013+
10081014
if (op->type == SETUP_RO_BIND_MOUNT)
10091015
bind_flags |= BIND_READONLY;
10101016

@@ -2433,6 +2439,10 @@ parse_args_recurse (int *argcp,
24332439
argv += 2;
24342440
argc -= 2;
24352441
}
2442+
else if (strcmp (arg, "--not-a-security-boundary") == 0)
2443+
{
2444+
opt_not_a_security_boundary = true;
2445+
}
24362446
else if (strcmp (arg, "--") == 0)
24372447
{
24382448
argv += 1;

bwrap.xml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,38 @@
614614
command line. Please be careful to the order they are specified.
615615
</para></listitem>
616616
</varlistentry>
617+
<varlistentry>
618+
<term><option>--not-a-security-boundary</option></term>
619+
<listitem>
620+
<para>
621+
Declare that this invocation of <command>bwrap</command>
622+
is not intended to create a security boundary
623+
between the sandbox and the host system.
624+
When this option is given,
625+
certain non-fatal sandbox setup failures
626+
(such as a subdirectory remount failing
627+
because an automounter did not respond in time)
628+
will produce a warning and will be skipped,
629+
rather than causing <command>bwrap</command> to exit with an error.
630+
In future releases of bubblewrap
631+
the effect of this option might be extended
632+
to make other sandbox setup operations non-fatal
633+
</para>
634+
<para>
635+
This option is intended for callers
636+
such as <application>xdg-dbus-proxy</application> or Steam
637+
that use <command>bwrap</command>
638+
to adjust the filesystem layout for a process,
639+
but do not rely on it to create a security boundary.
640+
</para>
641+
<para>
642+
Other operations that are fundamental to establishing the sandbox
643+
(creating namespaces, <function>pivot_root</function>,
644+
dropping capabilities)
645+
will still cause a hard failure regardless of this option.
646+
</para>
647+
</listitem>
648+
</varlistentry>
617649
</variablelist>
618650
</refsect1>
619651

tests/test-run.sh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -689,4 +689,13 @@ else
689689
fi
690690
fi
691691

692+
# Smoke-test --not-a-security-boundary
693+
#
694+
# Setting up an unavailable automount and triggering the right conditions is
695+
# complicated to do here, but we can at least check that the option is there,
696+
# and that it stays there.
697+
698+
$RUN --not-a-security-boundary true
699+
ok "Accepts --not-a-security-boundary"
700+
692701
done_testing

0 commit comments

Comments
 (0)