In Ubuntu, rsyslog is (a) part of the minimal image and (b) does not run
as root. To facilitate this, the rsyslog package configures /var/log
to be writeable by the syslog group.
There are currently conflicts in the Ubuntu packaging due to the way
tmpfiles are handled in package scripts: when systemd-tmpfiles is
invoked with both configurations (or for all configurations), things
work fine. But if invoked with only var.conf, which is the default case
for package upgrades, rsyslog is broken.
One suggestion to approach this was to make rsyslog's tmpfile
configuration use ACLs instead of trying to change the owning group and
directory mode. This can work, but since the ACL mask is stored in the
group permission bits, the effective mask for rsyslog becomes r-x again
when var.conf is invoked, because it sees that 0775 != 0755, and chmods
the directory.
Hence, for /var/log write permisssions to be extendable with ACLs,
the mode must be at least 0775. Rather than change the default,
add a build option to configure the /var/log mode.
The option is generalized from a simple boolean switch that enables
a fixed list to a list-of-patterns.
The old value works, but is deprecated: -Dstandalone-binaries=true is translated
to -Dstandalone-binaries=repart,report,tmpfiles,sysusers,shutdown.
We could already build all normal executables as .standalone, but the
installation only supported a small fixes subset. This wasn't flexible
enough:
- packagers might want to provide additional standalone binaries then the
small subset that was already enabled
- but at the same time, whenever new binaries were added to this subset,
downstream packaging had to be adjusted in sync, at least in the case of
Fedora, because otherwise we'd get a complaint about unexpected .standalone
binaries in the temporary install root.
With the new option, downstreams can just specify the binaries that they
want to be installed in the .standalone variant.
As usual with this type of change, the build dir must be reprovisioned.
1f76654f94 added support to build .standalone
variants of most binaries. test-dlopen-note.py is hooked in the test suite for
everything that can do .standalone, but this means that the .standalone
variants become a prerequisite for tests. This means that meson will build the
.standalone variants for all binaries before running tests, which takes quite a
bit of time in some situations. (Arguably, the dlopen test suite was excluded
by default, so maybe meson could be smart and figure out that those tests are
not enabled by default. But it doesn't seem to make this distinction.)
Add a 'fallback-default-target' meson option that configures which unit
to activate when default.target is not installed. This makes things more
resilient in general and is also useful for minimal/statically-linked
installations that may not ship a default.target symlink.
'graphical.target' is used as the default value of the setting, because
that's what we symlink as default.target in units/meson.build.
In the initrd, we had a fallback to start default.target if initrd.target
cannot be started. This fallback is changed to only do that if it is
not found, not on other errors. This seems more correct (and makes
the two fallbacks symmetrical.)
When we try to build with -static, the linker refuses dlopen and
various functions related to nss. This commit adds the basic support
to compile with -static and allow the link to pass.
This effectively reverts the meson config changes introduced in
0c6186695a. I wasn't happy with that form
back when it was commited, and in hindsight, I like it even less. Let's
just add a new option that hopefully is easier to understand and will
work better when new functionality is added in the future.
Now there are two options:
link-executor-shared (boolean, defaults to true)
— "link (separate) systemd-executor to libsystemd-shared.so and libsystemd-core.so"
systemd-multicall-binary (also boolean, defaults to false)
— "link systemd+systemd-executor as a single binary"
Build directories will need to be recreated again, sorry!
Allow systemd-executor to be compiled into a single binary.
The existing -Dlink-executor-shared=true|false is extended to also
allow -Dlink-executor-shared=single (*). The new mode is opt-in,
to allow experimentation and introduce this smoothly.
This saves a little space, but not as much as I expected:
$ ls -l build/{systemd,systemd-executor} build-new/systemd
-rwxr-xr-x 1 zbyszek zbyszek 631520 May 25 22:44 build/systemd
-rwxr-xr-x 1 zbyszek zbyszek 670464 May 25 22:44 build/systemd-executor
-rwxr-xr-x 1 zbyszek zbyszek 1214488 May 25 22:45 build-new/systemd
(This is with -Dbuildtype=debugoptimized -Db_lto=true).
The combined binary is slightly smaller than the sum of the separate
ones, but not much. In both cases, the binaries are linked to
libsystemd-core which is 10MB, so the size of the binaries themselves
doesn't make much of a difference. The executor needs exec-invoke.c
which is huge and not shared with anything else.
Longer term, I want to allow systemd to be linked statically. In
that case, having systemd-executor separate would be very painful.
So the option to use a multicall binary will be necessary.
Previously, we stored the resolved path to systemd-executor and
used it argv[0]. I don't think this was useful. After all, normally
we would use the non-resolved original path as argv[0]. So that
part is dropped, and the resolved path is only logged, but
"systemd-executor" is always used as argv[0]. This makes the
multicall binary work reliably, no matter what the actual file
name is.
(*) This means that compat as the commandline level is maintained:
'meson setup build -Dlink-executor-shared=true …' works as before.
Unfortunately, when using an existing build directory, meson chokes
on the type change and refuses to reconfigure the directory or change
the option or do anything useful. I think meson is DTWT here, but
this is hard to fix. So the build directory probably needs to be
recreated.
This commit adds support to /etc/hostname for substitution
of $ wordlists from {/etc,/run,/usr/lib}/systemd/hostname-wordlist.
The first $ will lookup hostname-wordlist/1, the next
hostname-wordlist/2 and so on.
With that we can do a petname [1] style hostname in systemd, e.g.
below a possible expansion for a hostname template:
$-$-$-???? -> wildly-happy-octopus-92a9
The substitution of words is stable (based on machine-id) but
not persisted, it is picked on every boot via a stable file
offset so the operation is cheap. But this means that if the
wordlist changes the hostname would change. The next commit
will add the pattern to the firstboot.hostname credential which
is persistet with the resolved names to avoid this issue.
This also includes a wordlist from the "petname" project
that can be optionally installed.
Thanks to Dustin Kirkland for this wonderful project.
[1] https://github.com/dustinkirkland/petname
Enabling locking by default would constitute a major footgun and
compatibility break on upgrades. This functionality is useful, but it
requires the rest of the system to be "ported" to use systemd-imds
first. The user or distro should opt in to "locked" mode only after
doing the integration work.
The infrastructure added in the previous commits added support for IMDS
client functionality, but didn't really to enable the logic by default
on suitable hosts.
This commit adds a generator that automatically hooks the IMDS
functionality into the boot process if it detects that the system is
running on a compliant cloud system. it enables both the imds daemon and
the client.
This service's job is to talk to a VM associated IMDS service provided
by the local Cloud. It tries to abstract the protocol differences
various IMDS implementations implement, but does *not* really try to
abstract more than a few basic fields of the actual IMDS metadata.
IMDS access is wrapped in a Varlink API that local clients can talk to.
If possible this makes use of the IMDS endpoint information that has
been added to hwdb in the preceeding commit. However, endpoint info can
also be provided via kernel command line and credentials. For debugging
purposes we also accept them via environment variables and command line
arguments.
This adds a concept of early-boot networking, just enough to be able to
talk to the IMDS service. It is minimally configurable via a kernel
cmdline option (and a build-time option): the user may choose between
"locked" and "unlocked" mode. In the former mode direct access to IMDS via
HTTPS is blocked via a prohibit route (and thus all IMDS communication
has to be done via systemd-imdsd@.service). In the latter case no such
lockdown takes place, and IMDS may be acquired both via this new service
and directly. The latter is typically a good idea for compatibility with
current systems, the former is preferable for secure installations.
Access to IMDS fields is controlled via PK.
Follow-up for a109189fab
This follows the existing practice for
systemd-journal-{upload,gatewayd}.service,
as I think allocating a full-blown user
specifically for this purpose is an overkill.
And with DynamicUser=yes we can also take
advantage of implied sandboxing.
We already have some varlink support for the journal to perform
some actions like `Rotate`. It would be nice to be able to query
the journal via varlink too so this commit adds a new varlinkctl
based journal service that exposes a single GetEntries() call
to retrieve journal entries. Basic filtering is supported and
we can expand the API as needed.
This is a separate `io.systemd.JournalControl` [1] service from the
existing `io.systemd.Journald` to decouple read and write (thanks
to Lennart for suggesting this).
This also extracts some shared helper so that we do not duplicate
code when generating the json or when adding the filters.
[1] The name mirrors the bootctl->io.systemd.BootControl naming.
This partially reverts commit e58ba80a40. Those
aliases were removed as part of the removal of sysvinit compat, but the removal
was immediately reported as a regression by users. In particular, users can
have one of those set as the default target, or use those names in Wants= or
Requires= dependencies. At least in Fedora, the removal was immediately
reverted.
When looking at our "portability and stability promise", I noticed that those
units are explicitly listed in the promise. Let's restore them upstream. They
are conditionalized under a new -Dcompat-sysv-interfaces=bool option, so that
downstreams like Arch that wasnt to strictly avoid legacy interfaces can easily
disable them. They are dropped from the docs, like we do for all deprecated
interfaces.
As announced by a few releases now, finally drop support for
sysvinit scripts.
Keep rc-local generator for now, as it's really a distinct
feature even though from the same era.
The current tree doesn't even compile with libidn(1) after
2c7bdaf9f1, which included
a non-existent call to check_dlopen_blocked() somehow.
Hence, it feels safe to just nuke legacy support from
our repo.
So far the idea was that the default is 'auto', and if appropriate, the
distribution will create /var/log/journal/ to tell journald to use persistent
mode. This doesn't work well with factory resets, because after a factory reset
obviously /var/log is gone. That old default was useful when journald was new
and people were reluctant to enable persistent mode and instead relied on
rsyslog and such for the persistent storage. But nowadays that is rarer, and
anyway various features like user journals only work with persistent storage,
so we want people to enable this by default. Add an option to flip the default
and distributions can opt in. The default default value remains unchanged.
(I also tested using tmpfiles to instead change this, since we already set
access mode for /var/log/journal through tmpfiles. Unfortunately, tmpfiles runs
too late, after journald has already started, so if tmpfiles creates the
directory, it'll only be used after a reboot. This probably could be made to
work by adding a new service to flush the journal, but that becomes complicated
and we lose the main advantage of simplicity.)
Resolves https://bugzilla.redhat.com/show_bug.cgi?id=1387796.
A --empower session is effectively root without being UID 0, so it
doesn't make sense to enforce polkit authentication in those. Let's
add the empower group, add --empower sessions to that group and ship
a polkit rule to skip authentication for all users in the empower
group.
(As a side-effect this will also allow users to add themselves to this
group outside of 'run0 --empower' to mimick NOPASSWD from sudo)
We'd like to measure various additional things into PCRs, but all
available ones to the OS are already used for various purposes. Hence,
let's introduce a new concept of "NV Index based PCRs", i.e. let's use
TPM2 nv indexes of type TPM2_NT_EXTEND that mostly behave like real
PCRs, but which we can allocate relatively freely from the nv index
space. Let's call these "fake" PCRs "NvPCRs".
My original intention was to get a fixed NV index range assigned from
the TCG, either for Linux or for systemd as a project, but this stalled
with no further updates from the TCG for more than a year and a half
now. I was told an NV index range to use though, even if it never was
officially assigned, hence this PR uses this by default. But the range
is configurable at build time, on purpose, so that downstreams have some
flexibility to change this if they want. To abstract the actual nvindex
number away we introduce a naming concept, so that nvindexes are
referenced by name string rather than number.
NvPCRs are defined in little JSON snippets in /usr/lib/nvpcr/*.nvpcr,
that match up index number and name, as well as pick a hash algorithm.
There's one complication: these nvindex (like any nvindex) can be
deleted by anyone with access to the TPM, and then be recreated. This
could be used to reset the NvPCRs to zero during runtime, which defeats
the whole point of them. Our way out: we measure a secret as first thing
after creation into the NvPCRs. (Or actually, we measure a per-NvPCR
secret we derive from a system secret via an HMAC of the NvPCR name) and
the nvindex handle). This "anchoring" secret is stored in /run/ +
/var/lib/ + ESP/XBOOTLDR (the latter encrypted as credential, locked to
the TPM), to make it available at the whole runtime of the OS.
I noticed in our NixOS packaging that we were working around the fact
that core/swap.c looks for swapon and swapoff in /sbin
Lets make it configurable just like all the other util-linux binaries
through meson and make it default to /usr/sbin/{swapon,swapoff}
This way mounts work on a systemd without the /sbin -> /usr/sbin
compatibility symlink. (And as a side-effect has NixOS be able
to have it in /nix/store too like the other util-linux tools).
In multi-seat scenarios, a display manager might need to start multiple
greeter sessions. But systemd allows at most one graphical session per
user. So, display managers now have a range of UIDs to dynamically
allocate users for their greeter sessions.
Currently, when fuzzers are enabled, we run meson from within meson
to build the fuzzer executables with sanitizers. The idea is that
we can build the fuzzers with different kinds of sanitizers
independently from the main build.
The issue with this setup is that we don't actually make use of it.
We only build the fuzzers with one set of sanitizers (address,undefined)
so we're adding a bunch of extra complexity without any benefit as we
can just setup the top level meson build with these sanitizers and get
the same result.
The other issue with this setup is that we don't pass on all the options
passed to the top level meson build to the nested meson build. The only things
we pass on are extra compiler arguments and the value of the auto_features
option, but none of the individual feature options if overridden are passed on,
which can lead to very hard to debug issues as an option enabled in the top
level build is not enabled in the nested build.
Since we're not getting anything useful out of this setup, let's simplify
and get rid of the nested meson build. Instead, sanitizers should be enabled
for the top level meson.build. This currently didn't work as we were overriding
the sanitizers passed to the meson build with the fuzzer sanitizer, so we
fix that as well by making sure we combine the fuzzer sanitizer with the ones
passed in by the user.
We also drop support for looking up libFuzzer as a separate library as
it has been shipped builtin in clang since clang 6.0, so we can assume
that -fsanitize=fuzzer is available.
To make sure we still run the fuzzing tests, we enable the fuzz-tests option
by default now to make sure they still always run (without instrumentation unless
one of llvm-fuzz or oss-fuzz is enabled).
We add a default test setup that excludes the integration-tests suite
so that the integration tests don't run by default. This allows us to
get rid of $SYSTEMD_INTEGRATION_TESTS. Then, we add two extra setups:
'integration' and 'shell'. The 'integration' setup does not exclude the
integration-tests suite, and so can be used to run the integration tests.
The 'shell' setup does the same, but additionally sets $TEST_SHELL=1,
allowing to get rid of $TEST_SHELL in the docs.
- default-hierarchy meson option was deprecated by
31323f21bb (v256).
- nscd meson option was deprecated by
28f1f1a5e6 (v257).
Let's completely remove them now.
I ran into the limit with ParticleOS, with 6 profiles, hence I think the
current default value is a bit low. let's bump it 4x, to 120. This is
still a lot lower than 500 or so which Debian uses downstream.
We can look into raising this further should we collide with this again,
but for now, let's try 120 and see how it goes in practice.
This makes the UID range configurable via build time options, but of
course it really shouldn't be changed. The default range I picked is
outside even of IPAs current (ridiculously large) allocation ranges,
hence hopefully minimizes conflicts.
This commit introduces a build-time option to enable/disable sysupdated
separately from sysupdate. 'auto' translated to enabled by default in
developer builds.