]> git.ipfire.org Git - thirdparty/systemd.git/commit
pid1: when taking possession of passed fds check O_CLOEXEC state first
authorLennart Poettering <lennart@poettering.net>
Tue, 23 May 2023 15:24:46 +0000 (17:24 +0200)
committerLennart Poettering <lennart@poettering.net>
Tue, 23 May 2023 17:23:32 +0000 (19:23 +0200)
commita3dff21ae882adadd946c51284bac9b14568f598
tree6a0ec11fae30e15c7e5e4c9a017faadcb7f11a64
parent13f37e6e972d3d6beca5fc628b746e07a6523ae2
pid1: when taking possession of passed fds check O_CLOEXEC state first

So here's the thing. One library we use (libselinux) is opening fds
behind our back when we initialize it and keeps it open. On the other
hand we want to automatically pick up all fds passed in to us, so that
we can distribute them to our services and close the rest. We pick them
up very early in our code, to ensure that we don't get confused by open
fds at that point. Except that libselinux insists on being initialized
even earlier. So suddenly we might take possession of libselinux' fds,
and then close them later when we decide no service wants them. Then
during shutdown we close down selinux and selinux closes its fds, but
since already closed long ago this ight close our fds instead. Hilarity
ensues.

I wish low-level software wouldn't do such things behind our back, but
well, let's make the best of it.

This changes the fd pick-up logic to only pick up fds that have
O_CLOEXEC unset. O_CLOEXEC must be unset for any fds passed in to us
over execve() after all. And for all our own fds we should set O_CLOEXEC
since we generally don't want to litter fd tables for execve(). Also,
libselinux thankfully appears to set O_CLOEXEC correctly on its fds,
hence the filter works.

Fixes: #27491
src/core/main.c
src/notify/notify.c
src/shared/fdset.c
src/shared/fdset.h
src/test/test-fdset.c