Skip to content

Commit

Permalink
fix: Add error message output to respond to the impact of Ubuntu 24.0…
Browse files Browse the repository at this point in the history
…4's restriction on user namespaces for containers, and update documentation

- Updated `container.py` and `containerexecutor.py` to detect whether BenchExec is being used with container mode enabled on Ubuntu 24.04 and the use of unprivileged user namespaces is restricted in system configuration, output the corresponding error message if so.
- Updated the relevant documentation.
  • Loading branch information
younghojan committed May 24, 2024
1 parent 6467aa5 commit f27c560
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 5 deletions.
19 changes: 19 additions & 0 deletions benchexec/container.py
Original file line number Diff line number Diff line change
Expand Up @@ -321,12 +321,14 @@ def setup_user_mapping(
@param parent_gid: The GID that is used in the parent namespace.
"""
proc_child = os.path.join("/proc", str(pid))
exception_occurred = False
try:
# map uid internally to our uid externally
uid_map = f"{uid} {parent_uid} 1"
util.write_file(uid_map, proc_child, "uid_map")
except OSError as e:
logging.warning("Creating UID mapping into container failed: %s", e)
exception_occurred = True

try:
util.write_file("deny", proc_child, "setgroups")
Expand All @@ -335,13 +337,30 @@ def setup_user_mapping(
# but if it does not exist, we do not need to write to it.
if e.errno != errno.ENOENT:
logging.warning("Could not write to setgroups file in /proc: %s", e)
exception_occurred = True

try:
# map gid internally to our gid externally
gid_map = f"{gid} {parent_gid} 1"
util.write_file(gid_map, proc_child, "gid_map")
except OSError as e:
logging.warning("Creating GID mapping into container failed: %s", e)
exception_occurred = True

# Ubuntu 24.04 restricts user namespaces, output error message here
if (
exception_occurred
and util.check_ubuntu_version() == "24.04"
and util.try_read_file("/proc/sys/kernel/apparmor_restrict_unprivileged_userns")
== "1"
):
logging.warning(
"Ubuntu 24.04 restircts user namespaces, "
"preventing UID/GID mapping into container. "
"Please try 'echo 0 | sudo tee "
"/proc/sys/kernel/apparmor_restrict_unprivileged_userns' "
"as a temporary workaround, or disable container mode."
)


_SIOCGIFFLAGS = 0x8913 # /usr/include/bits/ioctls.h
Expand Down
27 changes: 22 additions & 5 deletions benchexec/containerexecutor.py
Original file line number Diff line number Diff line change
Expand Up @@ -713,11 +713,28 @@ def child():
try:
socket.sethostname(container.CONTAINER_HOSTNAME)
except PermissionError:
logging.warning(
"Changing hostname in container prevented "
"by system configuration, "
"real hostname will leak into the container."
)
# Ubuntu 24.04 restricts user namespaces, output error message here
if (
util.check_ubuntu_version() == "24.04"
and util.try_read_file(
"/proc/sys/kernel/apparmor_restrict_unprivileged_userns"
)
== "1"
):
logging.warning(
"Ubuntu 24.04 restircts user namespaces, "
"preventing changing hostname in container, "
"real hostname will leak into the container. "
"Please try 'echo 0 | sudo tee "
"/proc/sys/kernel/apparmor_restrict_unprivileged_userns' "
"as a temporary workaround, or disable container mode."
)
else:
logging.warning(
"Changing hostname in container prevented "
"by system configuration, "
"real hostname will leak into the container."
)

if not self._allow_network:
container.activate_network_interface("lo")
Expand Down
19 changes: 19 additions & 0 deletions benchexec/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -819,3 +819,22 @@ def check_msr():
if all(os.access(f"/dev/cpu/{cpu}/msr", os.W_OK) for cpu in cpu_dirs):
res["write"] = True
return res


def check_ubuntu_version():
"""
Check the Ubuntu version by reading the content of the '/etc/os-release' file.
"""
if content := try_read_file("/etc/os-release"):
lines = content.splitlines()
name = None
version_id = None
for line in lines:
if line.startswith("NAME="):
name = line.split("=")[1].strip().strip('"')
elif line.startswith("VERSION_ID="):
version_id = line.split("=")[1].strip().strip('"')

if name == "Ubuntu":
return version_id
return None
11 changes: 11 additions & 0 deletions doc/container.md
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,17 @@ with several versions of the Linux kernel, including at least kernel versions up
If a kernel upgrade does not help, please use a different access mode for NFS-mounted directories,
such as `--hidden-dir` or `--read-only-dir`.

#### Problems due to default user namespaces restrictions on Ubuntu 24.04: `Changing hostname in container prevented by system configuration...`, `Creating UID mapping into container failed: [Errno 1] Operation not permitted`, `Could not write to setgroups file in /proc: [Errno 13] Permission denied`, `Creating GID mapping into container failed: [Errno 1] Operation not permitted`

It seems that you are using BenchExec on Ubuntu 24.04, which restricts the use of unprivileged user namespaces, making it impossible to change the hostname or create GID/UID mappings in a container. You can temporarily disable AppArmor's restriction on unprivileged user namespaces by executing
```
echo 0 | sudo tee /proc/sys/kernel/apparmor_restrict_unprivileged_userns
```
This setting will be reset upon reboot. To apply a persistent setting, create a new file at `/etc/sysctl.d/60-apparmor-namespace.conf` with the following contents:
```
kernel.apparmor_restrict_unprivileged_userns=0
```

### BenchExec sometimes hangs if many parallel runs are executed
This happens if we clone the Python process while it is in an inconsistent state.
Make sure to use BenchExec 3.14 or newer,
Expand Down

0 comments on commit f27c560

Please sign in to comment.