We already have LOG_CONTEXT_PUSH_EXEC() which with two additions
does exactly the same as the custom logging macros, so let's get rid
of the custom logging macros and use LOG_CONTEXT_PUSH_EXEC() instead.
Currently there are various circular dependencies between headers
in core/. Let's get rid of these by making judicious use of forward
declarations and moving includes into implementation files instead of
having them in header files.
Getting rid of circular header includes simplifies the code and makes
various clang based tooling such as iwyu work much better on our code.
The most important change is getting rid of the manager.h include in
unit.h which is possible thanks to the previous commits. We also move
the OOMPolicy and StatusType enums to unit.h to remove the need for
other unit headers to include manager.h to get access to these enums.
On musl, O_ACCMODE is defined as (03|O_SEARCH), unlike glibc which
defines it as (O_RDONLY|O_WRONLY|O_RDWR). Additionally, O_SEARCH is
simply defined as O_PATH.
This causes problems for systemd on musl, as it changes the
behaviour of open_mkdir_at_full() to return -EINVAL if O_PATH is
included in flags due to the fact that O_ACCMODE includes O_SEARCH
(i.e. O_PATH). Consequently, this makes the test-fs-util test fail.
Upstream musl seems content with this behaviour and doesn't seem
interested in matching glibc's behaviour due to that defining it this
way allows for O_SEARCH to match POSIX better by allowing it to open
directories where read permission is missing. Apparently musl does some
emulation in other places to make this work more consistently as well.
Initially I took the approach of working around this by redefining
O_SEARCH as O_RDONLY if O_SEARCH == O_PATH. This fixes the test and is
the approach taken by both XZ[1] and Gzip[2][3], but was not taken as
redefining system headers potentially could be problematic.
Instead, introduce O_ACCMODE_STRICT which just is a copy of glibc's
O_ACCMODE and use it everywhere. This way we don't have to deal with
unusual definitions of O_ACCMODE from C standard libraries other than
glibc.
[1]: https://git.tukaani.org/?p=xz.git;a=blob;f=src/xz/file_io.c;h=8c83269b13fa31284f7ea5f3627a1dfbce7d6e14;hb=HEAD#l72
[2]: https://git.savannah.gnu.org/cgit/gnulib.git/tree/lib/fcntl.in.h
(lines 380 and 396, commit d7f551b30f3f2a0fa57c1b10c12f4eea41a9b89e)
[3]: https://lists.gnu.org/archive/html/bug-gzip/2025-01/msg00000.html
We might have resolved the tty to something else if it was set to
/dev/console, so let's always go via stdin in setup_pam(). This also
means we won't set the pam tty if only stdout or stderr are connected
to a tty, which seems like a sensible thing to do.
If /dev/console is connected to stdin there's a possibility that
the unit might try to start a logind session from within the unit.
Let's make sure that any such sessions are started on the tty that
/dev/console points to and not on /dev/console itself.
This introduce `LOG_ITEM()` macro that checks format strings in
log_struct() and friends.
Hopefully, this silences false-positive warnings by Coverity.
Currently DelegateNamespaces= only works for services spawned by the
system manager. User managers will always unshare the user namespace
first even if they're running with CAP_SYS_ADMIN.
Let's add support for DelegateNamespaces= for user managers if they're
running with CAP_SYS_ADMIN. By default, we'll still delegate all namespaces
for user managers, but this can now be overridden by explicitly passing
DelegateNamespaces=.
If a user manager is running without CAP_SYS_ADMIN, the user manager is
still always unshared first just like before.
If the pid namespace is delegated, it doesn't matter if we have CAP_SYS_ADMIN,
we'll still fail to mount /proc if part of it is masked on the host so also
check if we can mount /proc if the pid namespace is delegated.
This introduce LOG_ITEM() macro that checks arbitrary formats in
log_struct().
Then, drop _printf_ attribute from log_struct_internal(), as it does not
help so much, and compiler checked only the first format string.
Hopefully, this silences false-positive warnings by Coverity.
When we configure a serial or VM terminal and have no $TERM
configuration, then we default to vt220 as a fallback. This is a pretty
safe bet, since the termcap/terminfo definitions for vt220 are
relatively widely available (much like vt100), and (in contrast to
vt100) it supports pageup/pagedown keys. vt220 is a terminal without
color support however, but we do want color support, because in 2025
there's really no terminal emulator without color in this world.
The $COLORTERM env var is used my many emulators and tools to
communicate that ANSI color support is available, despite what $TERM
says. Hence, let's tweak systemd's logic to also set $COLORTERM in case
we set the vt220 $TERM fallback.
This means we define an ahistoric frankenterminal: a vt220 (that
historically definitely didn't have color) that is explicitly configured
to have color.
One effect of this is that coreutils' dircolors command will start to
output color sequences in systemd's serial or VM terminals. (Since it
actually honours $COLORTERM).
Also note that systemd itself checks $COLORTERM since a long time, hence
it makes sense for us to also set it.
Note that this unfortunately doesn't have the desired effect of
propagating $COLORTERM into any getty shell sessions yet. That's because
util-linux' login package currently fiters $COLORTERM (but lets $TERM
though). I filed a bug about that here:
https://github.com/util-linux/util-linux/issues/3463
This delegates one or more namespaces to the service. Concretely,
this setting influences in which order we unshare namespaces. Delegated
namespaces are unshared *after* the user namespace is unshared. Other
namespaces are unshared *before* the user namespace is unshared.
Fixes#35369
(Note: we also change TEST-13-NSPAWN.machined.sh minimally here, because
it checks for byte precise output of a pty allocated for a service
invocation - which it's not going to get if it claims that the pty is an
all-powerful one. After all this PR ensures that we'll generate the new
OSC sequence on non-dumb terminals associated with services. Hence, set
TERM=dumb explicitly to ensure no ANSI sequences are generated, ever.
Which is a nice test btw that TERM=dumb really does its thing here.)
So far we conditioned the logic that issues ansi sequences for resetting
the TTY based on whether something is a pty is not (under the assumption
we need no reset on ptys, since they are shortlived).
This is simply wrong though. The pty that a container getty is invoked
on is generally long-lived: as long as the container is up, and it will
be reused between getty instances/sessions all the time. In such a case
we really should reset properly.
Let's instead make the logic dependent on whether TERM is set to
anything other than "dumb". The previous commit made sure we always set
TERM in a sensible way in systemd-run, hence this
*explicit* logic sounds like a much better choice now, as it mea
let's convert the 2nd argumeng form a boolean to a proper flags
parameter. Doesn't change behaviour in anyway, but is more readable, and
prepares ground for adding more flags soon.
In Arch Linux we currently have a half-baked apparmor support,
in particular we cannot link systemd to libapparmor for service
context integration, since that will pull apparmor into base system.
Hence, let's turn this into a dlopen dep.
Ref: https://gitlab.archlinux.org/archlinux/packaging/packages/systemd/-/issues/22
This ensures the child process is immediately re-parented to the
manager process which avoids a "Supervising process xxx which is
not our child. We'll most likely not notice when it exits." warning
which can currently happen if the parent systemd-executor parent
process sends the pid namespace child process pidref to the manager
process and the manager process dispatches the child process pidref
before the systemd-executor parent process exits, since at that point
the pid namespace child process's parent will still be the
systemd-executor parent process and not the manager process.
This follows the same recent change in util-linux:
https://github.com/util-linux/util-linux/pull/3354
i.e. we generally want that PAM modules can override $HOME and it is
honoured for the CWD after login.
(This renames the 'home' variable we maintained sofar to 'pwent_home',
to clarify that it's the home directory listed in the struct passwd
entry, and thus not necessarily the one actually used)
Let's drop support systems lacking memfds, i.e. pre kernel 3.17 systems.
This allows us to drastically simplify the "data fd" concept, so far
that we can remove it entirely.
This replaces acquire_data_fd() with a specialized call to
memfd_new_and_seal(), not that memfds can be the only implementation of
the concept.
Let's bump the kernel baseline a bit to 4.3 and thus require ambient
caps.
This allows us to remove support for a variety of special casing, most
importantly the ExecStart=!! hack.