[systemd-devel] systemd's connections to /run/systemd/private ?

Lennart Poettering lennart at poettering.net
Wed Aug 14 14:57:30 UTC 2019


On Mi, 14.08.19 10:26, Brian Reichert (reichert at numachi.com) wrote:

> On Wed, Aug 14, 2019 at 11:34:21AM +0200, Lennart Poettering wrote:
> > Hence: your code that closes fd1 like this is simply buggy. Don't do
> > that, you are shooting yourself in the foot.
>
> Buggy or no, this is fifteen-year-old code, and prior cron/service
> mgmt framework implementations had no issue.
>
> And, if I were to ever use daemonize(1), or any other other canonical
> mechanism for daemonizing code, STDOUT would normally be closed
> under those circumstances, as well.

In daemons, stdin/stdout/stderr are generally closed and then opened
as /dev/null again, precisely to avoid problems like that, so that
fd0,1,2 are taken and any future fd allocations are > 2. This is what
BSD/glibc daemon(3) does for example, and most daemons do it like
that.

printf() and friends assume that fd1 is stdout.
fgets() and friends assume that fd0 is stdin.
error() and friends assume that fd2 is stderr.

Most command line programs (such as ls, echo or systemctl assume that
fd0, 1, 2 are defined that way, and they will do their output and
input according to that. if you close these fds before invoking these
programs they will do borked stuff too...

Example:

   telnet www.microsoft.de 80 2>&1-

See, this will connect to port 80, and do so with a socket which is
allocated as fd1, because we called this tool with fd1 closed. Thus it
interferes with stdout, and that one line string that says "Trying
…\nConnected to …\r\nEscape character is '^]'" will be written to the
peer instead of the local tty!

That works with any tool. If you invoke a tool with
stdout/stderr/stdin not connected weird shit happens as soon as the
app allocates the first fd. systemctl is just one of many.

Note that the robustness we added to sd-bus which explicitly moves the
fd >= 3 is not supposed to make things work in cases where systemctl
is called with closed stdin, stdout or stderr. Instead, we made this
change since the sd-bus code is used in NSS clients, i.e. as backend
for gethostbyname(), and thus we really don't know in which kind of
contexts it is used. i.e. it might very well be called inside a
process that is currently rearranging stdin/stdout/stderr and thus
might have closed them temporarily.

Lennart

--
Lennart Poettering, Berlin


More information about the systemd-devel mailing list