Skip the net-namespace-isolation test when policy disables it

Found by running the full suite as root with every unshare-* flag forced
off via -c/--config-file: this test only ever checked kernel support for
--unshare-net, never the config's own policy, so disabling it via
global.unshare-net correctly makes bwrap skip requesting the namespace --
production code working exactly as configured, not a bug -- while the test
still asserted isolation and failed.

Generalized the existing pid-only two-gate check into
namespace_type_would_isolate(type), covering any of bwrap.cpp's own
namespace_probes names, and used it here instead of a kernel-support-only
check.
This commit is contained in:
2026-09-05 10:33:18 +00:00
parent e047d243f2
commit 4f988c1bbc
+38 -9
View File
@@ -220,16 +220,38 @@ bool sleep_process_gone_within(const std::string& arg, int timeout_ms) {
} }
// Whether the current -t run's effective config (g_test_app_config, // Whether the current -t run's effective config (g_test_app_config,
// fixtures.h) would actually get bwrap to request --unshare-pid for a // fixtures.h) would actually get bwrap to request --unshare-<type> for a
// container it creates -- both the config's own policy *and* live kernel // container it creates -- both the config's own policy *and* live kernel
// support (detect_bwrap_unshare_args(), bwrap.h) have to allow it, the same // support (detect_bwrap_unshare_args(), bwrap.h) have to allow it, the same
// two-gate check build_bwrap_args() itself applies. // two-gate check build_bwrap_args() itself applies. `type` is one of
bool pid_namespace_would_isolate() { // "user"/"ipc"/"pid"/"net"/"uts"/"cgroup", matching bwrap.cpp's own
if (!g_test_app_config.unshare_pid.value_or(true)) { // namespace_probes names. Root never actually requests --unshare-user
// (bwrap.cpp) regardless of policy, so "user" always reports false here --
// callers that care about that distinction (this file's own "every
// kernel-supported namespace type" test) already exclude it up front rather
// than relying on this to explain why.
bool namespace_type_would_isolate(const std::string& type) {
bool policy_enabled;
if (type == "user") {
policy_enabled = g_test_app_config.unshare_user.value_or(true);
} else if (type == "ipc") {
policy_enabled = g_test_app_config.unshare_ipc.value_or(true);
} else if (type == "pid") {
policy_enabled = g_test_app_config.unshare_pid.value_or(true);
} else if (type == "net") {
policy_enabled = g_test_app_config.unshare_net.value_or(true);
} else if (type == "uts") {
policy_enabled = g_test_app_config.unshare_uts.value_or(true);
} else if (type == "cgroup") {
policy_enabled = g_test_app_config.unshare_cgroup.value_or(true);
} else {
policy_enabled = true; // unreachable given the fixed set of types above
}
if (!policy_enabled) {
return false; return false;
} }
auto supported = detect_bwrap_unshare_args(); auto supported = detect_bwrap_unshare_args();
return std::find(supported.begin(), supported.end(), "--unshare-pid") != supported.end(); return std::find(supported.begin(), supported.end(), "--unshare-" + type) != supported.end();
} }
// Whether run_bwrap()'s own session cgroup (session_cgroup.h) would actually // Whether run_bwrap()'s own session cgroup (session_cgroup.h) would actually
@@ -263,9 +285,16 @@ TEST_CASE("rootless -r/--run: network namespace is genuinely isolated, loopback
if (!image) { if (!image) {
SKIP("no busybox fixture (images/busybox.tar) -- see tests/setup-tests.py"); SKIP("no busybox fixture (images/busybox.tar) -- see tests/setup-tests.py");
} }
auto supported = detect_bwrap_unshare_args(); // Covers both "the kernel doesn't support net namespaces" (the original
if (std::find(supported.begin(), supported.end(), "--unshare-net") == supported.end()) { // check here) and "the config's own policy disables it" (found by
SKIP("this kernel doesn't support net namespaces"); // running the full suite as root with every unshare-* flag forced off
// via -c/--config-file, per the user's own explicit request) -- with
// unshare-net disabled, bwrap genuinely never requests --unshare-net, so
// the sandbox correctly shares the host's own net namespace; that's the
// production code doing exactly what it was told, not a bug, so this
// test SKIPs rather than reports a false failure.
if (!namespace_type_would_isolate("net")) {
SKIP("net namespace isolation is not available under the current config/kernel");
} }
ScratchXdgDirs scratch; ScratchXdgDirs scratch;
@@ -363,7 +392,7 @@ TEST_CASE("rootless -r/--run: a nohup-backgrounded process does not survive the
// regression this test should be flagging. Skip rather than fail so a // regression this test should be flagging. Skip rather than fail so a
// deliberately-crippled config (e.g. via -c/--config-file, g_test_app_config // deliberately-crippled config (e.g. via -c/--config-file, g_test_app_config
// above) doesn't produce a misleading failure here. // above) doesn't produce a misleading failure here.
if (!pid_namespace_would_isolate() && !session_cgroup_would_work()) { if (!namespace_type_would_isolate("pid") && !session_cgroup_would_work()) {
SKIP("neither a pid namespace nor a working session cgroup is available under the " SKIP("neither a pid namespace nor a working session cgroup is available under the "
"current config/kernel -- no mechanism exists to reap a reparented straggler here"); "current config/kernel -- no mechanism exists to reap a reparented straggler here");
} }