From 418a4f1d2e52b3508b34be2e3d3ea688885b85c2 Mon Sep 17 00:00:00 2001 From: Antonio Ospite Date: Tue, 28 Apr 2026 17:46:27 +0000 Subject: [PATCH] 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 an automount timeout on a bind source) 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". In the first implementation enable the "fail open" behavior only to the case where bwrap fails to remount a submount with different flags during a `--bind` or `--bind-fd` operations, and still "fail close" for operations like `--dev-bind` and `--ro-bind` which are supposedly more critical. Signed-off-by: Antonio Ospite --- bind-mount.c | 9 +++++++++ bind-mount.h | 1 + bubblewrap.c | 11 ++++++++++- bwrap.xml | 25 +++++++++++++++++++++++++ 4 files changed, 45 insertions(+), 1 deletion(-) diff --git a/bind-mount.c b/bind-mount.c index a2e1ac6c..a7a729dd 100644 --- a/bind-mount.c +++ b/bind-mount.c @@ -476,6 +476,15 @@ bind_mount (int proc_fd, be safe to ignore because its not something the user can access. */ if (errno != EACCES) { + /* And if we don't need a security boundary, we can also + * ignore other remount errors for submounts. */ + if (options & BIND_FAIL_OPEN) + { + warn ("Can't remount %s submount (%s), ignoring error", + mount_tab[i].mountpoint, strerror (errno)); + continue; + } + if (failing_path != NULL) *failing_path = xstrdup (mount_tab[i].mountpoint); diff --git a/bind-mount.h b/bind-mount.h index 8a361fbd..8f2d5108 100644 --- a/bind-mount.h +++ b/bind-mount.h @@ -25,6 +25,7 @@ typedef enum { BIND_READONLY = (1 << 0), BIND_DEVICES = (1 << 2), BIND_RECURSIVE = (1 << 3), + BIND_FAIL_OPEN = (1 << 4), } bind_option_t; typedef enum diff --git a/bubblewrap.c b/bubblewrap.c index 2fb926c4..79b8134b 100644 --- a/bubblewrap.c +++ b/bubblewrap.c @@ -94,6 +94,7 @@ static int opt_tmp_overlay_count = 0; static int next_perms = -1; static size_t next_size_arg = 0; static int next_overlay_src_count = 0; +static bool opt_not_a_security_boundary = false; #define CAP_TO_MASK_0(x) (1L << ((x) & 31)) #define CAP_TO_MASK_1(x) CAP_TO_MASK_0(x - 32) @@ -350,6 +351,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" + " --not-a-security-boundary Do not fail hard when some sandbox setup steps fail;\n" + " use only when the sandbox is not a security boundary\n" ); exit (ecode); } @@ -1004,7 +1007,9 @@ setup_newroot (bool unshare_pid) die_with_error ("Can't create file at %s", op->dest); setup_op_bind_mount ((op->type == SETUP_RO_BIND_MOUNT ? BIND_READONLY : 0) | - (op->type == SETUP_DEV_BIND_MOUNT ? BIND_DEVICES : 0), + (op->type == SETUP_DEV_BIND_MOUNT ? BIND_DEVICES : 0) | + ((op->type == SETUP_BIND_MOUNT && + opt_not_a_security_boundary) ? BIND_FAIL_OPEN : 0), source, dest); if (op->fd >= 0) @@ -2427,6 +2432,10 @@ parse_args_recurse (int *argcp, argv += 2; argc -= 2; } + else if (strcmp (arg, "--not-a-security-boundary") == 0) + { + opt_not_a_security_boundary = true; + } else if (strcmp (arg, "--") == 0) { argv += 1; diff --git a/bwrap.xml b/bwrap.xml index 61fb0445..6b79faaa 100644 --- a/bwrap.xml +++ b/bwrap.xml @@ -614,6 +614,31 @@ command line. Please be careful to the order they are specified. + + + + + Declare that this invocation of bwrap is not + intended to create a security boundary between the sandbox and the + host system. When this option is given, certain non-fatal sandbox + setup failures (such as a bind mount failing because an automounter + did not respond in time) will produce a warning and will be skipped, + rather than causing bwrap to exit with an error. + + + This option is intended for callers such as + xdg-dbus-proxy or Steam that use + bwrap to adjust the filesystem layout for a + process, but do not rely on it to create a security boundary. + + + Other operations that are fundamental to establishing the sandbox + (creating namespaces, pivot_root, + dropping capabilities) will still cause a hard failure + regardless of this option. + + +