Package: systemd-sysv Version: 255.3-2 Running 'telinit u' within a podman container results in an infinite loop as telinit repeatedly re-exec's itself.
This behaviour comes from systemctl.c which has this logic for handling 'telinit': if (sd_booted() > 0) { arg_action = _ACTION_INVALID; return telinit_parse_argv(argc, argv); } else { /* Hmm, so some other init system is running, we need to forward this request to it. */ arg_action = ACTION_TELINIT; return 1; } Inside a container 'sd_booted()' will (typically) indicate systemd is NOT running, thus the 'else' clause will be followed. ACTION_TELINIT instructs the caller to execve() the telinit binary belonging to any *non-systemd* init impl, if any. This binary is determined by the 'telinit-path' meson build option, which defaults to /lib/sysvinit/telinit. Debian used to override this to /usr/lib/sysvinit/telinit, but a few months ago in Sid, this was changed to point to /usr/sbin/telinit, which is a symlink back to /usr/bin/systemctl: https://salsa.debian.org/systemd-team/systemd/-/commit/da95bc801088a6ab454851cf01addf97dd2c1ab3 IOW, Debian dpkg build has told systemd that the non-systemd telinit binary is the systemd telinit binary. Hilarity now ensues as it ends up exec'ing itself for all eternity :-) You might ask why should anyone hit this scenario ? Well consider that the 'libc6' package will run 'telinit u' in its postinst script, if it sees it is in a non-systemd environment. Not immediately a problem, since libc6 will be pre-installed in any container or VM disk image and thus the 'postinst' script won't run [not sure if 'postinst' is run on upgrades too ?]. Debian containers are an execellent environment for testing cross compiles though, and thus people will install a foreign arch libc6 package in the container which does trigger the postinst script. The following hangs (well loops forever in execve()): $ podman run -it debian:sid-slim # dpkg --add-architecture i386 # apt-get update # apt-get install systemd-sysv # apt-get install libc6:i386 Simpler example $ podman run -it debian:sid-slim # dpkg --add-architecture i386 # apt-get update # apt-get install systemd-sysv strace # strace -e trace=execve telinit u strace: Process 232065 attached execve("/usr/sbin/telinit", ["telinit", "u"], 0x7ffd9b26ba00 /* 24 vars */) = 0 execve("/usr/sbin/telinit", ["telinit", "u"], 0x7ffdab55f1d0 /* 24 vars */) = 0 execve("/usr/sbin/telinit", ["telinit", "u"], 0x7ffe79152400 /* 24 vars */) = 0 ....1000000's more times.... Even then though, most people won't (knowingly) install the systemd-sysv dpkg, so won't hit this problem. A few packages will pull in systemd-sysv behind the scenes, so you can unwittingly hit the problem. For libvirt CI, we install the open-iscsi and policykit-1 packages which both pull in systemd-sysv, so this hangs: $ podman run -it debian:sid-slim # dpkg --add-architecture i386 # apt-get update # apt-get install systemd-sysv # apt-get install open-iscsi:i386 Our foreign arch CI jobs that use Sid are thus suffering broken container builds right now. The simple solution appears to be to just remove the '-Dtelinit-path' option from debian/rules, and leave it on systemd's built-in defaults. The binary at this default path won't exist, and thus on a non-systemd execution environment 'telinit u' will simply exit with an error: # telinit u Couldn't find an alternative telinit implementation to spawn. which is a sensible behaviour and what has happened in containers with Debian until recent Sid. Other distros (eg Fedora) leave the telinit binary on systemd's default (non-existant) path too. Possibly the upstream systemctl.c code should be made to protect itself against such a mis-configuration by setting an env variable it can look at to detect re-exec of itself. Possibly libc6 package postinst script should skip running its 'telinit u' action if it detects it is inside a container, though that could possibly break something if people do have a real in-systemd init running ? Seems fairly low probability. With regards, Daniel