Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Potentially unsafe interaction between StandardOutput=socket and ExecStartPre= #32930

Open
tomfitzhenry opened this issue May 20, 2024 · 0 comments
Labels
bug 🐛 Programming errors, that need preferential fixing pid1

Comments

@tomfitzhenry
Copy link
Contributor

tomfitzhenry commented May 20, 2024

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

$ 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
@tomfitzhenry tomfitzhenry added the bug 🐛 Programming errors, that need preferential fixing label May 20, 2024
@github-actions github-actions bot added the pid1 label May 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug 🐛 Programming errors, that need preferential fixing pid1
Development

No branches or pull requests

1 participant