Since being online is a privileged operation, it’s better to fail-safe
and make the `Context` offline by default unless explicitly initialised
(e.g. with `context_from_cmdline()` or an explicit initialisation of
`.offline = false`).
There are a few instances where `.offline = true` is set explicitly.
I’ve left those in place, even though they’re now redundant, as
documentation.
Signed-off-by: Philip Withnall <pwithnall@gnome.org>
(cherry picked from commit 97183383af03279c43d9c270af5832d36d527d01)
Currently, `CONTEXT_NULL` initialises `.offline` to false, so helper
contexts are being accidentally run in online mode. Fix that.
The following commit will rework this to be safe by default, but let’s
fix the individual instances first.
Signed-off-by: Philip Withnall <pwithnall@gnome.org>
(cherry picked from commit 4212fba4a4258a19057642d13a0ae52181675e23)
I’m about to refactor it slightly and it would be nice to have a little
test coverage to check against.
(cherry picked from commit 8433ed1c7a66ee575621cde027a890017769252c)
The domain and protocol arguments of socket() are ints, but are passed
to the kernel in 64-bit registers, and the kernel truncates them to the
low 32 bits. The rule that makes socket(AF_NETLINK, *, NETLINK_AUDIT)
fail compared the full 64-bit registers with SCMP_CMP_EQ, so setting any
bit above bit 31 in either argument let an audit socket be created.
Use SCMP_CMP_MASKED_EQ with a 32-bit mask for both comparisons.
Follow-up for #44134
Signed-off-by: Ricardo Branco <rbranco@suse.de>
(cherry picked from commit 03e27922cae696af7a15b5375e1820e868284286)
The nstype argument of setns() is an int, but it is passed to the kernel
in a 64-bit register, and the kernel truncates it to the low 32 bits.
The rule that blocks setns() with nstype == 0 compared the full 64-bit
register with SCMP_CMP_EQ, so setting any bit above bit 31 let the call
through, and the kernel then joined whichever namespace the fd referred
to, even one that RestrictNamespaces= is supposed to deny.
Use SCMP_CMP_MASKED_EQ with a 32-bit mask so we match on the same value
the kernel does.
Add a test that issues setns() via syscall() with an upper bit set.
Follow-up for #44134
Signed-off-by: Ricardo Branco <rbranco@suse.de>
(cherry picked from commit da72537164910f9050793055fef030711c00b954)
The domain argument of socket() is an int, but it is passed to the kernel
in a 64-bit register, and the kernel truncates it to the low 32 bits.
The deny-list rules we install compared the full 64-bit register with
SCMP_CMP_EQ, so setting any bit above bit 31 (e.g. AF_VSOCK | 1UL << 32)
let a denied family through unfiltered.
Use SCMP_CMP_MASKED_EQ with a 32-bit mask so we match on the same value
the kernel does.
The allow-list path is not affected: it relies on the LT/GT range checks,
which compare as unsigned 64-bit, so values with upper bits set are
always rejected.
Add a test that issues socket() via syscall() with an upper bit set.
Fixes: #44134
Signed-off-by: Ricardo Branco <rbranco@suse.de>
(cherry picked from commit 62eb6cd8eab6a35a408b2c6547526645bda55ffa)
Data and field objects are only ever appended, and a new object is
always linked after the current tail of its hash chain, so a valid
next_hash_offset is either 0 or larger than the offset of the object
itself. A new data object is also prepended to the list of data objects
of its field, so a valid next_field_offset is always smaller than the
offset of the object itself. Nothing checks either of these when an
object is read, so if a chain loops back on itself, everything that
walks it loops forever:
- "journalctl --verify" spins in data_object_in_hash_table() instead of
reporting the file as corrupted,
- journal_file_punch_holes() never returns when the file is archived,
so it is never offlined,
- sd_journal_enumerate_fields() returns the same field over and over,
so "journalctl --fields" never finishes,
- sd_journal_enumerate_unique() returns the same value over and over,
so "journalctl -F FIELD" never finishes.
A single flipped bit in next_hash_offset or next_field_offset is enough
for any of these.
Check both in check_object(), like we already do for
next_entry_array_offset, so that all readers are covered.
(cherry picked from commit a1bf29afbeed5e4c702f58ea5a9038e433c99c11)
Since a couple of days the pcrlock subtest fails intermittently on
debian-testing and arch CI runs (unrelated PRs: #44152 and others), with
"systemd-pcrlock is-supported" printing "partial" and exiting with 97,
i.e. TPM2_SUPPORT_FIRMWARE is missing.
The console output of the affected boots shows that the TPM already
breaks down while the firmware runs:
EFI stub: WARNING: Failed to measure data for event 1: 0x8000000000000007
EFI stub: WARNING: Failed to measure data for event 0: 0x8000000000000007
i.e. the TCG2 protocol is there, but all measurements fail with
EFI_DEVICE_ERROR, systemd-stub reports no active PCR banks in
LoaderTpm2ActivePcrBanks, and ConditionSecurity=measured-os is hence
false for the whole boot. pcrlock can't do anything useful in that case,
so let's skip the subtest instead of failing, and log what
"systemd-analyze has-tpm2" reports so that this remains visible.
(cherry picked from commit 09fdbf4d715e962cc13fd678760754e59d0aeeaf)
dir_cleanup() stores the result of xstatx_full() in r, which is also the
function's return value. If a file is removed between readdir() and
statx(), it is skipped, but when it was the last entry r stays -ENOENT
and --clean fails with EX_CANTCREAT without logging anything. A
successful statx() also overwrote errors recorded for earlier entries.
Use a separate variable for the statx() result.
Reproducer:
d=$(mktemp -d)
echo "d $d - - - 1d" >$d.conf
while :; do touch $d/f{1..200}; rm -f $d/f*; done &
for i in $(seq 200); do systemd-tmpfiles --clean $d.conf; echo $?; done | sort | uniq -c
kill %1
Before:
177 0
23 73
After:
200 0
Follow-up for a98a6eb95c.
Follow-up for 10072d8be4.
(cherry picked from commit 4c250e3f1325f91cdee047f7daeaf532abe4af6f)
When namespace_enter_full() is called with namespaces that the current
process is already a part of, skip the setns() call on the user
namespace. This allows the function to succeed without CAP_SYS_ADMIN.
Follow-up for 211c3c9d41
(cherry picked from commit 27b1fd3a1e2e6c28bb09ec79cb3dc949a4ba416d)
tpm2_parse_luks2_json() only insists on "tpm2_pubkey" being present when
"tpm2_pubkey_pcrs" is set, but happily accepts a token carrying
"tpm2_pubkey_ref" without a public key. tpm2_unseal() then trips over its
assert(!pubkey_policy_ref || iovec_is_set(pubkey)), i.e. a crafted LUKS2
header aborts whatever tries to unlock it instead of being rejected.
tpm2_make_luks2_json() never writes that combination (it asserts the same
invariant), hence refuse it when parsing, as is already done for a PCR
mask without a public key. This matters more now that systemd-dissect,
systemd-nspawn and systemd-sysext unlock images via these tokens, as the
headers they see are less trusted than the host's own volumes.
(cherry picked from commit 3520b44f7e398f924c267ee4527941924297c6bc)
Since 7da67c3f8b ("vconsole-setup: skip setfont(8) when the console
driver lacks font support") font_load_and_wait() probes the font with
KDFONTOP before running setfont(8). The kernel returns EINVAL for a vc
that is not in KD_TEXT, which is not treated as "no font support", so
systemd-vconsole-setup now fails with
Failed to check '/dev/tty1' has font support: Invalid argument
when run on an explicitly specified vc that a graphical splash (e.g.
plymouth) occupies, for instance from a unit ordered after getty@tty1.
Previously setfont(8) silently ignored this case: verify_source_vc()
accepts it with a notice that the font settings likely won't be applied,
and setup_remaining_vcs() skips such vcs. Do the same here, skip the
font setup and still load the keymap.
(cherry picked from commit 4a3ece0b733d41eab9baad25648c8a921c590ed2)
The tag separator can only appear as the last path component, hence
start the search there.
Fixes an issue reproducible through:
```
> /usr/lib/systemd/systemd-pull oci quay.io:443/fedora/fedora fedora-without-tag
OCI ref 'quay.io:443/fedora/fedora' is invalid.
```
(cherry picked from commit fe9fe613d92f2acffdf3f8b96d3af027f19d6b7e)
GetMemberships with both keys only filtered groupName and could return
other members.
Reproduce with a non-member and a group that has members:
varlinkctl call --more SOCKET io.systemd.UserDatabase.GetMemberships
'{"userName":"nonmember","groupName":"GROUP","service":"io.systemd.Multiplexer"}'
(cherry picked from commit 2126abeb6d4905f95b963c7f5c5bc4bd92444ba5)
If sources are already pending, sd_event_prepare() calls
sd_event_wait(e, 0). Since fd69f22475 this returns 0 when a ratelimit
expiry callback was invoked, so that sources re-enabled by the callback
are evaluated in the next iteration. However, sd_event_prepare() then
returned 0 ("nothing pending"), so sd_event_run() blocked in epoll_wait()
forever, as the pending sources never make the epoll fd readable.
PID 1 can hit this via the ratelimited mount event source, which hangs
the boot, e.g. in the initrd after sysroot.mount.
Fix this by remembering in the sd_event object that a ratelimit expiry
callback was invoked in this iteration. In that case sd_event_wait()
reports the loop as pending, and sd_event_dispatch() returns right away
without dispatching anything, so that the caller goes directly for
sd_event_prepare() again, and no other callback is dispatched in the
same iteration.
Add a test that reproduces the issue.
Follow-up for fd69f22475.
Fixes#44107
(cherry picked from commit 1a60b10de9e4a3fe59a2efa3c6a58fd72c305807)
NvPCRs persist across boots, so on almost every boot NV_DefineSpace()
failed with TPM2_RC_NV_DEFINED before we fell back to reusing the
index, and the TSS logged that as an error. Check for an existing
index first and only define a new one if there is none.
Signed-off-by: Paul Meyer <katexochen0@gmail.com>
(cherry picked from commit 3c59c8daec12c445f446237c260594e4f5eb6b34)
Pass the digest of the init branch to the NvPCR define and write policy
helpers instead of the PCR public key and policy ref, bundle what is
needed to satisfy the init branch into a struct, and split opening the
write session into an init and an extend variant. No functional change.
This prepares for supporting a second kind of init policy.
Signed-off-by: Paul Meyer <katexochen0@gmail.com>
(cherry picked from commit 13c417c1faa372a5c7f32d01385f741bc6e5cf57)
THe limits are hit with valid configurations, hence raise the limits
4x.
Fixes: #44125
(cherry picked from commit 116981d536f52279715df266098bf3093037fc3f)
Since dac2b39405 ("compress: strictly check if stream finished on
decompress") the gzip branch of decompressor_push() no longer loops
"while (avail_in > 0)", but loops until inflate() can make no further
progress, so that we can properly detect truncated streams and trailing
garbage. This means inflate() may now be called with no input left.
If a previous iteration happened to fill the output buffer exactly
(avail_out == 0) while also consuming the last input byte (avail_in ==
0), we go around once more, and inflate() then has nothing to do and
returns Z_BUF_ERROR. This is documented zlib behaviour and not an error
condition: it merely indicates that no progress was possible. However,
we treated anything other than Z_OK/Z_STREAM_END as a corrupted stream
and returned -EBADMSG, hence valid gzip data was refused whenever the
input chunk boundaries happened to line up with the output buffer size
in this way.
Accept Z_BUF_ERROR if all input has been consumed, and let the existing
avail_in/avail_out check that follows decide whether we are done with
the current input, or whether the stream is truncated (in the size == 0
finalization case). If input is left, Z_BUF_ERROR still results in
-EBADMSG, so that we never loop forever without making progress.
Whether the boundary condition is hit depends on the data being
decompressed and on how it is chunked. This showed up in CI here:
https://github.com/systemd/systemd/actions/runs/38428217767/job/115403151687?pr=44163
Add a test that decompresses incompressible data split at every offset
around COMPRESS_PIPE_BUFFER_SIZE, which reliably triggers the condition
for gzip, and checks the other algorithms the same way for good measure.
Follow-up for: dac2b39405
(cherry picked from commit 4128feb9f29e01ccd1f6b7594acc4af579ba4534)
EV_EFI_HANDOFF_TABLES and EV_EFI_HANDOFF_TABLES2 are both defined with
the same name.
(cherry picked from commit 195a17c59b22f5b0fa626fdb4917107cdc281bac)
The order of fds in fdstore may not be preserved.
Set a name for the stored fd, then find the fd by name.
(cherry picked from commit b5372aef629c12266d9a87bafcb1192c697e5d86)
- if 'set +e' is called in a trap (except for EXIT), then call
'set -e' at the end.
- added several missing cleanups.
(cherry picked from commit a7de35462a3df6a30e7eba2d36d1b8bd2fd92aaf)
"systemctl is-system-running --wait" installs a match rule for the
StartupFinished signal, but never calls the manager's Subscribe()
method. PID 1 broadcasts manager signals unconditionally only on direct
(private) bus connections; on the API bus it emits them only while at
least one client is subscribed (see bus_foreach_bus()).
When run as non-root, systemctl talks to PID 1 via the system bus and
only receives StartupFinished if some unrelated client happens to be
subscribed at that moment. Otherwise it keeps waiting after boot has
completed, even though the system state is already "running" or
"degraded".
Call Subscribe() after installing the match and before querying the
current state, so the signal cannot be missed in between. This is a
no-op on direct connections, and the subscription is dropped
automatically when the connection closes.
Fixes: #44150
(cherry picked from commit 9ac5e0b4ee9e87d9ce671a70354dbab2b06c254b)
Then, added explanations for the missing arguments. Also mentioned that
the memfd is sealed by the function.
(cherry picked from commit 20604d980057da1a606339fb7a660242e8d2db02)
sd_bus_message_append_array_memfd() and
sd_bus_message_append_string_memfd() are public functions, hence the
passed fd may be already sealed by the caller. Let's gracefully handle
such case.
(cherry picked from commit 16025762d9055ec56694e4a1d74344029061b7c2)
Previously, readlink_malloc() was used to find the target device.
However, devlink is a relative symbolic link, hence the path obtained by
readlink_malloc() never matched with the one by sd_device_get_devname().
Also path_startswith(target, "/dev/") was always negative.
Let's use chase_and_stat() to obtain the absolute path to the target
device that the devlink currently points to.
Fixes the following spurious logs on remove event:
(udev-worker)[2338]: loop1p1: Processing device (SEQNUM=2231, ACTION=remove)
(udev-worker)[2338]: Notify message sent to '@4814750286313953891': "INOTIFY_WATCH_REMOVE=1"
(udev-worker)[2338]: loop1p1: Symbolic link '/dev/udevtest/x2' points to '../loop1p1' which is outside of '/dev/', updating it.
(udev-worker)[2338]: loop1p1: No reference left for '/dev/udevtest/x2', removing
(udev-worker)[2338]: loop1p1: Symbolic link '/dev/disk/by-diskseq/9-part1' points to '../../loop1p1' which is outside of '/dev/', updating it.
(udev-worker)[2338]: loop1p1: No reference left for '/dev/disk/by-diskseq/9-part1', removing
(udev-worker)[2338]: loop1p1: Symbolic link '/dev/disk/by-label/udevtest-b-fs1' points to '../../loop1p1' which is outside of '/dev/', updating it.
(udev-worker)[2338]: loop1p1: No reference left for '/dev/disk/by-label/udevtest-b-fs1', removing
(udev-worker)[2338]: loop1p1: Symbolic link '/dev/disk/by-uuid/221d135f-7bf7-45b8-abeb-d9b3afb2c215' points to '../../loop1p1' which is outside of '/dev/', updating it.
(udev-worker)[2338]: loop1p1: No reference left for '/dev/disk/by-uuid/221d135f-7bf7-45b8-abeb-d9b3afb2c215', removing
(udev-worker)[2338]: loop1p1: Symbolic link '/dev/disk/by-partlabel/udevtest-b-part1' points to '../../loop1p1' which is outside of '/dev/', updating it.
(udev-worker)[2338]: loop1p1: No reference left for '/dev/disk/by-partlabel/udevtest-b-part1', removing
(udev-worker)[2338]: loop1p1: Symbolic link '/dev/udevtest/b1' points to '../loop1p1' which is outside of '/dev/', updating it.
(udev-worker)[2338]: loop1p1: No reference left for '/dev/udevtest/b1', removing
(udev-worker)[2338]: loop1p1: Symbolic link '/dev/udevtest/x1' points to '../loop1p1' which is outside of '/dev/', updating it.
(udev-worker)[2338]: loop1p1: No reference left for '/dev/udevtest/x1', removing
(udev-worker)[2338]: loop1p1: Symbolic link '/dev/disk/by-partuuid/5ef627b6-95f1-a942-8d7a-bd4ac53485ac' points to '../../loop1p1' which is outside of '/dev/', updating it.
(udev-worker)[2338]: loop1p1: No reference left for '/dev/disk/by-partuuid/5ef627b6-95f1-a942-8d7a-bd4ac53485ac', removing
(udev-worker)[2338]: loop1p1: Symbolic link '/dev/udevtest/b3' points to '../loop1p1' which is outside of '/dev/', updating it.
(udev-worker)[2338]: loop1p1: No reference left for '/dev/udevtest/b3', removing
(udev-worker)[2338]: loop1p1: Symbolic link '/dev/disk/by-loop-inode/0:36-13-part1' points to '../../loop1p1' which is outside of '/dev/', updating it.
(udev-worker)[2338]: loop1p1: No reference left for '/dev/disk/by-loop-inode/0:36-13-part1', removing
(udev-worker)[2338]: loop1p1: Symbolic link '/dev/disk/by-loop-ref/\x2ftmp\x2fudevtest-b.img-part1' points to '../../loop1p1' which is outside of '/dev/', updating it.
(udev-worker)[2338]: loop1p1: No reference left for '/dev/disk/by-loop-ref/\x2ftmp\x2fudevtest-b.img-part1', removing
(udev-worker)[2338]: loop1p1: Device processed (SEQNUM=2231, ACTION=remove)
(cherry picked from commit 03a65741d77d61929b98977d1bfdf2b470e14b55)
A verity signature partition carries a JSON object that must be followed by
NUL bytes only, up to the end of the partition (dissect refuses anything
else). The split-out artifact repart generates for it however is trimmed of
that padding since b54ef83414, so that it is a plain JSON text file (which
jq nowadays insists on).
sysupdate installs such a file into a partition by simply writing it at the
partition's offset, leaving whatever follows in place. Hence, once a shorter
signature (e.g. after rotating to a different key type) is installed into a
partition that previously held a longer one, the tail of the old signature
survives right after the new JSON object, and the partition becomes
unparsable.
Add a new PartitionZeroFill= boolean setting to the [Target] section, which
makes the importer continue writing zeroes up to the end of the partition
once the payload has been written, by passing --zero-fill= to systemd-import
and systemd-pull. It defaults to off, except for verity signature partitions
(which are tiny, hence this is cheap) where it defaults to on.
Fixes: #43567
(cherry picked from commit d3b6d765a5b320d6d864591c6a7b87e1047d0c78)
When writing a raw image into a section of an existing file or block device
(i.e. with --offset= and --size-max=, as sysupdate does when updating a
partition), we so far wrote precisely as many bytes as the payload was
large, leaving whatever followed in the destination range untouched. For
some payloads that's a problem: a verity signature partition for example
must carry NUL bytes only after the JSON object, and if a shorter signature
is written over a longer one, the tail of the old one survives.
Add a --zero-fill= boolean switch to both "systemd-import raw" and
"systemd-pull raw", which fills up the remainder of the destination range
(from the end of the payload up to --size-max=) with zeroes once the payload
has been written, via blockdev_zero_out(). It defaults to off, and requires
both --offset= and --size-max= to be specified.
(cherry picked from commit aff5aff407d421fbedc9eb0229c40996ca5570a1)
blockdev_zero_out() overwrites a byte range of a block device (or a regular
file, e.g. a disk image) with zeroes. On block devices we try to let the
kernel do the work via BLKZEROOUT, which it might be able to offload to the
device. That ioctl operates on whole sectors only however, hence incomplete
sectors at the beginning and the end of the range are filled with explicit
zeroes, and only the aligned middle part is handed to the ioctl. If that
fails, explicit zeroes are written for that part too. On regular files a
hole is punched instead (which reads back as zeroes and keeps the file
sparse), falling back to explicit zeroes if the file system doesn't support
that.
(cherry picked from commit eb98b03118f27f33d3834ef8322f38391eb2c238)
On kernels lacking CLONE_INTO_CGROUP sd-executor is forked into the
service manager's cgroup, logs a few messages from there, and only then
attaches itself to the unit's cgroup and connects stdout/stderr to
journald. Since we cache client metadata per PID and only refresh it
after 1s, log output on such a stream was attributed to init.scope
rather than to the unit, and hence "journalctl -u" (and thus
"systemd-run -v", "systemctl -v start", "systemctl -v wait") would not
show it.
Hence, if a stream tells us the unit it belongs to, and that doesn't
match what we have cached, refresh the cached data.
(cherry picked from commit 44a9316bf49967164567a7c716b79af7edf53d03)
The job map owns its keys, but the error path added in commit 1d0a8e5dbd
only frees the value when it unregisters the job. Free the key as well,
like dispatch_pending_job() does.
Signed-off-by: Martin Pitt <martin@amutable.com>
(cherry picked from commit 67b4f43a54f29b3c0fd5a455b4f956613eae8668)
The next commit drains the QMP client before resuming the VM, while
boot-time devices are being set up. Callbacks report fatal setup errors
by logging them and requesting the event loop to exit. As the loop
isn't running yet, the pump would not notice and continue. Stop it
instead, and return the error.
Signed-off-by: Martin Pitt <martin@amutable.com>
(cherry picked from commit 50063acf50dc81b194780758d3cd2c5fb0a709f4)
The upcoming boot-time device setup will need the same synchronous
driving of the QMP client before resuming the VM.
Move the loop into a helper, and generalize the error messages.
Signed-off-by: Martin Pitt <martin@amutable.com>
(cherry picked from commit 73833bdddfd4e8a1aa003516a8eda53515c9110f)
Most errors that end the event loop are logged where they happen, except
these two.
Signed-off-by: Martin Pitt <martin@amutable.com>
(cherry picked from commit 7681db4546d0eb3ef9160e90200ccaf5c9d7edc2)
Since the previous commit, pending jobs are registered and dispatched
only within vmspawn-qmp.c. Move their types and helpers out of the
header.
No behaviour change, clean code move.
Signed-off-by: Martin Pitt <martin@amutable.com>
(cherry picked from commit f1a83ef728923f1cb527724581872d4ae5daf8fc)
The QMP client's userdata (the `VmspawnQmpBridge`, vmspawn's QPM state)
and its event callback were previously only set up in
`vmspawn_varlink_setup()`, after the VM has been resumed. This caused two
problems:
- Boot-time device setup could not wait for its own completion before
the VM is resumed, as that needs exactly these replies and events.
- QMP replies and events that arrive before that were mishandled.
Command callbacks like `on_qmp_complete()` crashed on a NULL bridge
assertion. Also, `JOB_STATUS_CHANGE` events were dropped: they drive
the boot-time blockdev-create continuation for `--ephemeral`.
This only showed when the varlink setup failed, e.g. with a too long
runtime directory path. Tearing down the bridge then failed the
pending commands, and vmspawn aborted with an assertion instead of
exiting with the error.
Both were introduced with commits 882049362d and 1a7b6fd9dd.
To fix this, set the `userdata` and bind the event callback when
creating the bridge. The bridge itself handles the events that drive its
own state (job continuations, `DEVICE_DELETED`), and forwards the others
to a callback that the varlink server binds for its event subscribers.
Signed-off-by: Martin Pitt <martin@amutable.com>
(cherry picked from commit 2cac293064215d3e4f5ed92a1e898f89e6ac4629)
Previously, the sd_device object was sealed after it was verified. However,
the verifier device_verify() calls device_in_subsystem() which reads the uevent
file if the object is not sealed. Hence, basic information such as
MAJOR=/MINOR=/IFINDEX= and so on were updated by the uevent file,
and the ones passed through netlink were simply discarded.
Seal the device earlier, like we already do in device_clone_with_db().
This ensures all basic information passed through netlink is always honored.
Fixes the following issue:
$ journalctl --no-hostname --file TEST-17-UDEV.journal SEQNUM=2244 DEVNUM=259:1
Oct 12 04:44:22 systemd-udevd[404]: loop1p1: Device is queued (SEQNUM=2244, ACTION=remove)
$ journalctl --no-hostname --file TEST-17-UDEV.journal SEQNUM=2244 DEVNUM=259:2
Oct 12 04:44:22 (udev-worker)[2593]: loop1p1: Processing device (SEQNUM=2244, ACTION=remove)
Oct 12 04:44:22 (udev-worker)[2593]: Notify message sent to '@4814750286313953891': "INOTIFY_WATCH_REMOVE=1"
Oct 12 04:44:22 (udev-worker)[2593]: loop1p1: Device processed (SEQNUM=2244, ACTION=remove)
Oct 12 04:44:22 (udev-worker)[2593]: loop1p1: sd-device-monitor(worker): Passed 325 byte to netlink monitor.
Oct 12 04:44:22 (udev-worker)[2593]: Notify message sent to '@4814750286313953891': "PROCESSED=1"
Here, the main process of udevd receives the uevent with SEQNUM=2244 with
MAJOR=259 and MINOR=1. However, when it is forwarded to the udev worker,
MINOR= is changed to 2. Hence, the worker tries to read a wrong
non-existent database file and cannot remove stale devlinks.
Fixes a regression in ab1bd9daed.
(cherry picked from commit f58a2efc557a740891c5a56c82c971ae9a4e84c1)
Currently systemd-tpm2-setup will fail if NvPCR initialization doesn't
succeed, either because the currently booted UKI carries no PCR public
key, or it carries no appropriate signed policy (one with the "initrd"
policy reference). In addition to this, systemd-pcrextend will
subsequently fail because it also fails to initialize the NvPCR it is
requested to extend.
This makes systemd-tpm2-setup return EX_CONFIG in these scenarios, with
this marked as a successful exit status in the service unit file. In
addition to this, systemd-pcrextend is updated to only attempt NvPCR
initialization from the initrd (the only place it will succceed), and
when called with --graceful, to not exit with an error code if the
target NvPCR is uninitialized, and can't be initialized because of a
missing PCR public key or appropriate signed policy. When called via
Varlink, it will return the existing "NoSuchNvPCR" error.
Note that I also removed some NvPCR initialization specific exit status
codes from systemd-tpm2-setup.service.in, as these can only be returned
via systemd-tpm2-setup-early.service.
This should address the issues in
https://github.com/systemd/systemd/issues/43848.
(cherry picked from commit e846bbad04d87e58ba9c3e30d8a1087141691715)
Several places write a buffer at an offset with a single pwrite() or
pwritev(), and fail if the call writes less than the whole buffer. The
lock file of a dynamic user is then truncated to the bytes written, so
it keeps a cut-off user name. memfd_new_and_seal() fails for data larger
than one write() call accepts, which is about 2 GiB on Linux. The other
callers return -EIO, and lose the error that another write would report,
such as ENOSPC.
Use pwrite_full(), which keeps writing until the whole buffer is written
or a write fails. The lock file of a dynamic user is written from two
buffers and uses pwritev_full() instead.
repart writes the verity signature with lseek() and loop_write(). It
uses pwrite_full() as well, which does not move the file offset.
(cherry picked from commit 2fd17cb9eaca00a4dcb9af85a1f485e6d04bda04)
loop_write() writes one buffer at the file position. To write at an
offset, callers call pwrite() or pwritev() directly and handle short
writes themselves.
Add pwritev_full(), which writes all iovecs at an offset, retries on
EINTR and short writes, splits batches larger than IOV_MAX, and reports
the number of bytes written, also on failure. Add pwrite_full(), which
does the same for one buffer.
(cherry picked from commit 4d36be491a568180dc6336b91b0c496bb8cb6601)