You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
stdout of service's ExecStartPre= should not be written to the serving socket.
Unexpected behaviour you saw
stdout of service's ExecStartPre= is written to the serving socket.
Steps to reproduce the problem
The ExecStartPre= directive on service units is often used as a lightweight "do this setup thing before starting my real daemon".
This works fine for most service units. But for units that start are StandardOutput=socket, users might not be expecting that the stdout of their setup.sh is written over the socket.
Examples:
• NixOS in 2016 had this issue: NixOS/nixpkgs#19589 . In this case it was just the public key output of ssh-keygen, but it could have been more serious.
• Gentoo dev in 2014 suggesting this for OpenSSH: https://bugs.gentoo.org/501708#c8
• I personally ran into this issue.
That said, this interaction of StandardOutput=socket and ExecStartPre= is risky, and it's not clear what valid use cases there are (though I'd be keen to hear some!).
Are there ways we can mitigate this risk?
Ideas:
• Document in systemd.service's ExecStartPre= doc that any output will be streamed according to StandardOutput, even over the wire.
• Unconditionally stream ExecStartPre's stdout to journald
• Conditionally stream ExecStartPre's stdout, based on a new directive ExecStartPreStandardOutput. That doesn't sound so great though.
• Ignore ExecStartPre= on StandardOutput=socket, with a warning.
All of the above applies to stdin too. Worse, if your setup.sh reads stdin, it's reading untrusted input.
Additional program output to the terminal or log subsystem illustrating the issue
$ cat ~/.config/systemd/user/foo.socket
[Unit]
Description=Foo Socket
PartOf=foo.service
[Socket]
ListenStream=9999
Accept=yes
[Install]
WantedBy=sockets.target
$ cat ~/.config/systemd/user/foo\@.service
[Unit]
Description=Foo Service
After=network.target foo.socket
Requires=foo.socket
[Service]
Type=simple
StandardInput=socket
# Let's pretend this is a setup-style script, whose output I'm expecting to go to journald.
ExecStartPre=/usr/bin/hostname
ExecStart=/usr/bin/uptime
TimeoutStopSec=5
[Install]
WantedBy=default.target
$ systemctl --user daemon-reload
$ systemctl --user start foo.socket
$ nc localhost 9999
my.host.example.com # Oh no, this is my setup's stdout!
15:40:57 up 2 days, 1:23, 1 user, load average: 1.14, 1.11, 1.17
The text was updated successfully, but these errors were encountered:
systemd version the issue has been seen with
255
Used distribution
Debian Testing
Linux kernel version used
6.6.15
CPU architectures issue was seen on
x86_64
Component
systemd
Expected behaviour you didn't see
stdout of service's ExecStartPre= should not be written to the serving socket.
Unexpected behaviour you saw
stdout of service's ExecStartPre= is written to the serving socket.
Steps to reproduce the problem
The ExecStartPre= directive on service units is often used as a lightweight "do this setup thing before starting my real daemon".
This works fine for most service units. But for units that start are StandardOutput=socket, users might not be expecting that the stdout of their setup.sh is written over the socket.
Examples:
• NixOS in 2016 had this issue: NixOS/nixpkgs#19589 . In this case it was just the public key output of ssh-keygen, but it could have been more serious.
• Gentoo dev in 2014 suggesting this for OpenSSH: https://bugs.gentoo.org/501708#c8
• I personally ran into this issue.
I can see the logic for the current behaviour, and know that systemd.socket has its own ExecStartPre= directive which runs before the listening socket is created.
That said, this interaction of StandardOutput=socket and ExecStartPre= is risky, and it's not clear what valid use cases there are (though I'd be keen to hear some!).
Are there ways we can mitigate this risk?
Ideas:
• Document in systemd.service's ExecStartPre= doc that any output will be streamed according to StandardOutput, even over the wire.
• Unconditionally stream ExecStartPre's stdout to journald
• Conditionally stream ExecStartPre's stdout, based on a new directive ExecStartPreStandardOutput. That doesn't sound so great though.
• Ignore ExecStartPre= on StandardOutput=socket, with a warning.
All of the above applies to stdin too. Worse, if your setup.sh reads stdin, it's reading untrusted input.
Additional program output to the terminal or log subsystem illustrating the issue
The text was updated successfully, but these errors were encountered: