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 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: 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, 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