diff --git a/benchexec/container.py b/benchexec/container.py index ca49ed4dd..9c80055d2 100644 --- a/benchexec/container.py +++ b/benchexec/container.py @@ -44,6 +44,7 @@ "CONTAINER_GID", "CONTAINER_HOME", "CONTAINER_HOSTNAME", + "check_apparmor_userns_restriction", ] @@ -115,6 +116,28 @@ ) """Whether we use generated native code for clone or an unsafe Python fallback""" +_ERROR_MSG_USER_NS_RESTRICTION = ( + "Unprivileged user namespaces forbidden on this system, please " + "enable them with 'sysctl -w kernel.apparmor_restrict_unprivileged_userns=0'. " + "Ubuntu disables them by default since 24.04, refer to " + "https://ubuntu.com/blog/ubuntu-23-10-restricted-unprivileged-user-namespaces " + "for more information." +) + + +def check_apparmor_userns_restriction(error: OSError): + """Check whether the passed OSError was likely caused by Ubuntu's AppArmor-based + restriction of user namespaces.""" + return ( + error.errno + in [ + errno.EPERM, + errno.EACCES, + ] + and util.try_read_file("/proc/sys/kernel/apparmor_restrict_unprivileged_userns") + == "1" + ) + @contextlib.contextmanager def allocate_stack(size=DEFAULT_STACK_SIZE): diff --git a/benchexec/containerexecutor.py b/benchexec/containerexecutor.py index ff2a31641..eb6d08393 100644 --- a/benchexec/containerexecutor.py +++ b/benchexec/containerexecutor.py @@ -754,6 +754,8 @@ def child(): traceback.extract_tb(e.__traceback__, limit=-1)[0].line, e, ) + if container.check_apparmor_userns_restriction(e): + logging.critical(container._ERROR_MSG_USER_NS_RESTRICTION) return CHILD_OSERROR try: diff --git a/benchexec/containerized_tool.py b/benchexec/containerized_tool.py index bcd0259b7..3ab1c005e 100644 --- a/benchexec/containerized_tool.py +++ b/benchexec/containerized_tool.py @@ -124,6 +124,8 @@ def _init_container_and_load_tool(tool_module, *args, **kwargs): try: _init_container(*args, **kwargs) except OSError as e: + if container.check_apparmor_userns_restriction(e): + raise BenchExecException(container._ERROR_MSG_USER_NS_RESTRICTION) raise BenchExecException(f"Failed to configure container: {e}") return _load_tool(tool_module) diff --git a/doc/INSTALL.md b/doc/INSTALL.md index b5c90ce26..4f3a16c88 100644 --- a/doc/INSTALL.md +++ b/doc/INSTALL.md @@ -169,6 +169,10 @@ that are not usable on all distributions by default: On CentOS it can be necessary to enable this feature with `sudo sysctl -w user.max_user_namespaces=10000` or a respective entry in `/etc/sysctl.conf` (the exact value is not important). + On Ubuntu 24.04 (or newer versions) it can be necessary to enable this feature with + `sysctl -w kernel.apparmor_restrict_unprivileged_userns=0` or a respective entry + in `/etc/sysctl.conf`. + - **Unprivileged Overlay Filesystem**: This is only available since Linux 5.11 (kernel option `CONFIG_OVERLAY_FS`), diff --git a/doc/container.md b/doc/container.md index a01b40b27..fe81c5354 100644 --- a/doc/container.md +++ b/doc/container.md @@ -211,7 +211,7 @@ in a container with `containerexec` than using `benchexec` or `runexec`. #### `Cannot execute ...: Unprivileged user namespaces forbidden on this system...` Unprivileged user namespaces are forbidden on your system -(this is the default on some distributions like Debian, Arch Linux, and CentOS). +(this is the default on some distributions like Debian, Arch Linux, CentOS, and Ubuntu since 24.04). Please check the [system requirements](INSTALL.md#kernel-requirements) how to enable them.