From fd7399760ac36695dc438095f0ac80cbac6c11f1 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Tue, 15 Sep 2026 19:53:52 +0100 Subject: [PATCH 1/2] Add a mechanism to enable debug() at compile-time Now that bubblewrap doesn't support being setuid, we can safely look at environment variables to decide whether to emit noisy debug messages. Instead of inventing our own environment variable, let's use `DEBUG_INVOCATION` as popularized by systemd. Enable debug messages in one CI pass, leaving them disabled in the other. Signed-off-by: Simon McVittie --- .github/workflows/check.yml | 4 +++- bubblewrap.c | 5 +++++ meson.build | 4 ++++ meson_options.txt | 6 ++++++ utils.c | 7 +++++++ utils.h | 3 ++- 6 files changed, 27 insertions(+), 2 deletions(-) diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 702558f7..105ab752 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -26,7 +26,7 @@ jobs: run: mkdir test-logs - name: setup run: | - meson setup _build -Db_sanitize=address,undefined -Doptimization=2 + meson setup _build -Db_sanitize=address,undefined -Ddebug_logging=true -Doptimization=2 env: CFLAGS: >- -Wp,-D_FORTIFY_SOURCE=2 @@ -38,11 +38,13 @@ jobs: ./_build/bwrap --bind / / --tmpfs /tmp true env: ASAN_OPTIONS: detect_leaks=0 + DEBUG_INVOCATION: '1' - name: test run: | BWRAP_MUST_WORK=1 meson test -C _build env: ASAN_OPTIONS: detect_leaks=0 + DEBUG_INVOCATION: '1' - name: Collect overall test logs on failure if: failure() run: mv _build/meson-logs/testlog.txt test-logs/ || true diff --git a/bubblewrap.c b/bubblewrap.c index d70afe41..87da2307 100644 --- a/bubblewrap.c +++ b/bubblewrap.c @@ -2920,6 +2920,11 @@ main (int argc, /* Get the (optional) privileges we need */ acquire_privs (); +#ifdef BWRAP_DEBUG + if (getenv ("DEBUG_INVOCATION") != NULL) + bwrap_is_debugging = true; +#endif + /* Never gain any more privs during exec */ if (prctl (PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) die_with_error ("prctl(PR_SET_NO_NEW_PRIVS) failed"); diff --git a/meson.build b/meson.build index feb3a785..6c51c145 100644 --- a/meson.build +++ b/meson.build @@ -87,6 +87,10 @@ if selinux_dep.found() endif endif +if get_option('debug') + cdata.set('BWRAP_DEBUG', 1) +endif + assume_kernel = get_option('assume_kernel') if assume_kernel != '' kernel_parts = assume_kernel.split('.') diff --git a/meson_options.txt b/meson_options.txt index d2ad767d..f4f4ac70 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -31,6 +31,12 @@ option( description : 'generate man pages', value : 'auto', ) +option( + 'debug_logging', + type : 'boolean', + description : 'Provide debug messages, off-by-default', + value : false, +) option( 'program_prefix', type : 'string', diff --git a/utils.c b/utils.c index 92ac6052..ac5c446d 100644 --- a/utils.c +++ b/utils.c @@ -39,6 +39,10 @@ #define security_check_context(x) security_check_context ((security_context_t) x) #endif +#ifdef BWRAP_DEBUG +bool bwrap_is_debugging = false; +#endif + bool bwrap_level_prefix = false; int proc_fd = -1; @@ -48,6 +52,9 @@ bwrap_logv (int severity, va_list args, const char *detail) { + if (severity == LOG_DEBUG && !bwrap_is_debugging) + return; + if (bwrap_level_prefix) fprintf (stderr, "<%d>", severity); diff --git a/utils.h b/utils.h index 7a26939d..0872223a 100644 --- a/utils.h +++ b/utils.h @@ -33,7 +33,8 @@ #include #include -#if 0 +#ifdef BWRAP_DEBUG +extern bool bwrap_is_debugging; #define debug(...) bwrap_log (LOG_DEBUG, __VA_ARGS__) #else #define debug(...) From 360dcd862aa49c2f4908bcaa6025051958b2a2d9 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Tue, 15 Sep 2026 19:48:18 +0100 Subject: [PATCH 2/2] bind-mount: Add some debug() calls around mount_setattr() Signed-off-by: Simon McVittie --- bind-mount.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/bind-mount.c b/bind-mount.c index ea521bf3..b1687bbe 100644 --- a/bind-mount.c +++ b/bind-mount.c @@ -473,6 +473,7 @@ mount_setattr_fallback (const char *resolved_dest, char **failing_path) { #if !USE_MOUNT_SETATTR_FALLBACK + debug ("No mount_setattr fallback"); (void) resolved_dest; (void) options; @@ -489,6 +490,12 @@ mount_setattr_fallback (const char *resolved_dest, cleanup_mount_tab MountTab mount_tab = NULL; int i; + debug ("Remounting mount table entries (%s %s) on \"%s\" %s", + readonly ? "ro" : "rw", + devices ? "dev" : "nodev", + resolved_dest, + recursive ? "recursively" : "only"); + mount_tab = parse_mountinfo (resolved_dest); if (mount_tab[0].mountpoint == NULL) { @@ -520,6 +527,7 @@ mount_setattr_fallback (const char *resolved_dest, { for (i = 1; mount_tab[i].mountpoint != NULL; i++) { + debug ("Acting on submount %s", mount_tab[i].mountpoint); current_flags = mount_tab[i].options; new_flags = current_flags | (devices ? 0 : MS_NODEV) | MS_NOSUID | (readonly ? MS_RDONLY : 0); if (new_flags != current_flags && @@ -548,6 +556,7 @@ mount_setattr_fallback (const char *resolved_dest, } } + debug ("-> success"); return BIND_MOUNT_SUCCESS; #endif /* USE_MOUNT_SETATTR_FALLBACK */ } @@ -679,6 +688,12 @@ mount_setattr_setup (const char *resolved_dest, .attr_set = MOUNT_ATTR_NOSUID, }; + debug ("Setting mount attributes (%s %s) on \"%s\" %s", + readonly ? "ro" : "rw", + devices ? "dev" : "nodev", + resolved_dest, + recursive ? "recursively" : "only"); + if (!devices) attr.attr_set |= MOUNT_ATTR_NODEV; @@ -703,6 +718,7 @@ mount_setattr_setup (const char *resolved_dest, if (mount_setattr_wrapper (resolved_dest_fd, "", setattr_flags, &attr, sizeof(attr)) == 0) { + debug ("-> success"); return BIND_MOUNT_SUCCESS; } else if (errno != ENOSYS) @@ -711,6 +727,8 @@ mount_setattr_setup (const char *resolved_dest, *failing_path = xstrdup (resolved_dest); return BIND_MOUNT_ERROR_MOUNT_SETATTR; } + + debug ("-> Falling back"); } /* mount_setattr(2) isn't available, so we'll have to do this the hard way: */ mount_attr_supported = false;