So far BLOCKDEV_LIST_IGNORE_VIRTUAL filtered out everything below
/sys/devices/virtual/, which includes loopback devices. Loopback devices
are frequently used as stand-ins for real disks though (in tests, and
when installing to disk images), hence it's useful to be able to control
them independently of the other virtual devices (dm, md, zram, …).
Introduce a separate BLOCKDEV_LIST_IGNORE_LOOP flag for loopback
devices, and make BLOCKDEV_LIST_IGNORE_VIRTUAL only cover the non-loop
virtual devices. The only existing user (systemd-report) is updated to
pass both flags, so that its behaviour stays unchanged.
When systemd-loop@.service is instantiated for a block device (e.g. a
CD-ROM drive, which is the primary usecase now that --relax is used),
%f resolves to the backing block device rather than to the loopback
block device that was attached on top of it. In that case ExecStop=
hence invoked --detach on a block device that is not a loopback device
at all, which made loop_device_set_autoclear() a silent no-op, leaking
the attachment.
Hence, if --detach is passed a block device that is not a loopback
block device itself, search for the loopback block device backed by it,
the same way we already do for regular files. The kernel reports the
backing inode for block device nodes too, so the same inode matching
logic applies.
Our primary usecase for this service is to deal with sector issues
around CDROMs. For that insisting on proper DDI layout and a root
partition is overkill. Let's hence relax the logic for this.
Fixes: #43605
It's nice to use --attach since it validates our images. So far, it
strictly insisted on checking that the image was a DDI however, which
limits its use for certain usecases.
Add "--relax" to address this limitation.
The set of file based output types is open-coded in three places (and a
fourth one is about to be added), let's define it once, next to the
other ExecInput/ExecOutput predicates.
So far strip_tab_ansi() was very superficial: it only focussed on OSC
and CSI sequences, and left the other ANSI sequences in touch.
Let's make it more powerful and port it to the more complete
AnsiSeqParser logic, and strip *all* ANSI sequences.
For the relevant usecases this seems like the better, safer choice,
since it's good to strip too much rather than too little, when
stripping ANSI sequences.
We generally want that the exposed strings for enum values and the
internal names for them stay in sync. Let's make sure this is the case
for the ConfidentialComputing enum.
This just changes the internal names, so that they match the external
ones. No user visible change, just some search and replace.
This undoes some of the work in #43603 which was a follow-up to #42900
which – unintentionally I'd claim – renamed some JSON fields. Instead of
setting those changes in stone we should undo them.
Not just to not needlessly break compat, but more importantly because
the old names made more sense given the underlying .feature file knobs.
Similar as the previous commit: the field was renamed by accident, and
we should revert to the old name to not break compat needlessly, and
because the old name actually made sense, given the underlying .transfer
file knob is AppStream=
The "isEnabled" name was changed from "enabled" post v261 by accident
(because a6f7ded859 replaced json
formatting via table formatter to a native json generator which was
introduced for varlink, which changed the names). THis was later made
official in #43603, but it should rather have changed things back to the
original name, in particular as the underling .feature file field
actually is called "Enabled=" and not "IsEnabled=".
We really should take care to generate the same names for Varlink JSON
data as for the data returned by the systemd-sysupdate cli.
a6f7ded859 ensured that, so that's great.
But at the same time I think the varlink names should be adjusted to the
old names, since varlink support for this was just added in this cycle.
Given that v262 is not tagged yet, let's now revert to the old name.
This updates a couple of links talking about Varlink:
1. anything that refers to specific Varlink concepts now point to the
UAPI.20 spec
2. More general references to Varlink as a whole point to both the
varlink.org domain and the spec.
PAM is a bit quirky: the main libpam calls are pam_authenticate(),
pam_open_session(), pam_acctmgmt(), pam_chauthtok(), pam_setcred() and
each have their own PAM "management group" in PAM configuration files
that configure the modules to call: "auth", "account", "session",
"password" – except for pam_setcred() which shares its grpup with
pam_authenticate() and uses "auth".
Both our PAM configuration files we ship by default are never used for
authentication (they just appear in PAMname= in a service to get a PAM
session set up, and PAMName= never calls pam_authenticate()). However,
they end up being used for pam_setcreds() (because some modules want to
use that the service manager calls it).
So far we used the pam_deny module for the "auth" management group for
these two PA; configurations (since
d6aed1dca8) but that's not ideal, since it
means we'll always cause pam_setcreds() to fail which will create debug
log noise (since the service manager debug logs pam_secreds() failures).
Let's switch to pam_rootok for this instead. This has the benefit that
pam_setcred() will always succeed for this, and pam_authenticate() only
if the caller is root anyway.
This is great, because it means our PAM configuration cannot be misused
for other purposes accidentally (authentication will fail, unless you
are already root), but won't result in any log noise (debug or
otherwise).
Follow-up for: d6aed1dca8Fixes: #39617
When we set up a device with LUKS or verity, we so far didn't release
references to the allocated device nodes even though we destructed the
volumes they are for. Let's fix that, and release everything.
This mostly matters for cases where multiple attempts to unlock are made
(for example because of a password issue), without releasing the
DissectedImage.
This drops a good chunk of 21ab2fe6ec
again, which I think is plainly wrong or at the very least too
overengineered.
1. it's wrong to assume that overlayfs layers are mounted elsewhere in
the fs. it's quite likely they aren't. and overlayfs correctly passes
through fsync() to the top layer, hence we really should keep syncing
it.
2. network file systems deserve syncing. This code here runs in the
initrd, where a very restrictive set of file systems is mounted and
which runs for a very short time only, i.e. the circumstances haven't
really changed. Hence I am very sure it's better to sync file systems
here than not to, we do this for safety reasons after all.
Reliability always trumps speed here, we should not give up
correctness over presumed speed improvements.
3. There's zero reason to believe FUSE doesn't need syncing. We live in
a world where increasingly complex kernel file systems are moved to
userspace, and hence FUSE can be used to implement *anything*. Hence
we should sync it. Yes, FUSE means some backing process needs to run,
but that's a job for the initrd to get right: make sure the process
runs properly over the switch root if the mount is left in tact over
the switch root too.
Hence, dumb this all down and drop the weird fine tuning here.
Let's make timer prop handling less special, and more like path/socket
handling. Let's move the checks for at least one OnXYZ= setting to a
common place at the end of parsing, instead of explicit checks for each
property.
Let's shorten an already very long .c file, by splitting it apart a bit.
Splitting out the polkit code is relatively easy, since it does not
touch any of the arg_xyz variables.
This is a pretty relevant usecase: preparing an image on some trusted
host, submitting it to some other host that authenticates it and
decrypts it, and consumes it only then.
Let's support this explicitly.
For various cases it is interesting to both sign and encrypted a file
system, for example to prepare it on one host and provide it to another.
Let's explicitly support preparing this in systemd-repart via setting
both Verity= and Encrypt=.
## Problem
A `BrowseServices` subscription with `"ifindex":0` (browse all
interfaces) receives a continuous flap of `added`/`removed` events for a
service that is still present — within a second, and with no goodbye
packet involved.
## Root cause
For `ifindex==0`, `mdns_browser_revisit_cache()` looked up each mDNS
scope's cache separately and called `mdns_manage_services_answer()`
**once per scope**. That function derives `removed` events by diffing
the browser's *global* discovered-service list (all interfaces, filtered
only by owner family) against the single answer it's handed. So with ≥2
mDNS-relevant interfaces of the same family, a service present on
interface A isn't in interface B's answer and is spuriously removed
while B is reconciled, then re-added on the next revisit tick.
## Fix
Accumulate the pruned cache answers from every matching mDNS scope into
one combined `DnsAnswer` and reconcile **once**, so removals diff the
global list against the union across interfaces. Items are merged with
`dns_answer_add_full()` (not `dns_answer_extend()`, which defaults each
item's `until` to `USEC_INFINITY` and would skew the RFC 6762 §5.2
TTL-maintenance schedule). The single-interface (`ifindex>0`) path is
unchanged.
## Test
`TEST-89-RESOLVED-MDNS.sh` gains `testcase_browse_ifindex_zero_no_flap`:
it adds a service-less dummy mDNS link to guarantee ≥2 same-family
scopes (the flap precondition), browses `ifindex=0`, waits for
discovery, then asserts **zero** `removed` events while every publisher
stays up. The subscription uses `varlinkctl --timeout=infinity`, since
it sits idle after discovery and the default 45s idle timeout would
sever it (and the assertion) mid-observation.
## Testing status
Builds clean; `shellcheck -x` clean. First CI round: `TEST-89`
(including this testcase) passed on all mkosi platforms; the failing
jobs all traced to unrelated flakes/infra.
Following on from adding the basic varlink scaffolding to sysupdate,
let’s varlinkify a couple of the D-Bus methods. Because varlink doesn’t
have a concept of object paths, the D-Bus path structure which allows a
target to be selected has been squashed down to a target argument for
each relevant method.
Varlinkify the way to list targets, and also the way to list features
because that was simple to do at the same time.
More methods need varlinkifying in the future, but let’s do it in small
and manageable chunks.
Allow full UAPI.10 version strings, i.e. "+", "_", "~" and "^" too, to
match the recent reworking.
These version strings are generally distro-managed, hence use the more
liberal alphabet.
Fixes: #32785
Let's take inspiration from string_is_safe() and take a flags field that
allows fine tuning the validation.
Then port over all current users of either function to the new logic.
Note that this *does* change behaviour in various cases:
1. Generally: we'll now always accept the full UAPI.10 alphabet,
including the "~" and "^" characters. As far as I can see there's no
downside to this liberalization as none of the current consumers of
the two functions uses these characters for anything else.
2. systemd-analyze compare-version will now accept version strings with
"_" and "+" without complaining. I see no downside here, it just
normalizes these debugging tools, to make them accept what most our
other tools accept.
3. "bootctl link" will not accept empty version strings anymore
Which is a bugfix I guess.
4. vpick will now refuse "_" and "+" in version strings. It kinda
already did, because when parsing versions from filenames it uses "_"
and "+" as name, architecture and attempt counter separators. We now
systematically refuse it everywhere else in vpick too. This is hence
a clean-up.
Fixes: #28906
Replaces: #42815#41937
Let's bring the version string character set into a systematic order,
matching the order in which they appear and are defined in the UAPI.10
specification text.
This makes it easier to compare the relevant functions.
Allowing this apparently has been cargo-culted from my initial sysupdate
PR, but Claude and me could not find a single other software package
that uses "," as a character within version strings. Hence, let's remove
this, even though this is a compat breakage of a kind, in the hope
nobody notices. We can easily restore this if this later shows to be an
issue for people.
The "Donate to preceding partition" logic is dead code since commit
https://github.com/jonas2515/systemd/commit/19903a433507897449c086b72abb5e133e431336
("repart: split out context_grow_partition_one()").
context_grow_partition_one() gets passed a free area and a partition,
and it has
an early-return check to ensure the partition it got passed belongs to
the free
area it got passed. That means we compare the FreeArea a to the FreeArea
a->after->allocated_to_area, which always yields FALSE.
Fix the behavior of donating any left over space to the preceding
partition
by adding that partition to the loop below (and relying on the
partitions list
being ordered according to physical partition offsets).
Since this behavior is not that easy to trigger, mention how to trigger
it in a
comment, and add a test for it as well.
If the read-only FAT file attribute is set on a boot entry file with a
counter in its name, don't attempt to rename it, but simply skip the
boot counter logic for it, taking the flag as a hint that the entry
shall not be subject to boot assessment.
If the boot secret mixin file exists but is empty we'd normally fill it
with a fresh mixin. Refrain from that if the read-only FAT file
attribute is set on it, taking that as a hint that the file shall not
be initialized. Reading an existing, fully populated mixin file remains
unaffected by the flag.
If the read-only FAT file attribute is set on /loader/random-seed,
don't update the seed file — and hence don't use it either, since a
seed we cannot update would be the same on every boot.
This gives users an explicit way to turn off random seed handling by
marking the file read-only, useful for example in pre-built OS images
that are replicated to many systems, where the baked-in seed is shared
and hence must not be credited.
The check is done upfront in process_random_seed(), before any other
work, mirroring the existing check for read-only volumes. This covers
both systemd-boot and systemd-stub, which share this code.
Inspired-by: #42979
Treat an empty volume name alongside other fields as unset instead of
rejecting it as invalid.
Example use case:
```
EncryptedVolume=:none:discard
```
In this case, the volume name is not specified so it can be generated as
luks-UUID.
From the docs:
> EncryptedVolume=
> Specifies how the encrypted partition should be set up. Takes at least
one and at most four fields separated with a colon (":"). The first
field specifies the encrypted volume name under /dev/mapper/. If not
specified, "luks-UUID" will be used where "UUID" is the LUKS UUID.
The current TPM2 PIN mode is flawed as a compromised TPM directly
exposes
the sealed secret which is the LUKS volume key itself
(https://github.com/systemd/systemd/pull/27502 and
https://github.com/systemd/systemd/issues/37386).
Goal: add Argon2id-based PIN hardening to TPM2 enrollment, making
the TPM a second factor rather than a single point of failure:
1. Password + salt → Argon2id → 512-bit key split into Key1 + Key2
2. Key2 (base64-encoded) is used as the PIN to seal a random secret
in the TPM
3. Key1 + unsealed secret → HKDF-SHA256 → final LUKS volume key
This implementation ensures that if the TPM is compromised, an attacker
still needs the password to derive Key1 and combine it with the unsealed
secret.
The --tpm2-with-pin= option now accepts three values:
- false (no PIN used)
- true (PIN hardened with Argon2id - default)
- "direct" (legacy PIN without Argon2id for backward compatibility)
Argon2id parameters are customizable via:
--tpm2-argon2id-memory=
--tpm2-argon2id-iterations=
--tpm2-argon2id-parallelism=
--tpm2-argon2id-iter-time=
These default to a function of available CPUs and physical memory, with
a benchmark that scales iterations to the target time (default: 2s) and
falls back to ARGON2ID_PARAMETERS_DEFAULT (64 MiB, 8 iter, 4 lanes) when
auto detection fails.
Also if the runtime OpenSSL lacks Argon2id support (< 3.2), the feature
silently falls back to direct PIN mode with a warning.
Added includes:
- src/cryptenroll/cryptenroll.c: cpu-set-util.h, limits-util.h,
time-util.h
for Argon2id benchmark auto-tuning (cpus_online, physical_memory_scale,
now/usec_t)
- src/cryptenroll/cryptenroll-tpm2.c: crypto-util.h for
Argon2IdParameters
struct in load_volume_key_tpm2()
- src/shared/tpm2-util.h: crypto-util.h for Argon2IdParameters in
tpm2_make_luks2_json() API
- src/cryptsetup/cryptsetup-tokens/luks2-tpm2.c: crypto-util.h for
kdf_argon2id_derive()/kdf_hkdf_sha256() on the token unlock path
This adds similar concepts as we already have for enable-component:
let's add a way to enable all features or the suggeste dones, and
possibly on all components.
Or in other words, with this:
systemd-sysupdate enable-component -S
systemd-sysupdate enable-feature -A -s
We'll automatically enable all suggested components, and all features of
them.
Let's now introduce "systemd-sysupdate enable-component
--component-suggested" and systemd-sysupdate enable-component
--component-all" for enabling all or all suggested components at once.
Similar, if used for disable-component will disable all components or
those not suggested.
While --component-all really picks all components --component-suggested
picks only the suggested ones.
Note that none of the verbs currently implement the concept, they will
all refuse the option. Hooking this up is going to be added next.
Let's make it possible to "suggest" that certain features or components
are enabled under some conditions.
For this, both features and components gain two things:
1. A Suggested= field which takes a boolean. If true the
feature/component will be suggested for installation, if false it
will not.
2. A set of SuggestedOnXYZ= settings are modelled after ConditionXYZ= in
unit files (and implement a subset of them), will suggest some
component/feature under specific conditions.
The result of the condition is shown in the various output tools.
SImilar reasons as for the memfd change: let's normalize behaviour and
always use pid_get_comm().
This adds escaping here for the first time, which is a good thing.
Let's the common function for querying the local thread name.
This changes the escaping rules when the therad name is not quite
kosher: previously we'd just escape invalid UTF-8 charcaters, now we do
what we usually do: also escape control characters and such, and limit
us to ASCII.
The description generated here is mostly for debug purposes, and process
names should normally not require this escaping anyway (it's mostly
paranoia), hence I think this change in behaviour should be fine, it's
not part of the API in any form.
With 2c6f9af8e5 sd-varlink gained protocol
upgrade support, however only in a synchronous fashion. This adds
asynchronous protocol upgrade for the server side, thus enabling
multiplexing daemons (i.e. those that handle multiple connections from
the same event loop) to support protocol upgrades too.
I plan to use this in the upcoming "ptybroker" component that allows
acquiring a pty through varlink.
/cc @mvo5
We can't make a lot of restrictions here, since users are allowed to
basically freely pick their user names and UIDs too. But let's at least
exclude system UID ranges and those beyond the 16bit range.
When doing a userdb lookup we might end up issuing a lot of IPC calls in
parallel to backends and cause them all to do work, with us waiting for
it. Let's optimize this a bit, and indicate on the socket inodes via
xattrs hints which kind of records are provided by a backend. That way
we can suppress lookups to them and optimize runtime behaviour.
This only works on Linux 7.1 and newer where socket inodes gained
support for extended attributes.
This are to the existing sd_varlink_call_and_upgrade() what
sd_varlink_callb() and sd_varlink_callbo() are to sd_varlink_call():
they put together an object on the fly, via the usual JSON builder
logic.
These are the next 3 commits from #42651. Split out again, in the hope
to get a review from claude.
ptal.
full test suite and docs are in #42651. test suite passed there.