diff --git a/docs/source/markdown/options/privileged.md b/docs/source/markdown/options/privileged.md index 608b0ded8f..5cca2ad5e0 100644 --- a/docs/source/markdown/options/privileged.md +++ b/docs/source/markdown/options/privileged.md @@ -9,7 +9,9 @@ Give extended privileges to this container. The default is **false**. By default, Podman containers are unprivileged (**=false**) and cannot, for example, modify parts of the operating system. This is because by default a container is only allowed limited access to devices. A "privileged" container -is given the same access to devices as the user launching the container. +is given the same access to devices as the user launching the container, with +the exception of virtual consoles (_/dev/tty\d+_) when running in systemd +mode (**--systemd=always**). A privileged container turns off the security features that isolate the container from the host. Dropped Capabilities, limited devices, read-only mount diff --git a/docs/source/markdown/options/systemd.md b/docs/source/markdown/options/systemd.md index 973c063536..9a6e9fcf08 100644 --- a/docs/source/markdown/options/systemd.md +++ b/docs/source/markdown/options/systemd.md @@ -24,6 +24,7 @@ Running the container in systemd mode causes the following changes: * Podman sets the default stop signal to **SIGRTMIN+3**. * Podman sets **container_uuid** environment variable in the container to the first 32 characters of the container id. +* Podman will not mount virtual consoles (_/dev/tty\d+_) when running with **--privileged**. This allows systemd to run in a confined container without any modifications. diff --git a/pkg/util/utils_linux.go b/pkg/util/utils_linux.go index 27ab162e4a..e1e87c6d6d 100644 --- a/pkg/util/utils_linux.go +++ b/pkg/util/utils_linux.go @@ -7,7 +7,6 @@ import ( "os" "path" "path/filepath" - "strings" "syscall" "github.com/containers/podman/v4/libpod/define" @@ -107,7 +106,18 @@ func AddPrivilegedDevices(g *generate.Generator, systemdMode bool) error { Source: d.Path, Options: []string{"slave", "nosuid", "noexec", "rw", "rbind"}, } - if d.Path == "/dev/ptmx" || strings.HasPrefix(d.Path, "/dev/tty") { + + /* The following devices should not be mounted in rootless containers: + * + * /dev/ptmx: The host-provided /dev/ptmx should not be shared to + * the rootless containers for security reasons, and + * the container runtime will create it for us + * anyway (ln -s /dev/pts/ptmx /dev/ptmx); + * /dev/tty[0-9]+: Prevent the container from taking over the host's + * virtual consoles, even when not in systemd mode + * for backwards compatibility. + */ + if d.Path == "/dev/ptmx" || isVirtualConsoleDevice(d.Path) { continue } if _, found := mounts[d.Path]; found { @@ -121,6 +131,16 @@ func AddPrivilegedDevices(g *generate.Generator, systemdMode bool) error { } } else { for _, d := range hostDevices { + /* Restrict access to the virtual consoles *only* when running + * in systemd mode to improve backwards compatibility. See + * https://github.com/containers/podman/issues/15878. + * + * NOTE: May need revisiting in the future to drop the systemd + * condition if more use cases end up breaking the virtual terminals + * of people who specifically disable the systemd mode. It would + * also provide a more consistent behaviour between rootless and + * rootfull containers. + */ if systemdMode && isVirtualConsoleDevice(d.Path) { continue } diff --git a/test/system/030-run.bats b/test/system/030-run.bats index bcc78c907f..e6ad64bb0a 100644 --- a/test/system/030-run.bats +++ b/test/system/030-run.bats @@ -952,10 +952,29 @@ $IMAGE--c_ok" \ run_podman stop -t 0 $cid } -# 16925: --privileged + --systemd = share non-virtual-terminal TTYs -@test "podman run --privileged as root with systemd mounts non-vt /dev/tty devices" { - skip_if_rootless "this test only makes sense as root" +@test "podman run --privileged as rootless will not mount /dev/tty\d+" { + skip_if_not_rootless "this test as rootless" + # First, confirm that we _have_ /dev/ttyNN devices on the host. + # ('skip' would be nicer in some sense... but could hide a regression. + # Fedora, RHEL, Debian, Ubuntu, Gentoo, all have /dev/ttyN, so if + # this ever triggers, it means a real problem we should know about.) + vt_tty_devices_count=$(find /dev -regex '/dev/tty[0-9].*' | wc -w) + assert "$vt_tty_devices_count" != "0" \ + "Expected at least one /dev/ttyN device on host" + + run_podman run --rm -d --privileged $IMAGE ./pause + cid="$output" + + run_podman exec $cid sh -c "find /dev -regex '/dev/tty[0-9].*' | wc -w" + assert "$output" = "0" \ + "ls /dev/tty[0-9]: should have no ttyN devices" + + run_podman stop -t 0 $cid +} + +# 16925: --privileged + --systemd = share non-virtual-terminal TTYs (both rootful and rootless) +@test "podman run --privileged as root with systemd mounts non-vt /dev/tty devices" { # First, confirm that we _have_ non-virtual terminal /dev/tty* devices on # the host. non_vt_tty_devices_count=$(find /dev -regex '/dev/tty[^0-9].*' | wc -w)