In some cases it might make sense to provide
features/transfers/components in a more dynamic fashion. Let's add a
concept of "sysupdate provider" backends, that can provide such
definitions at runtime.
Fixes: #33351Fixes: #30695
This utilizes the `mkdir_foreign_at` helper function to create
foreign-owned directories. I extended it to `mkdir_foreign_at_full` to
allow for creating btrfs subvolumes too (thanks for merging #43869 to
enable this).
When a read-only directory is requested, the system instance can create
a read-only mount and return a file descriptor to that.
The unprivileged user instance can't do that, so it just returns the
directory file descriptor. An alternative would be to not allow for
read-only requests, but its not like we're consulting polkit for user
session requests.
Use mkdir_foreign_at_full() to create directory volumes from the user
instance. Unlike the system instance, read-only directories can't be
enforced by the storage instance, but are still supported.
When duplicates were present, the existing code picked the
lexicographically earliest entry. This is strange, no other code
that combines list in systemd behaves in this way. This really looks
like an accident of implementation.
In graceful mode, rework the parsing to take the key=value pair that is
specified last. Also, rework the code to use a hashmap. This allows the
graceful and non-graceful paths to be unified into a single pass.
In graceful mode a conflicting tag is replaced by the entry specified
later, in strict mode refused. Every valid tag counts towards
MACHINE_TAGS_MAX.
(The O(n²) complexity in sorting of the tags wasn't great. The tag list is
bounded to 1024 items, so this wasn't _too_ bad, but the approach with the
hashmap is not much more complicated and has better computational
complexity, now the dominant part is O(n×log n) sort that happens later.)
For systemd-firstboot this means that a conflicting tag repeated in
--machine-tags= or in the firstboot.machine-tags credential is now an
error. The duplicated description of tag syntax in systemd-firstboot man
page is replaced by a reference. It was already inaccurate previously,
after not having been adjust for key=value.
If the user doesn't set the node parameter, determine the node backing
/var/. This is usefull for installers or any UI that want to operated on
the
current system.
Tamper with the validatefs xattrs of the various file systems in the
test image, and check that systemd-dissect refuses to mount the image
then, unless validation is turned off via $SYSTEMD_DISSECT_VALIDATEFS=0.
Also check that a bare file system image extracted from the image is
refused as long as it carries GPT or non-root mount point constraints.
On openSUSE, `/etc/nsswitch.conf` may be absent, with glibc falling back
to `/usr/etc/nsswitch.conf`. The bind mount added in #44086 creates an
empty destination file on the host, blocking that fallback and causing
subsequent TEST-74-AUT-UTILS tests to fail with:
```
++ id -gn nobody
id: ‘nobody’: no such user
+++ testcase_exec_properties FAILED +++
```
Bind over `/usr/etc/nsswitch.conf` when `/etc/nsswitch.conf` is absent,
avoiding changes to the host configuration.
The report metrics currently report various useful unit state. It
does not report the SubState currently though. Having it is useful
to determine if e.g. a oneshot unit that has RemainAfterExit=yes
is still running or has exited. So this commit adds it as a
field `sub_state` to the io.systemd.Manager.UnitActiveState metric.
Expose ConfigurationDirectorySymlink with the same a(sst) signature as
the other directory types and route transient ConfigurationDirectory=
assignments through the tuple parser. Keep the name and signature for
uniform client handling; its destination is always empty because
configuration directories do not support symlinks.
Preserve the plain as property for ordinary names and empty assignments.
Emit empty arrays for resets of all five directory types, including the
four types whose client previously discarded empty assignments.
Show tuple flags in systemctl, retaining unknown 64-bit values numerically
for compatibility with newer managers. Document literal-colon escaping,
which now needs an extra level for transient ConfigurationDirectory=,
and the changed output/reset behavior in NEWS.
Read client messages back to check property names, signatures, fields and
empty arrays. Cover flags, raw D-Bus validation and reload/restart path
round-trips in TEST-23, resetting failed transient units during cleanup.
Fixes#43611.
On openSUSE, /etc/nsswitch.conf may be absent and glibc falls back to
/usr/etc/nsswitch.conf. Binding over the absent path creates an empty
file on the host, disabling that fallback and breaking subsequent nobody
lookups.
Bind over the fallback configuration when /etc/nsswitch.conf is absent.
Check the generic disk metrics against sysfs and the udev database in
TEST-74, and the NVMe health metrics against the QEMU emulated NVMe
controllers in TEST-64, including the case of shared namespaces.
The test runs with debug logging, so PID 1 logs a lot. If journald's
native socket is congested, PID 1's log write fails with EAGAIN and it
falls back to /dev/kmsg. Messages logged that way lack the structured
UNIT= field (and _PID=), and hence are not matched by "journalctl -u".
This happened in CI: the "lacks handler for reload signal" warning for
notify-reload-toggle-handler.service ended up in the journal with
_TRANSPORT=kernel, and the -u lookup failed.
Match on SYSLOG_IDENTIFIER=systemd plus the message text instead, which
includes the unit name as prefix on both transports.
On the Arch Linux the logind tests sometimes flake on logind-test-user
session still being active. This is possibly caused by getty getting
re-activated on tty2 during the long timeouts waiting on the user
session to fully get removed. To prevent this remove the
getty@tty2.service.d override as soon as possible and that should fix
the test failure shown below:
[ 69.641642] TEST-35-LOGIN.sh[1014]: + echo 'Session of the '\''logind-test-user'\'' is already present.'
[ 69.642207] TEST-35-LOGIN.sh[1014]: Session of the 'logind-test-user' is already present.
[ 69.642947] TEST-35-LOGIN.sh[1014]: + exit 1
nss-systemd always passes USERDB_EXCLUDE_NSS to userdb. That flag skips
the io.systemd.NameServiceSwitch and io.systemd.Multiplexer services. A
sandbox can bind mount the host's userdb sockets into
/run/systemd/userdb/,
but nss-systemd in that sandbox still cannot resolve the host's regular
users and groups.
Add $SYSTEMD_NSS_SERVER_SIDE_NSS. If it is set, nss-systemd queries the
server-side NSS services too. Client-side NSS stays off, because
nss-systemd itself runs as a glibc NSS module.
io.systemd.Unit.StartTransient currently supports only ExecStart. Add
support
for ExecCondition, ExecStartPre, ExecStartPost, ExecReload,
ExecReloadPost,
ExecStop, and ExecStopPost.
Extract shared command construction into exec_command_new() and use it
in
both the D-Bus and Varlink paths.
Add integration coverage for command execution during startup, reload,
and
shutdown, plus invalid paths and conflicting flags for all eight fields.
systemd-report-sign-tpm2.socket carries ConditionSecurity=measured-uki,
which does not necessarily hold in the test VM. If it doesn't the socket
is silently skipped, systemd-report only finds the plain software
signer, and the report-sign subtest fails because it gets no TPM2
signature record back.
The same applies to systemd-pcrlock.socket, whose Varlink interface the
TPM2 backend reads the event log from. So far this only worked because
TEST-70-TPM2.pcrlock.sh ran first and left the socket up.
Patch out the condition of both via drop-ins for the duration of the
test, like TEST-70-TPM2.pcrextend.sh and
TEST-70-TPM2.cryptsetup-measure.sh already do for
systemd-pcrextend.socket.
Follow-up for 768b6f21ec.
Follow-up to #42921, implementing the conclave rule that all output
fields must be consumable on input.
`Unit.List()` emits the `CGroupTasksMax` pair in full, but
`StartTransient()` refused a
supplied `scale` and pointed at `TasksMaxScale` instead, so its own
output was not valid
input. This takes the pair as emitted.
The denominator is not fixed, which is why the pair has to be accepted
as given rather
than normalized to one scale on input:
| configured via | internal pair |
| --- | --- |
| `TasksMaxScale` (Varlink) | `{permyriad, 10000}` |
| `TasksMaxScale` (D-Bus) | `{v, UINT32_MAX}` |
| unit file `TasksMax=50%` | `{5000, 10000}` |
Accepting only `10000` would still refuse the output of any
D-Bus-configured unit. The
pair is stored as given and normalized only for the transient fragment,
which carries
permyriad percent — the same thing the D-Bus setter does.
Two deliberate details:
- The pair form accepts 0% and 100%, which `TasksMaxScale` rejects.
`config_parse_tasks_max()` parses both through `parse_permyriad()`, so a
unit file can
hold them, they appear on the read side, and they therefore have to be
settable.
`TasksMaxScale` keeps its D-Bus-mirroring bounds, so the asymmetry is
between the
round-trip form and the convenience form.
- A scaled value above 100% is now reported against `CGroup.TasksMax`
instead of the whole
`context`, because it is caught at apply time rather than while
dispatching the object.
`TasksMaxScale` is unchanged and stays input only, which the rule
permits: multiple input
forms are fine as long as the output is normalized, and only `TasksMax`
is emitted.
Note that a daemon-reload still goes through the fragment, so a relative
limit is coarsened
to permyriad precision there. That is pre-existing and applies to the
D-Bus path equally;
the in-memory pair, and so `List()`, keeps what was set.
TEST-74 covers the pair as input, a reply fed straight back, the D-Bus
denominator, the 0%
and 100% cases, and the above-100% rejection.
No fuzzer passes malformed journal files to the code that reads them.
fuzz-journal-remote only reads back the files that it wrote itself.
Add fuzz-journal-file, which writes the input to a file and reads it
through sd-journal: forwards and backwards, by timestamp, cursor, match,
and unique value, and through field enumeration. It also runs
journal_file_verify() on the file. The corpus has a compact and a
regular file with twelve entries each, one of them with a compressed
field.
(TCG is considering to assign us an NV index range, this is a
placeholder document that they can reference in their registry
eventually. Should not be merged like this until TCG folks are happy)
Previously, `varlinkctl call` would print nothing for an empty reply,
and `varlinkctl --exec call` would abort with an assertion failure. This
PR makes varlinkctl consistently output `{}` for cases where the reply
parameters are empty/null/absent.
nss-systemd always passes USERDB_EXCLUDE_NSS to userdb. That flag skips
the io.systemd.NameServiceSwitch and io.systemd.Multiplexer services. A
sandbox can bind mount the host's userdb sockets into /run/systemd/userdb/,
but nss-systemd in that sandbox still cannot resolve the host's regular
users and groups.
Add $SYSTEMD_NSS_SERVER_SIDE_NSS. If it is set, nss-systemd queries the
server-side NSS services too. Client-side NSS stays off, because
nss-systemd itself runs as a glibc NSS module.
The read side emits the CGroupTasksMax pair in full, but StartTransient()
refused a supplied "scale", so the output of Unit.List() was not valid
input again. Take the pair as it is emitted instead.
The denominator depends on how the unit was configured: 10000 via
TasksMaxScale and the unit-file percent syntax, UINT32_MAX via the D-Bus
TasksMaxScale setter. Accepting only one of them would still refuse the
other, so the value/scale pair is taken as given and normalized just for
the fragment, which carries permyriad percent.
UINT32_RATIO_TO_PERMYRIAD() bounds the denominator at UINT32_MAX, which no
producer exceeds. That bound matters: cgroup_tasks_max_resolve() resolves
the pair through system_tasks_max_scale(), whose overflow guard returns
UINT64_MAX once the numerator passes UINT64_MAX/system_tasks_max(). A
larger pair would apply no limit at all while the fragment recorded a
percentage.
Unlike TasksMaxScale, the pair form accepts 0% and 100%:
config_parse_tasks_max() parses both through parse_permyriad(), so they
reach the read side and have to be settable again. TasksMaxScale keeps
its D-Bus-mirroring bounds.
A scaled value above 100% is now reported against CGroup.TasksMax rather
than the whole context, because it is caught when the property is
applied rather than while the object is dispatched.
On aarch64 there is no SMM to protect Secure Boot variables from the
guest, so Fedora ships aarch64 Secure Boot capable firmware only with
the `host-uefi-vars` feature: it keeps its variables in QEMU's uefi-vars
device instead of pflash. vmspawn previously skipped these firmware
descriptors, so `--secure-boot=yes` failed on aarch64:
> Skipping /usr/share/qemu/firmware/91-edk2-aarch64-qemuvars-sb.json,
> firmware does not have an NVRAM template.
> Failed to find OVMF config: No such file or directory
Select such firmware if its descriptor declares a variable store
template, and give it the `uefi-vars` device. This is backed by a JSON
state file with the same semantics as the pflash NVRAM state. Its
`--efi-nvram-state=auto` path gets a different suffix, so that switching
between the two firmware types never feeds a state file to the wrong
one.
Descriptors are still picked in sort order, so when pflash firmware
satisfies the requested features and is sorted first (as with Fedora's
x86 descriptors), it does not change behaviour.
Signed-off-by: Martin Pitt <martin@amutable.com>
vmspawn enabled SMM for all Secure Boot firmware, and restricted the
pflash variable store to SMM accesses for all firmware on architectures
with SMM. Firmware built without SMM support, such as Fedora's
non-Secure Boot OVMF builds, then can't write its variables: QEMU drops
all of its writes to the variable store, so e.g. boot options never
persist.
The `requires-smm` feature of the firmware descriptor declares whether
firmware needs SMM [1]. Enable SMM and restrict the variable store to
SMM accesses only for such firmware. libvirt does the same.
[1] [1] https://gitlab.com/qemu-project/qemu/-/blob/master/docs/interop/firmware.json
Signed-off-by: Martin Pitt <martin@amutable.com>
With a console PTY, QEMU's stdio is the PTY since bde83a9e1e. Nothing
reads it before the PTY forwarder starts after the QMP device setup.
When QEMU refuses to start, e.g. due to an unknown device, its error
message got lost, and vmspawn only reported "QMP connection dropped
during feature probing".
If vmspawn fails before the forwarder starts, copy QEMU's buffered
console output to stderr.
Signed-off-by: Martin Pitt <martin@amutable.com>
Previously, sd-varlink was inconsistent about what it did with
empty/missing/null parameters in a Varlink call or reply: when
dispatching to a callback, it would always construct an empty object and
hand over the empty object to the handler (good!). But when returning
the value directly (i.e. with sd_varlink_call), it would return NULL
when parameters were omitted and a JSON null when the paramerters were
null.
This inconsistency is a violation of UAPI.20, which states that
receivers of Varlink messages MUST treat omitted/null/empty parameters
on Varlink calls and replies equivalently, where senders only SHOULD
prefer to omit the parameters.
This commit makes sd-varlink normalize the parameters to an empty object
whenever it is null or omitted, which brings sd-varlink into compliance
with this rule in UAPI.20
The firmware subtest of TEST-87-AUX-UTILS-VM.vmspawn-drives.sh boots
the Secure Boot OVMF build with SMM in a nested VM. On a slow CI runner
the firmware took ~33s to set the RTC and ~45s to bring up the console,
so the 60s timeout for the BdsDxe "UEFI Misc Device" line expired
before BDS got to try the drive, failing the test even though nothing
was wrong.
Bump the timeout to 300s. The test still bails out as soon as the line
shows up, so this only costs time when things are actually broken.
The dependency testcase references a unit that is never created after the
split. Start a local oneshot fixture and keep it active so the checks
exercise dependencies on an existing unit, with cleanup owned by the
same testcase.
The existing checks pass the comma-separated values via systemd-run -p,
which splits them on the client side, so the parsers in load-fragment.c
were not exercised. Load a unit file with comma-separated SystemCallFilter=,
SystemCallLog= and RestrictFileSystems= and check what the manager reports.
The names are reported sorted, so the expected output is deterministic.
systemd-run normalizes the names on the client side before sending them to
the manager, so talk to the manager directly to exercise the code in
dbus-execute.c: 'inet Unix' must end up as 'AF_INET AF_UNIX' in the
transient unit file and in the exposed property, and an unknown name must
be rejected with InvalidArgs.
busctl only reports the name of the error via BUSERROR=, so run it as a
service with NotifyAccess=main and check StatusBusError, like TEST-80 does.
The options added to the --volatile= checks only verify that the various
spellings are accepted. Add a dedicated testcase which checks that the
restriction actually applies: ip(8) needs an AF_NETLINK socket, so it must
fail when netlink is not permitted and succeed when it is, regardless of how
the list is spelled.
The previous commits made SystemCallFilter= and RestrictAddressFamilies=
accept commas as separators, and the shared serialization helper in
bus-unit-util.c now splits on commas for all the filter-list settings it
handles. That left unit files and 'systemctl set-property'/'systemd-run
-p' disagreeing for the remaining three settings. Accept commas in the
unit file parsers too, and update the documentation.
Note that a comma is a valid character in a network interface name, so an
interface with a comma in its name needs to be quoted or escaped. Add a
hint in the man page. Such names should be exceedingly rare so this
shouldn't matter in practice.
The manager writes transient settings back into a drop-in which is parsed
again on daemon-reload. Quote the interface names there, so that a name
containing a comma (or a quote or backslash, which are valid in interface
names too) survives the round trip.