Commit Graph
88705 Commits
Author SHA1 Message Date
Daan De Meyer f795d54591 libc,shared: detect newer library symbols at runtime
For libc syscall wrappers (pidfd_open, fsopen, openat2, etc.) we previously
gated the calls behind build-time HAVE_* checks. Replace these with shim
functions in src/libc/ that fall back to the raw syscall at runtime when the
loaded glibc lacks the symbol. The infrastructure lives in src/libc/libc-shim.h:
DEFINE_SYSCALL_SHIM falls back to a direct syscall, DEFINE_LIBC_SHIM returns
ENOSYS (for posix_spawn-family helpers that have no corresponding syscall), and
DEFINE_LIBC_ERRNO_SHIM sets errno=ENOSYS and returns -1 (for read/write-style
helpers). The weak reference to the libc symbol is bound via __asm__(\"name\")
rename so the bare libc identifier never appears as a C token — this avoids
both #undef boilerplate against override-header redirects and the resulting
-Wredundant-decls warning. Drop the corresponding cc.has_function() loop from
meson.build.

For optional libraries (libcryptsetup, libdw, libarchive), drop the per-symbol
HAVE_* checks. Always declare the prototypes, suppressing the redundant-decl
warnings via DISABLE_WARNING_REDUNDANT_DECLS and NOLINT, and resolve the symbols
after the main dlopen via a new DLSYM_OPTIONAL() helper that only assigns on
success. libcryptsetup's crypt_set_keyring_to_link / crypt_token_set_external_path
and libarchive's *_is_set wrappers use fallback functions as their pointer
initializers (returning -ENOSYS and 0 respectively), so call sites can invoke
the symbol unconditionally and just check for -ENOSYS where the \"not supported\"
distinction matters.

The same shim treatment applies to pidfd_spawn / posix_spawnattr_setcgroup_np
(src/libc/spawn.c) and epoll_pwait2 (src/libc/epoll.c), with corresponding
override headers in src/include/override/spawn.h and
src/include/override/sys/epoll.h. posix_spawn_wrapper() in process-util.c and
epoll_wait_usec() in sd-event.c now detect ENOSYS in the return value instead
of checking the function pointer, falling back to plain posix_spawn() and
epoll_wait() respectively. coredump-config and coredump-submit get a
dlopen_dw_has_dwfl_set_sysroot() helper. The kexec arch gate now uses
defined(__NR_kexec_file_load) directly; pidfd.h uses __has_include_next() to
decide whether to pull in glibc's header.

This lets binaries built against newer glibc / libcryptsetup / libdw /
libarchive headers still load and run on older targets where these symbols are
absent.
2026-05-13 10:29:50 +02:00
Daan De Meyer 5d60cd8539 syscall: add kexec_file_load to the generated override header
This makes __NR_kexec_file_load available on architectures where the kernel
UAPI headers don't define it, matching the runtime fallback path in
src/libc/kexec.c which is gated on #ifdef __NR_kexec_file_load.
2026-05-13 08:51:28 +02:00
Christian Brauner fe18d94610 vmspawn: add io.systemd.MachineInstance.ReplaceStorage (#42017)
A follow-up to the AddStorage / RemoveStorage series. ReplaceStorage
swaps the *backing file* of an already-attached storage device on a
running vmspawn-managed VM, leaving the guest-visible device frontend
(virtio-blk, virtio-scsi, nvme, scsi-cd) and every other property of
the device untouched. The intended use is to point an existing disk
at a new image without the guest seeing a hot-unplug/hot-plug cycle.

The signature mirrors AddStorage minus the 'config' field: the
device frontend doesn't change, only the backing behind it. Read-
only / read-write is derived from the new fd's O_ACCMODE; scsi-cd is
forced read-only to match the boot-time policy. S_ISBLK on the new
fd selects host_device vs file driver, matching AddStorage.

The QMP primitive is blockdev-reopen. It cannot change a file /
host_device node's 'filename' so we can't just point the existing
file node at a new fd, but it can swap a format node's 'file' child
to a different existing monitor-owned node by node-name reference
(case 3 in qemu/qapi/block-core.json:5034-5040). The chain is:

  add-fd          (host fd → new fdset)
  blockdev-add    (new file node, filename=/dev/fdset/N — fd-only)
  remove-fd       (release monitor's ref; new file holds the dup)
  blockdev-reopen (format node, file = new file node-name)
  blockdev-del    (old file node; its dup release frees old fdset)

The reopen options must restate every option the original blockdev-
add emitted on the format node — blockdev-reopen resets any
unspecified option to its driver default. The 'file' field is a
node-name string reference, never a path.

No new errors and no new IDL types beyond the method itself;
everything is built on the existing NoSuchStorage / StorageImmutable
/ NotConnected / EBUSY vocabulary.

The series is:

  vmspawn: split blockdev-add into separate file and format calls
      Preparatory refactor. qemu/blockdev.c:3440 only marks the
      top-level BDS returned by blockdev-add as monitor-owned;
      inline children are NOT, so blockdev-del later rejects them
      with "Node X is not owned by the monitor". Split into two
      blockdev-add calls so the file node is independently
      deletable. DriveInfo gains qmp_file_node_name and a
      file_generation counter; the teardown helper deletes format
      then file (file-first is rejected as "node used as 'file'
      of Y"). The ephemeral path was already structured this way;
      only the regular add path changes. Drops the now-unused
      qmp_build_blockdev_add_inline().

  shared/varlink-io.systemd.MachineInstance: add ReplaceStorage method
      IDL only: ReplaceStorage(fileDescriptorIndex, name). No new
      errors.

  vmspawn: implement io.systemd.MachineInstance.ReplaceStorage
      vmspawn_qmp_replace_block_device() entry point, ReplaceCtx
      (refcounted, ReplaceCtxStateFlags for partial-state tracking)
      and four async callbacks plus an idempotent replace_fail.
      file_generation is bumped before issuing blockdev-add so
      retries don't collide on node-name.
      BLOCK_DEVICE_STATE_REPLACE_PENDING gates concurrent
      Replace / Remove on the same drive. On reopen success the
      trailing blockdev-del of the old file node fires from the
      reopen callback; its failure logs a warning and still replies
      success (the swap already committed; the orphan resolves at VM
      exit). QMP disconnect mid-replace routes via
      qmp_client_fail_pending → replace_fail → NotConnected.

  test: integration test for io.systemd.MachineInstance.ReplaceStorage
      TEST-87-AUX-UTILS-VM.replace-storage covers happy-path replace,
      successive replaces (file_generation rotation), StorageImmutable
      rejection on the boot-time drive, NoSuchStorage on unknown
      names, InvalidParameter on malformed names, and clean
      RemoveStorage after a replace (proves the new file node is
      monitor-owned and the teardown order works). Backing files are
      passed via 'varlinkctl --push-fd'; no machinectl front-end is
      added in this round.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-05-13 08:48:38 +02:00
Zbigniew Jędrzejewski-Szmek 735a5c10c5 report-basic: expose os-release fields as a metric (#41988)
Add io.systemd.Basic.OSRelease metric family that reports all the fields
in os-release.
2026-05-13 08:07:27 +02:00
Yu Watanabe 3d66a4550a dhcp: random trivial cleanups (#42061) 2026-05-13 08:15:11 +09:00
Frantisek Sumsal 7cecff8c99 sd-bus: handle non-string keys in dictionaries in JSON dump
JSON only supports string keys in objects, but D-Bus specification is a
bit more lenient and allows dict entries to have any basic type as key.
Let's stringify allowed non-string keys so that we can represent them as
JSON objects.

Relevant snippet from the D-Bus specification:

  A DICT_ENTRY works exactly like a struct, but rather than parentheses
  it uses curly braces, and it has more restrictions. The restrictions
  are: it occurs only as an array element type; it has exactly two
  single complete types inside the curly braces; the first single
  complete type (the "key") must be a basic type rather than a container
  type. Implementations must not accept dict entries outside of arrays,
  must not accept dict entries with zero, one, or more than two fields,
  and must not accept dict entries with non-basic-typed keys. A dict
  entry is always a key-value pair.

Resolves: #32904
2026-05-13 07:50:32 +09:00
Yu Watanabe 304899fa57 sd-dhcp-client: always set default broadcast hardware address when unspecified
The default value for InfiniBand is copied from dhcp-network.c.
2026-05-13 07:47:53 +09:00
Yaping Li eda10260a0 logind: zero-initialize dispatch struct in vl_method_release_session()
The local struct passed to sd_varlink_dispatch() was not
zero-initialized. Since sd_json_dispatch_full() does not call handlers
for absent optional fields, p.id could be left indeterminate when
the client omits the Id parameter, leading to use of uninitialized
memory.
2026-05-13 07:47:18 +09:00
Zbigniew Jędrzejewski-Szmek a117488d35 report-cgroup: use errno_or_else in one more place
Old gcc is confused about initialization:
In function ‘io_read_send’,
    inlined from ‘walk_cgroups’ at ../src/report/report-cgroup.c:288:24:
../src/report/report-cgroup.c:167:21: error: ‘values[0]’ may be used uninitialized [-Werror=maybe-uninitialized]
  167 |                 r = metric_build_send_unsigned(mf + i, link, unit, values[i], /* fields= */ NULL);
      |                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Maybe this helps.
2026-05-12 22:56:06 +02:00
Zbigniew Jędrzejewski-Szmek e27c382bf0 report-basic: expose os-release fields as metrics
Add io.systemd.Basic.OSRelease metric families that reports select fields
from os-release.

$ cat /etc/os-release
NAME="Fedora Linux"
VERSION="45 (Cloud Edition Prerelease)"
RELEASE_TYPE=development
ID=fedora
VERSION_ID=45
VERSION_CODENAME=""
PRETTY_NAME="Fedora Linux 45 (Cloud Edition Prerelease)"
ANSI_COLOR="0;38;2;60;110;180"
LOGO=fedora-logo-icon
CPE_NAME="cpe:/o:fedoraproject:fedora:45"
HOME_URL="https://fedoraproject.org/"
DOCUMENTATION_URL="https://docs.fedoraproject.org/en-US/fedora/rawhide/"
SUPPORT_URL="https://ask.fedoraproject.org/"
BUG_REPORT_URL="https://bugzilla.redhat.com/"
REDHAT_BUGZILLA_PRODUCT="Fedora"
REDHAT_BUGZILLA_PRODUCT_VERSION=rawhide
REDHAT_SUPPORT_PRODUCT="Fedora"
REDHAT_SUPPORT_PRODUCT_VERSION=rawhide
SUPPORT_END=2027-11-24
VARIANT="Cloud Edition"
VARIANT_ID=cloud

$ varlinkctl call --more ./build/systemd-report-basic io.systemd.Metrics.List {} | jq --seq -c
...
{"name":"io.systemd.Basic.OSRelease.NAME","value":"Fedora Linux 44 (Workstation Edition)"}
{"name":"io.systemd.Basic.OSRelease.ID","value":"fedora"}
{"name":"io.systemd.Basic.OSRelease.CPE_NAME","value":"cpe:/o:fedoraproject:fedora:44"}
{"name":"io.systemd.Basic.OSRelease.VARIANT_ID","value":"workstation"}
{"name":"io.systemd.Basic.OSRelease.VERSION_ID","value":"44"}
{"name":"io.systemd.Basic.OSRelease.SUPPORT_END","value":"2027-05-19"}

I picked the fields that contain useful information about the specific
version/image/variant/experiment/flavour of the system. Also, either
NAME or PRETTY_NAME is included. This one is intended for human readers
to be able to identify the OS version easily.
2026-05-12 22:56:06 +02:00
Zbigniew Jędrzejewski-Szmek 5cba9704ad report: drop MetricsFamilyContext, CGroupContext, CGroupInfo
Previously, we passed around information about the MetricFamily'ies
and the varlink connection in a helper structure. Having a hybrid of
const static and runtime stuff is iffy. Let's simplify things by passing
two separate parameters.

Also, in report-cgroup.c we built a cache of parsed values. This
requires additional storage requirements and introduces complexity when
dealing with population of the cache at the appropriate time.
This cache is not useful: for each cgroup, we generate a list of
metrics, and we have all the information at hand. The only reason
why we'd create the cache and not generate all the relevant replies
at once was that the helper functions called the .generate function
for each MetricFamily separately.

The MetricFamily interface is changed, so that metrics can be
defined without a .generate function. This is understood to mean
that the preceding metric family's .generate function will also
genarate this family. This allows us to define related metrics
nicely in a table:
  { METRIC_IO_SYSTEMD_CGROUP_PREFIX "CpuUsage", generate_func },
  { METRIC_IO_SYSTEMD_CGROUP_PREFIX "IOReadBytes", NULL },
  { METRIC_IO_SYSTEMD_CGROUP_PREFIX "IOReadOperations", NULL },
  { METRIC_IO_SYSTEMD_CGROUP_PREFIX "SomethingElse", generate_func2 },
  ...
When implementing .Describe, we list all the families. When implementing
.List, we only call those with .generate, and we get the same results
as before.

This allows the .generate functions to be simplified: instead of
keeping state, they just spit out all the metrics for a given
object in a tight loop.
2026-05-12 22:56:04 +02:00
Christian Brauner 91575e3a5a varlink-io.systemd.MachineInstance,vmspawn: treat AddStorage/RemoveStorage name as opaque
The 'name' field on AddStorage and RemoveStorage was documented as
'<provider>:<volume>' and enforced via machine_storage_name_split() at
the varlink boundary. That form is only the convention machinectl
inherits from the StorageProvider routing path; the API itself only
needs a unique identifier the caller can re-use to detach the binding.

Drop the strict format check, require only a non-empty string, and
update the IDL docs to describe the field as a caller-supplied
identifier with machinectl's convention as a non-normative example.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-05-12 22:54:08 +02:00
Christian Brauner 968d189414 vmspawn: reject O_PATH and O_WRONLY fds in AddStorage
An fd opened O_PATH cannot be read, and an O_WRONLY fd cannot serve as
a backing file for a virtual disk image. Reject both at the bind-volume
entry point with -EBADF instead of letting the request proceed to QMP
where QEMU's file backend would fail to read from the fd. The
ReplaceStorage entry point grew the same checks in parallel.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-05-12 22:54:07 +02:00
Christian Brauner 1360117a64 test: integration test for io.systemd.MachineInstance.ReplaceStorage
Modelled on TEST-87-AUX-UTILS-VM.bind-volume.sh. Boots vmspawn with
one boot-time bind-volume, hot-adds a runtime volume via machinectl
bind-volume, then exercises ReplaceStorage:

  1. happy-path replace of a runtime drive
  2. successive replace (verify file_generation rotation — no
     node-name collisions on the second swap)
  3. replace of the boot-time drive must fail with StorageImmutable
  4. replace of an unknown name must fail with NoSuchStorage
  5. invalid name (no provider:volume separator) must fail with
     InvalidParameter
  6. unbind-volume after replace must succeed — proves the new file
     node is monitor-owned and the format-then-file teardown order
     in vmspawn_qmp_block_device_teardown() correctly cleans up both
     blockdev nodes

Pushes the new backing file via varlinkctl --push-fd; the file is a
plain truncate'd image. Auto-discovered by run_subtests in
TEST-87-AUX-UTILS-VM.sh.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-05-12 22:54:07 +02:00
Christian Brauner b9155f789c vmspawn: implement io.systemd.MachineInstance.ReplaceStorage
Wire up the runtime hot-swap Varlink method. The signature mirrors
AddStorage minus 'config': the device frontend (virtio-blk,
virtio-scsi, nvme, scsi-cd) doesn't change, only the backing file
behind it. Read-only/read-write may flip based on the new fd's
O_ACCMODE; scsi-cd is forced read-only to match the boot-time policy.

QMP sequence (entry: vmspawn_qmp_replace_block_device):

  add-fd                          → on_replace_observe_stage
  blockdev-add (new file)         → on_replace_blockdev_add_complete
  remove-fd (new fdset)           → on_replace_observe_stage
  blockdev-reopen (format)        → on_replace_blockdev_reopen_complete
                                    [commit + fire trailing del]
  blockdev-del (old file)         → on_replace_old_blockdev_del_complete

The reopen options must be a superset of every option that
qmp_build_blockdev_add_format() may emit, otherwise reopen rejects
'Cannot reset option X to default'. The 'file' field is a string
reference to the new file node — case 3 of the schema in
qemu/qapi/block-core.json:5034-5040 ("the current child is replaced
with that other node"). The format node's qmp_node_name is preserved
so the device frontend's drive=<X> binding does not move.

ReplaceCtx tracks the per-call state with a refcount mirroring the
add-stage drive-info pattern. On any pre-commit failure replace_fail
tears down whatever new-side state we created on the wire and replies
on drive->link via reply_qmp_error (disconnect → NotConnected). On
post-commit del failure we log a warning, leak the orphan, and reply
success — the swap itself succeeded and the leak resolves at VM exit.

file_generation is bumped before issuing blockdev-add so failed
attempts cannot collide on node-name when the user retries.

Errors:
  NoSuchStorage     - drive not in the registry
  StorageImmutable  - drive lacks QMP_DRIVE_REMOVABLE (boot-time)
  EBUSY             - add still pending or another replace/remove in flight
  NotConnected      - QMP transport disconnect during the chain
  EIO               - QEMU rejected blockdev-reopen

Also gates RemoveStorage on REPLACE_PENDING so a device_del cannot
race a mid-flight blockdev-reopen on the same drive.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-05-12 22:54:07 +02:00
Christian Brauner 3063448b51 shared/varlink-io.systemd.MachineInstance: add ReplaceStorage method
Define the IDL for io.systemd.MachineInstance.ReplaceStorage, a
runtime hot-swap of an already-attached storage volume's backing
file. The signature mirrors AddStorage minus the 'config' field
because the device frontend (virtio-blk, virtio-scsi, nvme, scsi-cd)
does not change — only the backing file behind it.

The implementation lives in vmspawn (next commit) and uses QMP
blockdev-reopen to swap the file child of the existing format node.
The reused error vocabulary (NoSuchStorage, StorageImmutable,
NotConnected, plus the generic errno path) covers every failure
mode; no new errors are added.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-05-12 22:54:07 +02:00
Christian Brauner 8dc5dbe3c0 vmspawn: split blockdev-add into separate file and format calls
The current vmspawn_qmp_add_block_device() emits a single blockdev-add
that combines the format-level node ("vmspawn-N-storage") with an
inline file child. QEMU's qmp_blockdev_add() only marks the top-level
returned BDS as monitor-owned (qemu/blockdev.c:3440); inline children
are NOT, so qmp_blockdev_del() rejects them with "Node X is not owned
by the monitor" (qemu/blockdev.c:3513-3517).

To prepare for ReplaceStorage — which needs to swap the file child of
an existing format node via blockdev-reopen, and then blockdev-del the
old file node — make the file node monitor-owned by issuing it as its
own blockdev-add call. The 4-stage add chain becomes 5 stages:

  add-fd
  blockdev-add (file)    → on_add_file_node_stage   sets FILE_NODE_ADDED
  blockdev-add (format)  → on_add_format_node_stage sets BLOCKDEV_ADDED
  remove-fd
  device_add

DriveInfo gains qmp_file_node_name ("vmspawn-N-file-G", G a generation
counter bumped on every replace), file_generation, and a stashed
fdset_id so future ReplaceStorage can target both for cleanup.

vmspawn_qmp_block_device_teardown() now deletes both nodes in order —
format first, then file — because the format holds a strong reference
to its file child and a file-first del is rejected with "Node X is
busy: node is used as 'file' of Y".

Folds bridge->features VMSPAWN_QMP_FEATURE_IO_URING into the file
node's flags so the new path inherits io_uring just like the old
inline form did. The format-level options (read-only, discard,
discard-no-unref) are unchanged.

The ephemeral path is structurally already separate file+format with
monitor-owned children; no behavioural change there beyond the
on_add_blockdev_stage → on_add_format_node_stage rename.

Drops the now-unused qmp_build_blockdev_add_inline() helper.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-05-12 22:54:07 +02:00
Yu Watanabe 98d061e28b TODO: fix typo 2026-05-13 05:34:21 +09:00
Daan De Meyer 53f0ac20b2 repart: Add BtrfsReplace= (#41109)
This is a series of commits which adds a feature needed by GNOME OS'
installer. This was show during All Systems Go 2025 talk:
https://cfp.all-systems-go.io/all-systems-go-2025/talk/QRJVL3/

To sum up this PR, this changes first systemd-repart to use BLKPG
partition instead of loop devices when possible. We need then to always
rescan the partitions to try remove partitions if it failed. We allow
encrypted partitions to stay activated and with a chosen name. And we
add a new partition configuration `BtrfsReplace=`.

Note that "replace" comes from the command `btrfs replace`. But in the
case of systemd-repart, maybe "inplace" or "move" would make more sense.
I open to suggestions.

If it is better I can split this into several PRs.

The commits:

## repart: Reuse the backing fd for fdisk

Because fdisk_assign_device tries to open block devices with O_EXCL,
when it does it blocks cryptsetup from using partition block devices for
the same disk.

Since we already have a file descriptor for the device, we can just
share it and use fdisk_assign_device_by_fd instead.

## repart: Use blkpg partitions instead of loop devices when possible

We will want to allow future features to keep some devices mounted or
active. So in order to avoid leaving a mess of many loop devices, we can
just already use the partition block device already.

## repart: Rescan disk on failure if we create blkpg partitions on the
fly

Since we did not write the partition table, then the created partitions
should get removed on error.

## repart: Allow keeping luks2 volumes opened

## repart: Add BtrfsReplace=

BtrfsReplace=/mntpnt will move the btrfs filesystem from mount point to
the partition created. After moving, it will resize to take the whole
partition.
This is useful for OS installers that move a live system into a disk and
do not require a reboot.

## repart: Add VolumeName=

When a luks2 device mapper is to be kept alive after execution of
systemd-cryptsetup, the name of the volume will be taken from this
value.

## test: Add test for repart's BtrfsReplace
2026-05-12 22:24:51 +02:00
Yu Watanabe d5244e1df5 test: split unit tests (#42062) 2026-05-13 04:54:57 +09:00
Daan De Meyer 408d474dfa vmspawn: Prefer systemd-journal-remote from $PATH
$PATH might point to a systemd checkout containing
a newer version of systemd-journal-remote which we
should use, hence prefer an executable from $PATH
over the one from /usr/lib/systemd.
2026-05-12 20:52:18 +02:00
Daan De Meyer 42f2970f89 Convert journalctl to option macros (#42051) 2026-05-12 20:42:39 +02:00
Yu Watanabe c28ec168aa test: move test cases for client_id_{hash,compare}_func() to test-dhcp-client-id.c 2026-05-13 03:02:37 +09:00
Yu Watanabe 000eb0f908 test: move unit test for dhcp_identifier_set_iaid() to test-dhcp-duid.c 2026-05-13 03:02:24 +09:00
Yu Watanabe bcc7755438 dhcp-network: make dhcp_network_send_{raw,udp}_socket() take iovec_wrapper 2026-05-13 02:59:00 +09:00
Yu Watanabe 2f8348e352 dhcp: introduce sd_dhcp_message object and several related functions (part 1) (#42047) 2026-05-13 02:58:20 +09:00
Luca Boccassi 9f08885b0e test: make TEST-75-RESOLVED robust against journald metadata race
Even after switching the wait loop to a polling `journalctl --grep`, the
test still fails intermittently because the very first messages emitted by
the freshly-spawned systemd-networkd-wait-online process can carry stale
journald metadata. journald associates `_SYSTEMD_UNIT=` (and friends) with
each entry by reading `/proc/$pid/cgroup` of the originating PID; if those
messages are produced before journald notices the cgroup migration into the
new service, they get tagged with `_SYSTEMD_UNIT=init.scope`. The
`-u $unit` filter then fails to match them.

Capture a journal cursor before launching the unit, and grep using
`--after-cursor=` plus `SYSLOG_IDENTIFIER=systemd-networkd-wait-online`
instead of `-u $unit`. SYSLOG_IDENTIFIER is set by the program itself, so
it's not subject to the cgroup-discovery race. The cursor bounds the search
to entries produced by this invocation, so prior wait-online runs in
earlier testcases don't interfere.

Logs from the failing run showing the messages exist but are tagged with
the wrong unit:

  [ 2570.948554] TEST-75-RESOLVED.sh[2178]: + unit=wait-online-dns-ede81407-b93b-459d-8e5d-69292b42d2ae.service
  [ 2571.023162] TEST-75-RESOLVED.sh[2178]: + systemd-run -u wait-online-dns-ede81407-b93b-459d-8e5d-69292b42d2ae.service ...
  [ 2571.049189] TEST-75-RESOLVED.sh[2178]: + timeout 30 bash -c 'until journalctl -b -u wait-online-dns-ede81407-b93b-459d-8e5d-69292b42d2ae.service --grep ...'
  [ 2571.964986] systemd-networkd-wait-online[2190]: dns0: No DNS server is accessible.
  [ 2601.051088] TEST-75-RESOLVED.sh[2178]: ++ cleanup

And for that 2571.964986 entry:

      _SYSTEMD_CGROUP=/init.scope
      _SYSTEMD_UNIT=init.scope
      _EXE=/usr/lib/systemd/systemd-executor
      _CMDLINE=/usr/lib/systemd/systemd-executor --deserialize 68 ...
      SYSLOG_IDENTIFIER=systemd-networkd-wait-online
      MESSAGE=dns0: No DNS server is accessible.

Follow-up for d4bc62713e

Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-12 18:30:28 +01:00
Yu Watanabe d56adae624 copy: fix typo and slightly update comment 2026-05-13 02:04:33 +09:00
Yu Watanabe 3c5bb1f352 option: fix typo 2026-05-13 01:57:12 +09:00
Yu Watanabe 47eb11e4c2 po: update Japanese translation 2026-05-13 01:51:48 +09:00
Daan De Meyer d0234450b6 json-stream: tolerate truncated SCM_RIGHTS on inbound messages
When an LSM (e.g. SELinux) denies an fd transfer or the receiver hits
RLIMIT_NOFILE, the kernel drops the fd(s) from the SCM_RIGHTS cmsg and
sets MSG_CTRUNC on the recvmsg(). recvmsg_safe() turns that into
-ECHRNG, which causes json_stream_read() to discard the data bytes
that were nevertheless received and the varlink server to silently
tear down the connection — leaving the caller waiting for a reply
that never comes.

Inline the recvmsg() call instead and, on MSG_CTRUNC, drop the partial
fds but keep the message data. The method handler will surface a clean
-ENXIO when it tries to peek the missing fd, which sd-varlink wraps as
io.systemd.System for the peer, instead of a hang. This matches the
recent sd-bus fix in 6c8de404c9 ('sd-bus: allow receiving messages with
MSG_CTRUNC set').
2026-05-12 18:54:28 +02:00
Lennart Poettering 183ce1da4e update TODO 2026-05-12 18:49:43 +02:00
Valentin David 120f906c8b test: Add test for repart's BlockDeviceReplace 2026-05-12 18:31:27 +02:00
Valentin David 4021f565e2 repart: Add VolumeName=
When a luks2 device mapper is to be kept alive after execution
of systemd-cryptsetup, the name of the volume will be taken
from this value.
2026-05-12 18:31:26 +02:00
Valentin David c07fcbb507 repart: Add BlockDeviceReplace=
BlockDeviceReplace=/mntpnt will move the btrfs filesystem from mount point to
the partition created. After moving, it will resize to take the whole
partition.

This is useful for OS installers that move a live system into a disk and
do not require a reboot.
2026-05-12 18:31:25 +02:00
Valentin David 77b15343bc repart: Allow keeping luks2 volumes opened 2026-05-12 18:31:24 +02:00
Valentin David d0d00297a4 repart: Rescan disk on failure if we create blkpg partitions on the fly
Since we did not write the partition table, then the created partitions
should get removed on error.
2026-05-12 18:31:23 +02:00
Valentin David 0ef0824201 repart: Use blkpg partitions instead of loop devices when possible
We will want to allow future features to keep some devices mounted or
active. So in order to avoid leaving a mess of many loop devices, we can
just already use the partition block device already.
2026-05-12 18:31:22 +02:00
Valentin David 3ac8bd0e97 repart: Reuse the backing fd for fdisk
Because fdisk_assign_device tries to open block devices with O_EXCL, when it
does it blocks cryptsetup from using partition block devices for the same
disk.

Since we already have a file descriptor for the device, we can just share it
and use fdisk_assign_device_by_fd instead.

This requires at least libfdisk 2.35 (part of util-linux) which was
released in 2020.
2026-05-12 18:31:21 +02:00
Bone NI ee2c2b1b89 po: Translated using Weblate (Lao)
Currently translated at 100.0% (266 of 266 strings)

po: Added translation using Weblate (Lao)

Co-authored-by: Bone NI <bounkirdni@gmail.com>
Translate-URL: https://translate.fedoraproject.org/projects/systemd/main/lo/
Translation: systemd/main
2026-05-12 18:01:20 +02:00
Yu Watanabe 74f3cc4576 sd-dhcp-server-lease: rename dhcp_server_lease_append_json() -> dhcp_server_lease_build_json()
It does not append, but build a new JSON variant.
2026-05-13 00:48:13 +09:00
Yu Watanabe 9179cb31ed sd-dhcp-server: coding style fix 2026-05-13 00:47:48 +09:00
Yu Watanabe f51e7eeb7c fuzz: modernize fuzz-dhcp-server
- Do not include .c file.
- Use ASSERT_OK() and friends.
2026-05-13 00:47:03 +09:00
Yu Watanabe e507487b6d dhcp-protocol: introduce more sub-options for DHCP Relay Agent Information option
These new values will be used later.
2026-05-13 00:46:09 +09:00
Yu Watanabe 25482d832c sd-dhcp-lease: drop sd_dhcp_lease.have_subnet_mask and have_broadcast
NULL address is invalid in both cases. Let's refuse to use them when NULL.
2026-05-13 00:43:00 +09:00
Yu Watanabe 28423ea18c dhcp-message: introduce dhcp_message_{append,get}_option_hostname() and related functions
These are for DHCP options 12 (Hostname) and 81 (FQDN) options.
2026-05-13 00:27:49 +09:00
Yu Watanabe aa9584a037 dhcp-message: introduce dhcp_message_{append,get}_option_parameter_request_list()
These are for DHCP option 55 (parameter request list).
2026-05-13 00:27:49 +09:00
Yu Watanabe a6a6e371f7 dhcp-message: introduce dhcp_message_{append,get}_option_client_id()
These are for DHCP option 61 (client ID).
2026-05-13 00:27:49 +09:00
Yu Watanabe 1c4ee9e969 dhcp-message: introduce dhcp_message_{append,get}_option_string()
These are for DHCP options that takes a string e.g. DHCP options
17 (root path), 60 (vendor class identifier), and so on.
2026-05-13 00:27:49 +09:00
Yu Watanabe 174a61135c dhcp-message: introduce dhcp_message_{append,get}_option_addresses()
These functions support multiple addresses.

These are for e.g. DHCP options 6 (DNS servers), 42 (NTP servers) and so on.
2026-05-13 00:27:49 +09:00