663f0bf5cb stopped reusing the original block device fd whenever
partition scanning was requested (LO_FLAGS_PARTSCAN) but couldn't be
enabled on the device, so that nested partition tables on devices the
kernel won't scan (e.g. the pmOS/android case) get exposed via a real
loop device.
However that also forced a pointless loop device for any partition that
carries a file system directly, e.g. a btrfs subvolume mounted via
MountImages=. For multi-device btrfs this is fatal: the kernel rejects
seeing the same member via both the original partition and the loop
device, and the mount fails.
A loop device is only ever needed here to expose a nested partition
table. So only refuse the shortcut when the device actually carries one,
probed via gpt_probe(), instead of whenever partition scanning is
disabled. Devices carrying a file system directly (or nothing) take the
shortcut as before.
Add an integration test to cover the failure scenario of the original
issue.
Fixes: https://github.com/systemd/systemd/issues/42520
Replaces: https://github.com/systemd/systemd/pull/42576
Follow-up for 663f0bf5cb79ecaf6dd71441ecdc9dc401e7eae6
Co-Authored-By: Luca Boccassi <luca.boccassi@gmail.com>
Co-developed-by: Claude Opus 4.8 <noreply@anthropic.com>
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.
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.
probe_gpt_boot_disk_needs_loop() sets ID_PART_GPT_AUTO_ROOT_DISK_NEEDS_LOOP
for any whole disk that holds the boot ESP/XBOOTLDR but whose partition table
the kernel cannot parse. Until now the udev rule turned that into a
systemd-loop@.service for every block device.
That is too broad: device-mapper devices also report kernel partition
scanning as disabled, but their partitions are managed in userspace by kpartx
(see 66-kpartx.rules). Setting up a loop device on top of them re-exposes the
same partition table a second time and only causes trouble.
Restrict the rule to optical drives, the one class that genuinely needs a
kernel-side loop device (El Torito GPT sector size mismatch, or drives that do
not support partition scanning) and that has no userspace partition manager of
its own.
Co-developed-by: Claude Fable 5 <noreply@anthropic.com>
Since 4e0eabd401 ("udev: also trigger loop device for boot disk when
partition scanning is unsupported"), builtin_blkid() bails out entirely as
soon as probe_gpt_boot_disk_needs_loop() reports that a loop device is
needed, skipping all superblock probing. As a result whole-disk properties
such as ID_PART_TABLE_UUID and ID_FS_* are no longer set.
This regresses any whole disk whose partitions the kernel cannot expose
itself but which is otherwise perfectly probeable, most notably
device-mapper multipath disks: kernel partition scanning is disabled on them
(their partitions are managed in userspace by kpartx), so they are now
flagged as needing a loop device and lose their ID_PART_TABLE_UUID.
The early return was never necessary. The original intent was only to skip
root partition discovery on the device, and that already happens on the loop
device instead: find_gpt_root() bails when the kernel can't scan partitions,
blkid probes at the device's own logical sector size so a GPT written for a
different sector size is simply not detected, and PART_ENTRY_* is only
emitted for partitions the kernel actually registered, of which a
loop-needing whole disk has none. So keep probing the device for its
whole-disk properties unconditionally and let partition and root discovery
happen on the loop device.
Co-developed-by: Claude Fable 5 <noreply@anthropic.com>
Now that the fast path performs a deep copy identical to the general
loop (when n_changes_attached==0, found stays false for all entries),
the block is redundant. Remove it and let the general loop handle this
case.
Signed-off-by: dongshengyuan <dongshengyuan@uniontech.com>
Co-developed-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
At line 285, ftruncate() failure was logged using 'r' which is 0
from the preceding successful loop_write() call. log_error_errno(0, ...)
triggers an assertion crash in developer builds (ASSERT_NON_ZERO) and
silently returns success in release builds, swallowing the ftruncate error.
Replace with errno which is set by ftruncate() on failure.
Signed-off-by: dongshengyuan <dongshengyuan@uniontech.com>
Co-developed-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
```
../src/boot/test-efi-string.c: In function 'test_xvasprintf_status':
../src/boot/test-efi-string.c:744:34: error: format '%zi' expects argument of type 'signed size_t', but argument 4 has type 'long int' [-Werror=format=]
744 | test_printf_one("%i %i %zi", INT_MIN, INT_MAX, SSIZE_MAX);
| ~~^
| |
| int
| %li
cc1: some warnings being treated as errors
ninja: subcommand failed
```
A previous refactoring failed to copy the flag from the command line
argument to the installation context object, so the flag was ignored.
Closes: https://github.com/systemd/systemd/issues/41488
Fixes: 38433a6d06 ("bootctl: rework bootctl-install.c in preparation of varlinkification")
If a partition gets removed due to factory reset, we will recreate it
as blkpg later. So it needs to get removed. So rescan is needed to be
done after we write the partition table for factory reset.
Fixes#42453
This will also allow debugging systemd-boot easily on RISC-V.
Note that the following much simpler variant won't work, as we might be missing
the optional 'zihintpause' extension:
asm volatile("pause");
Signed-off-by: Marcel Ziswiler <marcel.ziswiler@codethink.co.uk>
unhexmem_full() ignores whitespace, so a 64-byte manifest digest field
can decode to fewer than 32 bytes. Reject that while parsing instead.
[ 83.883087] TEST-72-SYSUPDATE.sh[5995]: systemd-sysupdate: ../src/src/sysupdate/sysupdate-resource.c:581: resource_load_from_web: Assertion `h.iov_len == sizeof(instance->metadata.sha256sum)' failed.
Follow-up for 43cc7a3ef4
Assisted-by: kres (claude-opus-4-7)
Co-developed-by: Claude Opus 4.8 <noreply@anthropic.com>
manager_varlink_done() tore down the varlink server without dropping the
queued reload reply, unlike bus_done_api() which unrefs
pending_reload_message_dbus. Unref it here too, so the slot consistently
mirrors the D-Bus side at teardown.
Follow-up for 55a1b36e91
Assisted-by: kres (claude-opus-4-7)
Co-developed-by: Claude Opus 4.8 <noreply@anthropic.com>
After enumeration, networkd may receive RTM_NEWLINK messages carrying a
stale interface name. This can happen when interface rename notifications
are queued before link enumeration and processed afterwards.
Previously, networkd could become confused by such a message and put the
corresponding Link into the failed state. Avoid this by checking whether
the new interface name is already in use by another interface and ignoring
the rename if so.
Fixes#20203.
E.g. on issue #20203, we may wrongly remove entry for another interface.
Let's mitigate issue on such situation for safety, though this does not
solve the issue.
This reverts commit 176b8be10f.
The check introduced by the commit is racy, as when format_ifname() is
called, the interface may be already renamed (again) to another name.
This is typically problematic when we swap interface names:
```
ip link set aaa name tmpname
ip link set bbb name aaa
ip link set tmpname bbb
```
When networkd received the notification about name change aaa -> tmpname,
the interface is already renamed from tmpname to bbb. So, the reverted
logic skips updating Link.ifname:
```
aaa: New interface name 'tmpname' received from the kernel does not correspond with the name currently configured on the actual interface 'bbb'. Ignoring.
```
On the second notification about name change bbb -> aaa, networkd fails to
update the mapping Manager.links_by_name, as we skipped previous renaming
and the mapping still has an outdated entry for 'aaa'.
```
bbb: Interface name change detected, renamed to aaa.
aaa: Failed to manage link by its new name: File exists
aaa: Could not process link message: File exists
aaa: Failed
aaa: State changed: configured -> failed
```
By reverting the commit, the issue is fixed. But the commit intended to
fix another issue #20203. So this reintroduces #20203. Let's fix it
in a later commit.
Fixes#42527.
Reintroduces #20203.
The flags parameter is parsed into a global variable, which means
when there are multiple consecutive calls it is reused. Switch to
a local copy.
Follow-up for 066f6bfb62
Assisted-by: kres (claude-opus-4-7)
Co-developed-by: Claude Opus 4.8 <noreply@anthropic.com>
head_data_offset is declared as le64_t in journal-def.h, so it must be
assigned with htole64(p), not le64toh(p). All other le64_t field
assignments in this file (hash, next_hash_offset) consistently use
htole64().
On little-endian systems this makes no difference, but on big-endian
systems the field->data link would be stored with incorrect byte order,
corrupting journal file traversal.
Assisted-by: claude-opus-4-8 <noreply@anthropic.com>
So far --graceful only short-circuited when no TPM was present at all (the
!tpm2_is_mostly_supported() check). If a TPM is present but can't actually be
used for the measurement we want, the measurement still failed hard. For
systemd-pcrextend instances ordered before sysinit.target this pushes the
system to degraded and blocks boot, which defeats the purpose of --graceful.
Make the two extend helpers report every "TPM is present-or-absent but cannot
be used for this measurement" condition with a single errno, -EOPNOTSUPP: no
usable PCR bank, no TPM device, missing crypto (e.g. AES-128-CFB), no NvPCR
support, and OpenSSL-less builds. tpm2_context_new_or_warn() reports a missing
device as -ENOENT, so each helper translates that to -EOPNOTSUPP at the call
site, keeping every errno single-meaning.
Co-developed-by: Claude Opus 4.8 <noreply@anthropic.com>
The have_updatectl variable is meant to gracefully handle the case where
updatectl is missing. But, because the script runs with -e, it fails
immediately in that case instead. Moreover, expanding $have_updatectl
when it is present actually executes updatectl, rather than simply
checking for its existence.
Re-factor this check so that it does handle a missing updatectl.
When a slot is disconnected, previously we tried to remove the slot from
the hashmap with a wrong key. Hence, the pointer to the freed slot object
remained in the hashmap.
The cleanup destructor for VarlinkServerSocket only freed ss->address and
the struct, leaking ss->event_source. If sd_varlink_server_listen_address()
hits OOM at free_and_strdup() after the io-source was already armed, the
source stays registered in the event loop with userdata pointing at the
freed socket. Disable it before freeing; the call is a no-op when the
source was never armed, so the other freep sites are unaffected.
Follow-up for c14e841f31
Co-developed-by: Claude Opus 4.8 <noreply@anthropic.com>