From cc47702ff8289f9f1b51e68670c78d184971f683 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Kl=C3=B6tzke?= Date: Tue, 30 Dec 2025 20:34:16 +0000 Subject: [PATCH 1/4] namespace-sandbox: improve userns availability check On Ubuntu, the usage of mount namespaces is apparently restricted in unprivileged user namespaces. In particular, if /proc/sys/kernel/apparmor_restrict_unprivileged_userns_complain is enabled, the clone() or unshare() call succeeds but the following mount() call to make the mount namespace private is rejected. --- src/namespace-sandbox/namespace-sandbox.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/namespace-sandbox/namespace-sandbox.c b/src/namespace-sandbox/namespace-sandbox.c index 763aa46e..ba0af0e9 100644 --- a/src/namespace-sandbox/namespace-sandbox.c +++ b/src/namespace-sandbox/namespace-sandbox.c @@ -74,7 +74,12 @@ struct Options { static int CreateTarget(const char *path, bool is_directory); // Child function used by CheckNamespacesSupported() in call to clone(). -static int CheckNamespacesSupportedChild(void *arg) { return 0; } +static int CheckNamespacesSupportedChild(void *arg) { + // Check that we can make our mount namespace private. This fails on Ubuntu if + // /proc/sys/kernel/apparmor_restrict_unprivileged_userns_complain is enabled. + return mount("none", "/", NULL, MS_REC | MS_PRIVATE, NULL) == 0 + ? EXIT_SUCCESS : EXIT_FAILURE; +} // Check whether the required namespaces are supported. static int CheckNamespacesSupported() { @@ -100,9 +105,13 @@ static int CheckNamespacesSupported() { CLONE_NEWUSER | CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWNET | SIGCHLD, NULL)); - CHECK_CALL(waitpid(pid, NULL, 0)); + int status = 0; + CHECK_CALL(waitpid(pid, &status, 0)); - return EXIT_SUCCESS; + if (WIFEXITED(status) && WEXITSTATUS(status) == 0) + return EXIT_SUCCESS; + else + return EXIT_FAILURE; } // Print out a usage error. argc and argv are the argument counter and vector, From 434c5d0a0478780b1936a5c8fe26520820e7695f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Kl=C3=B6tzke?= Date: Tue, 30 Dec 2025 22:11:59 +0100 Subject: [PATCH 2/4] test: compile namespace-sandbox in advance Make sure the namespace-sandbox binary is up-to-date before any of the test runs. Some of the blackbox tests call it directly and they could accidentally call an outdated version. --- test/run-tests.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/run-tests.sh b/test/run-tests.sh index 4e97f169..c7cff46c 100755 --- a/test/run-tests.sh +++ b/test/run-tests.sh @@ -227,6 +227,11 @@ if [[ -n $RUN_COVERAGE ]] ; then fi fi +# Make sure sandbox helper is updated +$RUN_PYTHON3 -c "from bob.develop.make import makeSandboxHelper +makeSandboxHelper() +" + # execute everything if nothing was specified if [[ -z ${RUN_UNITTEST_PAT+isset} && -z ${RUN_BLACKBOX_PAT+isset} && -z ${RUN_INTEGRATION_PAT+isset} ]] ; then From 8e060afe9f17b856bbd9650c272d49ced46c122e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Kl=C3=B6tzke?= Date: Tue, 30 Dec 2025 22:20:08 +0000 Subject: [PATCH 3/4] invoker: better detection why userns does not work Add the Ubuntu procfs knob and actually test for the current value to give a more precise hint of what is going on. --- pym/bob/invoker.py | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/pym/bob/invoker.py b/pym/bob/invoker.py index fb5b0af9..63e7fefe 100644 --- a/pym/bob/invoker.py +++ b/pym/bob/invoker.py @@ -450,9 +450,23 @@ def ensureSandboxUsable(): ret = subprocess.run([getSandboxHelperPath(), "-C"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL).returncode if ret != 0: + knobs = [("/proc/sys/kernel/unprivileged_userns_clone", "1"), + ("/proc/sys/kernel/apparmor_restrict_unprivileged_userns", "0")] + for knob, expected_val in knobs: + try: + with open(knob) as f: + if f.read().strip() != expected_val: + msg = f"Make sure {knob} is {expected_val}." + break + except FileNotFoundError: + pass + except OSError: + msg = f"Make sure {knob} is {expected_val}." + break + else: + msg = f"Not sure why that is exactly. Please consider opening a bug report at https://github.com/BobBuildTool/bob." raise BuildError("Your system does not support unprivileged containers! You need to build without sandbox (--no-sandbox).", - help="Make sure /proc/sys/kernel/unprivileged_userns_clone is 1." - " In case you use Docker, consider using the 'unconfined' seccomp profile." + help=f"{msg} In case you use Docker, consider using the 'unconfined' seccomp profile." " See https://bob-build-tool.readthedocs.io/en/latest/installation.html#sandbox-capabilities for more details.", returncode=3) except OSError as e: From 95f1f7d8bb1ba206f90aed18148517b8555395bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Kl=C3=B6tzke?= Date: Tue, 30 Dec 2025 23:22:01 +0100 Subject: [PATCH 4/4] doc: add hint about Ubuntu AppArmor --- doc/installation.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/installation.rst b/doc/installation.rst index 875f7bae..cb24a860 100644 --- a/doc/installation.rst +++ b/doc/installation.rst @@ -190,6 +190,11 @@ not permitted" error when building. Add the line :: to your ``/etc/sysctl.conf`` (or wherever your distro stores that). +Ubuntu is further restricting user namespaces through AppArmor. Either set +``/proc/sys/kernel/apparmor_restrict_unprivileged_userns`` to ``0`` or create +an AppArmor profile for the ``bob-namespace-sandbox`` binary that allows user +namespaces for Bob. + If you are using Docker, you must relax the security settings as they block nested containers by default. Adding ``--security-opt seccomp=unconfined --security-opt apparmor=unconfined`` to the ``docker run`` command should