From ef831c5aa0943a3aa3f78928cf481a981fabd5ae Mon Sep 17 00:00:00 2001 From: younghojan Date: Fri, 24 May 2024 14:30:21 +0800 Subject: [PATCH 1/2] Add helpful error message on Ubuntu 24.04 if namespaces are restricted --- benchexec/container.py | 8 ++++++++ benchexec/containerexecutor.py | 7 +++++++ benchexec/containerized_tool.py | 8 ++++++++ doc/INSTALL.md | 4 ++++ doc/container.md | 2 +- 5 files changed, 28 insertions(+), 1 deletion(-) diff --git a/benchexec/container.py b/benchexec/container.py index ca49ed4dd..e1bba2e5f 100644 --- a/benchexec/container.py +++ b/benchexec/container.py @@ -115,6 +115,14 @@ ) """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." +) + @contextlib.contextmanager def allocate_stack(size=DEFAULT_STACK_SIZE): diff --git a/benchexec/containerexecutor.py b/benchexec/containerexecutor.py index ff2a31641..bf442d6cf 100644 --- a/benchexec/containerexecutor.py +++ b/benchexec/containerexecutor.py @@ -754,6 +754,13 @@ def child(): traceback.extract_tb(e.__traceback__, limit=-1)[0].line, e, ) + if util.try_read_file( + "/proc/sys/kernel/apparmor_restrict_unprivileged_userns" + ) == "1" and e.errno in [ + errno.EPERM, + errno.EACCES, + ]: + 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..59fa90345 100644 --- a/benchexec/containerized_tool.py +++ b/benchexec/containerized_tool.py @@ -124,6 +124,14 @@ def _init_container_and_load_tool(tool_module, *args, **kwargs): try: _init_container(*args, **kwargs) except OSError as e: + if ( + util.try_read_file("/proc/sys/kernel/apparmor_restrict_unprivileged_userns") + == "1" + ) and e.errno in [ + errno.EPERM, + errno.EACCES, + ]: + 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. From fb6a54a90e0da9a2f778591311cd5bfb7f521cb5 Mon Sep 17 00:00:00 2001 From: Philipp Wendler Date: Thu, 13 Jun 2024 13:26:10 +0200 Subject: [PATCH 2/2] Refactoring: remove duplicate code into utility function --- benchexec/container.py | 15 +++++++++++++++ benchexec/containerexecutor.py | 7 +------ benchexec/containerized_tool.py | 8 +------- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/benchexec/container.py b/benchexec/container.py index e1bba2e5f..9c80055d2 100644 --- a/benchexec/container.py +++ b/benchexec/container.py @@ -44,6 +44,7 @@ "CONTAINER_GID", "CONTAINER_HOME", "CONTAINER_HOSTNAME", + "check_apparmor_userns_restriction", ] @@ -124,6 +125,20 @@ ) +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): """Allocate some memory that can be used as a stack. diff --git a/benchexec/containerexecutor.py b/benchexec/containerexecutor.py index bf442d6cf..eb6d08393 100644 --- a/benchexec/containerexecutor.py +++ b/benchexec/containerexecutor.py @@ -754,12 +754,7 @@ def child(): traceback.extract_tb(e.__traceback__, limit=-1)[0].line, e, ) - if util.try_read_file( - "/proc/sys/kernel/apparmor_restrict_unprivileged_userns" - ) == "1" and e.errno in [ - errno.EPERM, - errno.EACCES, - ]: + if container.check_apparmor_userns_restriction(e): logging.critical(container._ERROR_MSG_USER_NS_RESTRICTION) return CHILD_OSERROR diff --git a/benchexec/containerized_tool.py b/benchexec/containerized_tool.py index 59fa90345..3ab1c005e 100644 --- a/benchexec/containerized_tool.py +++ b/benchexec/containerized_tool.py @@ -124,13 +124,7 @@ def _init_container_and_load_tool(tool_module, *args, **kwargs): try: _init_container(*args, **kwargs) except OSError as e: - if ( - util.try_read_file("/proc/sys/kernel/apparmor_restrict_unprivileged_userns") - == "1" - ) and e.errno in [ - errno.EPERM, - errno.EACCES, - ]: + 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)