Other systems (kubernetes…) allow tagging machines with key/value pairs.
Let's extend our allowed syntax slightly to allow that too. Thankfully,
we enforced a pretty strict ruleset on machine tags, hence we can
introduce this without breaking compatibility.
This basically allows tags to contain "=". If so, then the left-hand
side of it must be unique among machine tags.
When matching against a machine tag, we apply the same rules as before.
This means, that if people want to check if a tag with value applies
they can do:
ConditionMachineTag=foo=bar
If they just want to check if "foo=" is set to anything, they can use
the usual glob matching:
ConditionMachineTag=foo=*
Up to now we recommended to use TARGET.upholds/ symlinks to start units
when an extension is loaded. However, this has some drawbacks. First,
for services that should not be tried to be started all the time we have
to resort to hiding them through a target that gets uphold and then
uses regular .wants/ for the actual service. Second, we actually leak
services on extension unload even if the unit has disappeared with the
extension. Third, to affect a service through a drop-in or a config
change from a confext/sysext and that service is already running, we
need a way to restart/reload it instead of just starting it.
Similar to EXTENSION_RELOAD_MANAGER=1, add a EXTENSION_RESTART_UNITS=
and a EXTENSION_RELOAD_OR_RESTART_UNITS= setting to the
extension-release metadata file, carrying a whitespace-separated list
of units to restart/reload on merge/refresh/unmerge after the daemon
reload. Also detect when the unit has vanished which is normally the
case when the unit was part of the unmerged extension, and stop it
explicitly to prevent it leaking. When the extension itself ships the
binary it should use EXTENSION_RESTART_UNITS= to make sure the new
binary is picked up. Since starting through this setting does not work
when the extension is mounted from the initrd, extensions should still
ship at least a .wants/ symlink to start at boot but can also continue
to ship a .upholds/ symlink for backwards compatibility without any
drawback and still benefit from the unit stopping triggered by the new
setting. While there are cases where one could want to set
EXTENSION_RESTART_UNITS= without requiring a daemon reload (e.g., an
env var file change instead of a unit drop-in), we now do an implicit
daemon reload when we have to restart units so that we know we work on
the right state and we spare users remembering to set this setting in
addition to prevent running into this issue.
The `pending` and `reboot` verbs, as well as the `--reboot` switch, compare
the newest installed version against the booted OS version (IMAGE_VERSION= from
os-release). When a component is selected via --component=, this compares the
component's version against the unrelated host OS version, which by design live
in separate version spaces. The result is arbitrary reboot decisions: depending
on the relative version strings sysupdate would either always or never reboot.
Refuse the combination with a clear error instead of silently performing a
bogus comparison. Correctly tracking a per-component booted version is left as a
future feature.
Fixes: https://github.com/systemd/systemd/issues/42330
This adds the following:
1. systemd-report gains a new --sign= option, taking a boolean. If true,
this makes systemd-report generate + systemd-report upload generate a
signed report, instead of a regular one. The signatures are collected
from Varlink-based backends.
2. One such backend is added which does a simple Ed21159 based signing
scheme.
3. this adds a new metrics source which just reports text files
symlinked into a special dir as metrics. This is used to report the
Ed21159 public key as metric, by default, if it exists.
4. finally, systemd-report itself is turned into a varlink service. this
is useful for example for extracting a report from a system coming in
via the varlink/http bridge.
I thought a long time about the format of signing of reports. Initially
i intended to do this like homed's user record signing, i.e. require
normalization of the record, then normalize the record, and write it out
in dense form, since the result. Finally insert the resulting hash into
the user record itself. People have pointed me to the inherent messiness
of signing JSON this way though, as it requires any participant that
wishes to sign/authenticate records this way to implement the exact same
normalization/formatting rules, and in particular in the area of
floating point numbers (of which metrics presumably will have many) this
is quite problematic.
This signing hence goes a different way. instead of expecting
signer+verifier to independently come to the same normalized text form
of the json data, let's instead output a JSON-SEQ sequence, where the
first object is the report, and any subsequent objects are one signature
each. the signatures are supposed to cover the precise binary
representation of the first element in the JSON-SEQ stream. (i.e. from
the RS to the NL).
or in other words: a verifier would receive the JSON-SEQ stream, split
it up before each RS. Then it would leave object 1 unparsed for the
moment, and parse objects 2…n. It would then authenticate object 1's
precise binary representation with objects 2…n. Once that checks out, it
would parse object 1, and use it as report.
These signatures can be provided by arbitrary Varlink backends symlinked
into /run/systemd/report/sign.
Also add a proper Varlink IDL for the upload interface, since we are
extended it now.
Acquiring a LUO session from /dev/liveupdate requires privileges,
and also the device is a single-owner driver so only a single
process can open it at any given time.
Add a LUOSession= service settings that allows units running
without privileges to get a session assigned to them.
The kernel imposes a 64 chars limit on session names, which is
too short to avoid clashes, so derive a hash from joining the
unit name with the parameter name, that way two units using
the same setting don't clash.
let's name the dir "/run/systemd/report.upload/" (rather than
"/run/systemd/metrics-upload/"). After all, these are reports that we
upload, not indiviudual metrics. And it would be particular confusing
since the dir to pick up metrics is called /run/systemd/report/, rather
than /run/systemd/metrics/. Hence the thing that deals with reports is
nmamed metrics, and the thing that deals in metrics is named reports...
We really want to use io.systemd.Report for the interface
provided by systemd-report itself, not by its backend. hence, rename the
interface that uploading plugins shall implement to
io.systemd.Report.Uploader.
Note that we ideally should have a varlink interface definition for that
interface. if we had, we'd have noticed that earlier.
Only .dtbauto and .efifw may appear more than once, .hwids is a
singleton per the UKI specification and the stub reads a single .hwids
section (per profile), matching hardware IDs against entries within it.
Co-developed-by: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Paul Meyer <katexochen0@gmail.com>
A bind mount inherits the mount flags of the file system the source
directory resides on. For root=bind: the source typically lives below
/run/ (e.g. a freshly unpacked tar image in /run/machines/), which is
mounted nosuid,nodev, so those flags propagated to /sysroot and broke
suid binaries (e.g. sudo) and device nodes on the booted system.
Default bind root mounts to dev,suid,exec instead, unless the user
overrides this via rootflags=.
Fixes: https://github.com/systemd/systemd/issues/41352
Co-developed-by: Claude Opus 4.8 <noreply@anthropic.com>
keyfile-erase only erases a key file explicitly configured in the third
field of crypttab. Key files automatically discovered in
/etc/cryptsetup-keys.d/ and /run/cryptsetup-keys.d/ are considered shared
resources not owned by an individual volume, and are never erased. Make
this explicit in the documentation and add a code comment clarifying the
intent.
Fixes: https://github.com/systemd/systemd/issues/41127
Co-developed-by: Claude Opus 4.8 <noreply@anthropic.com>
- In `systemd.network.xml`, replaced `"without mode"` with `"without static"`
to clarify that if an IPv6 address is specified without the explicit keyword
`static`, then `static` mode is assumed.
- The original wording was ambiguous because "mode" appears multiple
times in the surrounding context (referring to IPv6 link-local address
modes like `eui64`, `static`, etc.).
Fixes: #39754
We shouldn't say that that they boot into "a … legacy target", because
they boot into the standard targets. Those names are just aliases now.
(And also the user is not required to know what SysV even is, so it
shouldn't be used in the main explanation.)
Add a service template that adds the machine tag given as its instance
name to the host's machine tags. Whenever an instance is pulled in, the
tag is added; the operation is idempotent.
It talks to hostnamed over Varlink (which is socket-activated), so it
works very early at boot, before the system bus is up. It is ordered
after local-fs.target so that /etc/machine-info can be written, requires
hostnamed's socket and the local filesystems to be available, and does
not run in the initrd.
Teach the "tags" verb to accept arguments prefixed with '+' or '-': a
'+'-prefixed argument adds all of its (colon-separated) tags to the
configured list, a '-'-prefixed one removes them, mapping onto the new
AddAndRemoveTags() D-Bus method. The prefix applies to the whole
argument, so e.g.
hostnamectl tags +foo:bar -quux:ooo
adds foo and bar and removes quux and ooo. Plain (replace) and prefixed
(add/remove) arguments may not be mixed in one invocation.
Add a new D-Bus method on org.freedesktop.hostname1 that incrementally
updates the machine tags instead of replacing the whole list: it takes
two string arrays, one of tags to add and one of tags to remove, and
stores (current ∪ add) \ remove.
This avoids the read-modify-write race that clients would otherwise hit
when several of them each manage a subset of the host's tags.
Factor the tag persistence and the write-error-to-D-Bus-error mapping out
of method_set_tags() into helpers, and add a machine_tags_add_remove()
helper for the set arithmetic, all to be shared with further callers.
Unit-level Condition…= / Assert…= directives that fail prevent activation
entirely, so SuccessAction= / FailureAction= never fire. An ExecCondition=
skip in [Service] runs as part of the activation transition itself, so
the unit goes active → inactive and SuccessAction= is honored.
This asymmetry has tripped users up; document it explicitly in both
systemd.service(5) (ExecCondition= section) and systemd.unit(5)
(SuccessAction= / FailureAction= section) with cross-references.
Fixes: https://github.com/systemd/systemd/issues/42035
Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
This is supposed to be useful to mark an interactive user login as a
"break glass" event in the measurement logs, i.e. as in many typically
headless scenerios this indicates debug access or similar.
This allows us to have a separate, more permissive, policy for
cancelling ongoing sysupdate jobs. The new default policy for
cancellation actions is to allow them for the active user, without admin
authentication, because typically the user can just pull the plug on the
computer to cancel a job anyway.
Signed-off-by: Philip Withnall <pwithnall@gnome.org>
Fixes: https://github.com/systemd/systemd/issues/38568
This is supposed to protect our SMBIOS type 11 importing for
credentials. Note that firmwares are supposed to measure SMBIOS anyway
to PCR 1. Alas firmware doesn't really do that in various cases. Hence
let's do so again, for select objects.
This closes a gap where some of the input for OS (i.e. system
credentials places in smbios11) isn't measured properly.
(I really want this to get into v261, because this will fuck up the PCRs
a bit more, and we already have the new separator measurement in v261,
hence there's value in getting this merged at the same time, so that we
don't break the measurements a 2nd time)
For management purposes it's useful to be able to "tag" a machine with
various labels. Let's add a field for that to /etc/machine-info and make
it settable.
Fixes: #38591
This allows us to have a separate, more permissive, policy for
cancelling ongoing sysupdate jobs. The new default policy for
cancellation actions is to allow them for the active user, without admin
authentication, because typically the user can just pull the plug on the
computer to cancel a job anyway.
Signed-off-by: Philip Withnall <pwithnall@gnome.org>
Fixes: https://github.com/systemd/systemd/issues/38568
Currently with FileDescriptorStorePreserve=yes the FD store is kept around
regardless of what happens to a unit, which is useful in many cases. But in
some cases, for example when complex services crash horribly, it's hard to
reason about what was in the intermediate state, and it's better to start
fresh.
Add a new 'on-success' option for the FileDescriptorStorePreserve= setting
that keeps it around only for as long as the unit doesn't go to a persistently
failed state.
This is especially useful in combination with LUO, where we don't want to
keep around LUO sessions created by units that then proceeded to crash and
burn, and might be in a bad state afterwards.
Then, this deprecates
- BindToInterface=
- RelayTarget=
- RelayAgentCircuitId=
- RelayAgentRemoteId=
settings in [DHCPServer] section.
These are gracefully translated as new settings.
This has little to do with host configuration (where it was so far), and
a lot with what being executed, let's move it over.
Note that --help and man page so far differed here quite a bit: the
former had the "Execution" section, the latter didn't. This creates it
in the man page, to bring the two back in sync.
While commit 83c1e8ff5f added support for interactive polkit
authentication in `updatectl`, some users might want to disable that for
some use cases; so add the standard `--no-ask-password` argument.
Signed-off-by: Philip Withnall <pwithnall@gnome.org>
Helps: https://github.com/systemd/systemd/issues/37412
Add --confidential-computing=sev-snp to run the guest as an AMD SEV-SNP
confidential VM. Loads a raw OVMF firmware blob via -bios (SNP doesn't
support the pflash + NVRAM split), attaches a sev-snp-guest object,
and hashes the kernel, initrd and cmdline into the launch measurement
when direct kernel boot is used. Incompatible features (Secure Boot,
CXL, virtio-balloon, SMBIOS credentials) are rejected or disabled; an
attached vTPM must be treated as untrusted by the guest.
The feature is marked experimental in the man page.
Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: Paul Meyer <katexochen0@gmail.com>