summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/differential-shellcheck.yml2
-rw-r--r--.github/workflows/issue_labeler.yml2
-rw-r--r--.github/workflows/mkosi.yml2
-rw-r--r--NEWS76
-rw-r--r--TODO2
-rw-r--r--docs/PORTABILITY_AND_STABILITY.md6
-rw-r--r--hwdb.d/60-evdev.hwdb8
-rw-r--r--hwdb.d/60-sensor.hwdb2
-rw-r--r--man/custom-entities.ent.in3
-rw-r--r--man/event-quick-child.c3
-rw-r--r--man/hwdb-usb-device.c7
-rw-r--r--man/journal-enumerate-fields.c3
-rw-r--r--man/journal-iterate-foreach.c7
-rw-r--r--man/journal-iterate-poll.c1
-rw-r--r--man/journal-iterate-unique.c6
-rw-r--r--man/journal-iterate-wait.c15
-rw-r--r--man/journal-stream-fd.c8
-rw-r--r--man/kernel-command-line.xml17
-rw-r--r--man/logcontrol-example.c50
-rw-r--r--man/meson.build86
-rw-r--r--man/notify-selfcontained-example.c188
-rw-r--r--man/org.freedesktop.portable1.xml5
-rw-r--r--man/path-documents.c2
-rw-r--r--man/print-unit-path-call-method.c3
-rw-r--r--man/print-unit-path.c3
-rw-r--r--man/repart.d.xml16
-rw-r--r--man/rules/meson.build2
-rw-r--r--man/sd-bus-container-append.c3
-rw-r--r--man/sd-journal.xml11
-rw-r--r--man/sd_bus_error-example.c4
-rw-r--r--man/sd_bus_service_reconnect.c140
-rw-r--r--man/sd_notify.xml11
-rw-r--r--man/systemd-debug-generator.xml32
-rw-r--r--man/systemd-hibernate-resume.service.xml8
-rw-r--r--man/systemd-sleep.conf.xml40
-rw-r--r--man/systemd-system.conf.xml10
-rw-r--r--man/systemd.service.xml12
-rw-r--r--man/systemd.system-credentials.xml10
-rw-r--r--man/tmpfiles.d.xml4
-rw-r--r--man/vtable-example.c75
-rw-r--r--meson.build15
-rw-r--r--meson_options.txt2
-rw-r--r--mkosi.conf2
-rw-r--r--mkosi.images/system/mkosi.conf2
-rw-r--r--mkosi.images/system/mkosi.conf.d/10-arch/mkosi.conf5
-rw-r--r--mkosi.images/system/mkosi.conf.d/10-centos-fedora/mkosi.conf7
-rwxr-xr-xmkosi.images/system/mkosi.conf.d/10-debian-ubuntu/mkosi.build.chroot2
-rw-r--r--mkosi.images/system/mkosi.conf.d/10-debian-ubuntu/mkosi.conf5
-rw-r--r--mkosi.images/system/mkosi.conf.d/10-opensuse/mkosi.conf3
-rw-r--r--mkosi.images/system/mkosi.conf.d/10-ubuntu/mkosi.conf5
m---------pkg/centos0
m---------pkg/debian0
-rw-r--r--rules.d/99-systemd.rules.in13
-rw-r--r--src/backlight/backlight.c4
-rw-r--r--src/basic/dlfcn-util.c2
-rw-r--r--src/basic/efivars.c11
-rw-r--r--src/basic/gcrypt-util.c110
-rw-r--r--src/basic/gcrypt-util.h50
-rw-r--r--src/basic/meson.build19
-rw-r--r--src/basic/signal-util.c2
-rw-r--r--src/basic/socket-util.c2
-rw-r--r--src/basic/string-util.c16
-rw-r--r--src/basic/string-util.h2
-rw-r--r--src/basic/time-util.h4
-rw-r--r--src/basic/unit-def.c14
-rw-r--r--src/core/automount.c4
-rw-r--r--src/core/cgroup.c2
-rw-r--r--src/core/dbus-manager.c10
-rw-r--r--src/core/device.c3
-rw-r--r--src/core/emergency-action.c30
-rw-r--r--src/core/exec-invoke.c27
-rw-r--r--src/core/execute-serialize.c8
-rw-r--r--src/core/execute.c62
-rw-r--r--src/core/main.c4
-rw-r--r--src/core/manager-serialize.c3
-rw-r--r--src/core/manager.c41
-rw-r--r--src/core/manager.h4
-rw-r--r--src/core/mount.c87
-rw-r--r--src/core/scope.c10
-rw-r--r--src/core/service.c107
-rw-r--r--src/core/slice.c4
-rw-r--r--src/core/socket.c33
-rw-r--r--src/core/swap.c18
-rw-r--r--src/core/target.c4
-rw-r--r--src/core/timer.c6
-rw-r--r--src/core/unit.c28
-rw-r--r--src/cryptsetup/cryptsetup-tokens/luks2-tpm2.h2
-rw-r--r--src/cryptsetup/cryptsetup.c2
-rw-r--r--src/debug-generator/debug-generator.c92
-rw-r--r--src/hibernate-resume/hibernate-resume-config.c35
-rw-r--r--src/hibernate-resume/hibernate-resume-config.h31
-rw-r--r--src/hibernate-resume/hibernate-resume.c126
-rw-r--r--src/home/homed-manager.c5
-rw-r--r--src/import/pull-job.c4
-rw-r--r--src/journal/journalctl-authenticate.c8
-rw-r--r--src/journal/meson.build1
-rwxr-xr-xsrc/kernel-install/90-loaderentry.install.in4
-rw-r--r--src/libsystemd-network/fuzz-ndisc-rs.c2
-rw-r--r--src/libsystemd-network/icmp6-util.c1
-rw-r--r--src/libsystemd-network/meson.build1
-rw-r--r--src/libsystemd-network/ndisc-neighbor-internal.h21
-rw-r--r--src/libsystemd-network/sd-ndisc-neighbor.c126
-rw-r--r--src/libsystemd-network/sd-ndisc.c40
-rw-r--r--src/libsystemd-network/test-ndisc-rs.c120
-rw-r--r--src/libsystemd/sd-journal/fsprg.c193
-rw-r--r--src/libsystemd/sd-journal/fsprg.h10
-rw-r--r--src/libsystemd/sd-journal/journal-authenticate.c68
-rw-r--r--src/libsystemd/sd-journal/journal-file.c9
-rw-r--r--src/libsystemd/sd-journal/journal-verify.c3
-rw-r--r--src/login/logind-dbus.c7
-rw-r--r--src/login/logind.c10
-rw-r--r--src/network/generator/main.c6
-rw-r--r--src/network/generator/network-generator.c158
-rw-r--r--src/network/meson.build3
-rw-r--r--src/network/networkd-link.c12
-rw-r--r--src/network/networkd-ndisc.c159
-rw-r--r--src/network/networkd-state-file.c2
-rw-r--r--src/nspawn/nspawn-network.c2
-rw-r--r--src/partition/meson.build1
-rw-r--r--src/partition/repart.c140
-rw-r--r--src/resolve/meson.build1
-rw-r--r--src/resolve/resolved-dns-dnssec.c23
-rw-r--r--src/resolve/resolved-varlink.c2
-rw-r--r--src/shared/bpf-dlopen.c11
-rw-r--r--src/shared/btrfs-util.c18
-rw-r--r--src/shared/btrfs-util.h2
-rw-r--r--src/shared/hibernate-util.c10
-rw-r--r--src/shared/hibernate-util.h2
-rw-r--r--src/shared/idn-util.c5
-rw-r--r--src/shared/meson.build1
-rw-r--r--src/shared/pkcs11-util.c4
-rw-r--r--src/shared/ptyfwd.c2
-rw-r--r--src/shared/serialize.c22
-rw-r--r--src/shared/sleep-config.c45
-rw-r--r--src/shared/sleep-config.h22
-rw-r--r--src/shared/tpm2-util.c2
-rw-r--r--src/shared/udev-util.c21
-rw-r--r--src/shared/udev-util.h2
-rw-r--r--src/shared/userdb.c2
-rw-r--r--src/shared/watchdog.c16
-rw-r--r--src/sleep/sleep.c32
-rw-r--r--src/sleep/sleep.conf1
-rw-r--r--src/ssh-generator/ssh-generator.c4
-rw-r--r--src/storagetm/storagetm.c5
-rw-r--r--src/sysext/sysext.c3
-rw-r--r--src/systemctl/meson.build3
-rw-r--r--src/systemd/meson.build1
-rw-r--r--src/systemd/sd-bus-vtable.h8
-rw-r--r--src/systemd/sd-ndisc-neighbor.h50
-rw-r--r--src/systemd/sd-ndisc.h2
-rw-r--r--src/sysupdate/sysupdate-transfer.c1
-rw-r--r--src/sysusers/meson.build1
-rw-r--r--src/test/test-dirent-util.c4
-rw-r--r--src/test/test-dlopen-so.c5
-rw-r--r--src/test/test-sleep-config.c8
-rw-r--r--src/test/test-string-util.c14
-rw-r--r--src/timesync/meson.build3
-rw-r--r--src/tmpfiles/meson.build1
-rw-r--r--src/udev/meson.build2
-rw-r--r--src/udev/net/link-config.c58
-rw-r--r--src/udev/net/link-config.h3
-rw-r--r--src/udev/test-udev-rule-runner.c2
-rw-r--r--src/udev/test-udev-spawn.c2
-rw-r--r--src/udev/udev-builtin-blkid.c68
-rw-r--r--src/udev/udev-builtin-btrfs.c6
-rw-r--r--src/udev/udev-builtin-hwdb.c31
-rw-r--r--src/udev/udev-builtin-input_id.c89
-rw-r--r--src/udev/udev-builtin-keyboard.c7
-rw-r--r--src/udev/udev-builtin-kmod.c7
-rw-r--r--src/udev/udev-builtin-net_driver.c4
-rw-r--r--src/udev/udev-builtin-net_id.c92
-rw-r--r--src/udev/udev-builtin-net_setup_link.c10
-rw-r--r--src/udev/udev-builtin-path_id.c18
-rw-r--r--src/udev/udev-builtin-uaccess.c7
-rw-r--r--src/udev/udev-builtin-usb_id.c54
-rw-r--r--src/udev/udev-builtin.c16
-rw-r--r--src/udev/udev-builtin.h12
-rw-r--r--src/udev/udev-event.c105
-rw-r--r--src/udev/udev-event.h16
-rw-r--r--src/udev/udev-rules.c37
-rw-r--r--src/udev/udev-spawn.c12
-rw-r--r--src/udev/udev-worker.c2
-rw-r--r--src/udev/udevadm-test-builtin.c4
-rw-r--r--src/udev/udevadm-test.c89
-rw-r--r--src/udev/udevadm-wait.c2
-rw-r--r--src/vmspawn/vmspawn.c2
-rwxr-xr-xtest/TEST-54-CREDS/test.sh15
-rw-r--r--test/test-functions4
-rwxr-xr-xtest/test-network-generator-conversion.sh2
-rw-r--r--test/test-network/conf/25-dhcp-server-veth-peer.network2
-rwxr-xr-xtest/units/end.sh4
-rwxr-xr-xtest/units/testsuite-08.sh2
-rwxr-xr-xtest/units/testsuite-17.link-property.sh8
-rwxr-xr-xtest/units/testsuite-43.sh2
-rwxr-xr-xtest/units/testsuite-46.sh2
-rwxr-xr-xtest/units/testsuite-50.sh20
-rwxr-xr-xtest/units/testsuite-54.sh17
-rwxr-xr-xtest/units/testsuite-55.sh2
-rwxr-xr-xtest/units/testsuite-58.sh2
-rwxr-xr-xtest/units/testsuite-59.sh8
-rwxr-xr-xtest/units/testsuite-62.sh4
-rwxr-xr-xtest/units/testsuite-72.sh2
-rwxr-xr-xtest/units/testsuite-74.coredump.sh26
-rw-r--r--tmpfiles.d/20-systemd-ssh-generator.conf.in3
-rwxr-xr-xtools/git-contrib.sh12
-rw-r--r--units/meson.build5
-rw-r--r--units/systemd-hibernate-clear.service.in24
-rw-r--r--units/systemd-networkd-persistent-storage.service1
208 files changed, 3134 insertions, 1230 deletions
diff --git a/.github/workflows/differential-shellcheck.yml b/.github/workflows/differential-shellcheck.yml
index 3db0e79528..948372ee96 100644
--- a/.github/workflows/differential-shellcheck.yml
+++ b/.github/workflows/differential-shellcheck.yml
@@ -28,7 +28,7 @@ jobs:
fetch-depth: 0
- name: Differential ShellCheck
- uses: redhat-plumbers-in-action/differential-shellcheck@b9df2a9417f69c056e0aeaf870abd9a2065a403e
+ uses: redhat-plumbers-in-action/differential-shellcheck@c15070885a82a2c93db8a765d332c38c50dde8b3
with:
# exclude all `.in` files because they may contain unsupported syntax, and they have to be preprocessed first
# TEMPORARY: exclude bash completion files, they would generate too many defects in Code scanning dashboard (600+)
diff --git a/.github/workflows/issue_labeler.yml b/.github/workflows/issue_labeler.yml
index e71153a6b0..0ecfb27164 100644
--- a/.github/workflows/issue_labeler.yml
+++ b/.github/workflows/issue_labeler.yml
@@ -23,7 +23,7 @@ jobs:
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633
- name: Parse issue form
- uses: stefanbuck/github-issue-parser@c1a559d78bfb8dd05216dab9ffd2b91082ff5324
+ uses: stefanbuck/github-issue-parser@1e5bdee70d4b3e066a33aa0669ab782943825f94
id: issue-parser
with:
template-path: .github/ISSUE_TEMPLATE/${{ matrix.template }}
diff --git a/.github/workflows/mkosi.yml b/.github/workflows/mkosi.yml
index 5b0ec27f0d..94b9fc3c56 100644
--- a/.github/workflows/mkosi.yml
+++ b/.github/workflows/mkosi.yml
@@ -74,7 +74,7 @@ jobs:
steps:
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633
- - uses: systemd/mkosi@31af101620fc2996517d87e86da310f7ba553d58
+ - uses: systemd/mkosi@4dfdf98ed2877a1e40f37234e0b8fbba0fec3584
# Freeing up disk space with rm -rf can take multiple minutes. Since we don't need the extra free space
# immediately, we remove the files in the background. However, we first move them to a different location
diff --git a/NEWS b/NEWS
index 7014e7582a..9b3933f32f 100644
--- a/NEWS
+++ b/NEWS
@@ -474,6 +474,82 @@ CHANGES WITH 256 in spe:
https://systemd.io.
+ * A small new unit generator "systemd-ssh-generator" has been added. It
+ checks if the sshd binary is installed. If so, it binds it via
+ per-connection socket activation to various sockets depending on the
+ execution context:
+
+ • If the system is run in a VM providing AF_VSOCK support, it
+ automatically binds sshd to AF_VSOCK port 22.
+
+ • If the system is invoked as a full-OS container and the container
+ manager pre-mounts a directory /run/host/unix-export/, it will
+ bind sshd to an AF_UNIX socket /run/host/unix-export/ssh. The
+ idea is the container manager bind mounts the directory to an
+ appropriate place on the host as well, so that the AF_UNIX socket
+ may be used to easily connect from the host to the container.
+
+ • sshd is also bound to an AF_UNIX socket
+ /run/ssh-unix-local/socket, which may be to use ssh/sftp in a
+ "sudo"-like fashion to access resources of other local users.
+
+ • Via the kernel command line option "systemd.ssh_listen=" and the
+ system credential "ssh.listen" sshd may be bound to additional,
+ explicitly configured options, including AF_INET/AF_INET6 ports.
+
+ In particular the first two mechanisms should make dealing with local
+ VMs and full OS containers a lot easier, as SSH connections will
+ *just* *work* from the host – even if no networking is available
+ whatsoever.
+
+ systemd-ssh-generator optionally generates a per-connection
+ socket activation service file wrapping sshd. This is only done if
+ the distribution does not provide one on its own under the name
+ "sshd@.service". The generated unit only works correctly if the SSH
+ privilege separation ("privsep") directory exists. Unfortunately
+ distributions vary wildly where they place this directory. An
+ incomprehensive list:
+
+ • /usr/share/empty.sshd/ (new fedora)
+ • /var/empty/
+ • /var/empty/sshd/
+ • /run/sshd/ (debian/ubuntu?)
+
+ If the SSH privsep directory is placed below /var/ or /run/ care
+ needs to be taken that the directory is created automatically at boot
+ if needed, since these directories possibly or always come up
+ empty. This can be done via a tmpfiles.d/ drop-in. You may use the
+ "sshdprivsepdir" meson option provided by systemd to configure the
+ directory, in case you want systemd to create the directory as needed
+ automatically, if your distribution does not cover this natively.
+
+ Recommendations to distributions, in order to make things just work:
+
+ • Please provide a per-connection SSH service file under the name
+ "sshd@.service".
+
+ • Please move the SSH privsep dir into /usr/ (so that it is truly
+ immutable on image-based operating systems, is strictly under
+ package manager control, and never requires recreation if the
+ system boots up with an empty /run/ or /var/).
+
+ • As an extension of this: please consider following Fedora's lead
+ here, and use /usr/share/empty.sshd/ to minimize needless
+ differences between distributions.
+
+ • If your distribution insists on placing the directory in /var/ or
+ /run/ then please at least provide a tmpfiles.d/ drop-in to
+ recreate it automatically at boot, so that the sshd binary just
+ works, regardless in which context it is called.
+
+ * A small tool "systemd-ssh-proxy" has been added, which is supposed to
+ act as counterpart to "systemd-ssh-generator". It's a small plug-in
+ for the SSH client (via ProxyCommand/ProxyUseFdpass) to allow it to
+ connect to AF_VSOCK or AF_UNIX sockets. Example: "ssh vsock/4711"
+ connects to a local VM with cid 4711, or "ssh
+ unix/run/ssh-unix-local/socket" to connect to the local host via the
+ AF_UNIX socket /run/ssh-unix-local/socket.
+
CHANGES WITH 255:
Announcements of Future Feature Removals and Incompatible Changes:
diff --git a/TODO b/TODO
index b5a2c1f30a..d9167bb73c 100644
--- a/TODO
+++ b/TODO
@@ -1439,8 +1439,6 @@ Features:
- kmod-libs (only when called from PID 1)
- libblkid (only in RootImage= handling in PID 1, but not elsewhere)
- libpam (only when called from PID 1)
- - bzip2 (always — gzip should probably stay static dep the way it is,
- since it's so basic and our defaults)
* seccomp: maybe use seccomp_merge() to merge our filters per-arch if we can.
Apparently kernel performance is much better with fewer larger seccomp
diff --git a/docs/PORTABILITY_AND_STABILITY.md b/docs/PORTABILITY_AND_STABILITY.md
index abdc3dc658..db94c976a7 100644
--- a/docs/PORTABILITY_AND_STABILITY.md
+++ b/docs/PORTABILITY_AND_STABILITY.md
@@ -15,7 +15,11 @@ The stable interfaces are:
* **The command line interface** of `systemd`, `systemctl`, `loginctl`, `journalctl`, and all other command line utilities installed in `$PATH` and documented in a man page. We will make sure that scripts invoking these commands will continue to work with future versions of systemd. Note however that the output generated by these commands is generally not included in the promise, unless it is documented in the man page. Example: the output of `systemctl status` is not stable, but that of `systemctl show` is, because the former is intended to be human readable and the latter computer readable, and this is documented in the man page.
-* **The protocol spoken on the socket referred to by `$NOTIFY_SOCKET`**, as documented in [sd_notify(3)](https://www.freedesktop.org/software/systemd/man/sd_notify.html).
+* **The protocol spoken on the socket referred to by `$NOTIFY_SOCKET`**, as documented in
+ [sd_notify(3)](https://www.freedesktop.org/software/systemd/man/sd_notify.html). Note that, although using
+ libsystemd is a good choice, this protocol can also be reimplemented without external dependencies, as
+ demonstrated in the example listed in
+ [sd_notify(3)](https://www.freedesktop.org/software/systemd/man/devel/sd_notify.html#Notes)
* Some of the **"special" unit names** and their semantics. To be precise the ones that are necessary for normal services, and not those required only for early boot and late shutdown, with very few exceptions. To list them here: `basic.target`, `shutdown.target`, `sockets.target`, `network.target`, `getty.target`, `graphical.target`, `multi-user.target`, `rescue.target`, `emergency.target`, `poweroff.target`, `reboot.target`, `halt.target`, `runlevel[1-5].target`.
diff --git a/hwdb.d/60-evdev.hwdb b/hwdb.d/60-evdev.hwdb
index c603f9ca2c..a4431e239e 100644
--- a/hwdb.d/60-evdev.hwdb
+++ b/hwdb.d/60-evdev.hwdb
@@ -498,9 +498,11 @@ evdev:input:b0003v256Cp0068*
EVDEV_ABS_01=::200
# HUION Kamvas 19 Pro (GT-1902)
-evdev:input:b0003v256Cp006Be0110*
- EVDEV_ABS_00=::68
- EVDEV_ABS_01=::123
+evdev:input:b0003v256Cp006B*
+ EVDEV_ABS_00=::40
+ EVDEV_ABS_01=::42
+ EVDEV_ABS_35=::40
+ EVDEV_ABS_36=::42
#########################################
# Lenovo
diff --git a/hwdb.d/60-sensor.hwdb b/hwdb.d/60-sensor.hwdb
index 75f7b26479..e54d6543d7 100644
--- a/hwdb.d/60-sensor.hwdb
+++ b/hwdb.d/60-sensor.hwdb
@@ -313,7 +313,7 @@ sensor:modalias:acpi:BOSC0200*:dmi:*:svnHampoo*:pnC3W6_AP108_4GB:*
ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1
# Chuwi Ubook X (CWI535)
-sensor:modalias:acpi:MXC6655*:dmi*:svnCHUWIInnovationAndTechnology*:pnUBookX:*
+sensor:modalias:acpi:MXC6655*:dmi:*:svnCHUWIInnovationAndTechnology*:pnUBookX:*
ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, -1
#########################################
diff --git a/man/custom-entities.ent.in b/man/custom-entities.ent.in
index a854d11f85..c82e2b8d8f 100644
--- a/man/custom-entities.ent.in
+++ b/man/custom-entities.ent.in
@@ -18,5 +18,4 @@
<!ENTITY DEFAULT_TIMEOUT "{{DEFAULT_TIMEOUT_SEC}} s">
<!ENTITY DEFAULT_USER_TIMEOUT "{{DEFAULT_USER_TIMEOUT_SEC}} s">
<!ENTITY DEFAULT_KEYMAP "{{SYSTEMD_DEFAULT_KEYMAP}}">
-<!ENTITY fedora_latest_version "38">
-<!ENTITY fedora_cloud_release "1.6">
+<!ENTITY fedora_latest_version "40">
diff --git a/man/event-quick-child.c b/man/event-quick-child.c
index 8195efbaa5..828f0cd6f4 100644
--- a/man/event-quick-child.c
+++ b/man/event-quick-child.c
@@ -1,9 +1,10 @@
/* SPDX-License-Identifier: MIT-0 */
+#define _GNU_SOURCE 1
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
-#include <sd-event.h>
+#include <systemd/sd-event.h>
int main(int argc, char **argv) {
pid_t pid = fork();
diff --git a/man/hwdb-usb-device.c b/man/hwdb-usb-device.c
index 19a5db8022..3ce3ccd87f 100644
--- a/man/hwdb-usb-device.c
+++ b/man/hwdb-usb-device.c
@@ -1,17 +1,18 @@
/* SPDX-License-Identifier: MIT-0 */
+#define _GNU_SOURCE 1
#include <stdio.h>
#include <stdint.h>
-#include <sd-hwdb.h>
+#include <systemd/sd-hwdb.h>
int print_usb_properties(uint16_t vid, uint16_t pid) {
- char match[STRLEN("usb:vp") + DECIMAL_STR_MAX(uint16_t) * 2];
+ char match[128];
sd_hwdb *hwdb;
const char *key, *value;
int r;
/* Match this USB vendor and product ID combination */
- xsprintf(match, "usb:v%04Xp%04X", vid, pid);
+ snprintf(match, sizeof match, "usb:v%04Xp%04X", vid, pid);
r = sd_hwdb_new(&hwdb);
if (r < 0)
diff --git a/man/journal-enumerate-fields.c b/man/journal-enumerate-fields.c
index bb0931970a..3d35b00178 100644
--- a/man/journal-enumerate-fields.c
+++ b/man/journal-enumerate-fields.c
@@ -11,8 +11,7 @@ int main(int argc, char *argv[]) {
r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY);
if (r < 0) {
- errno = -r;
- fprintf(stderr, "Failed to open journal: %m\n");
+ fprintf(stderr, "Failed to open journal: %s\n", strerror(-r));
return 1;
}
SD_JOURNAL_FOREACH_FIELD(j, field)
diff --git a/man/journal-iterate-foreach.c b/man/journal-iterate-foreach.c
index 381b50f9ce..9c0fa0eaf1 100644
--- a/man/journal-iterate-foreach.c
+++ b/man/journal-iterate-foreach.c
@@ -7,10 +7,10 @@
int main(int argc, char *argv[]) {
int r;
sd_journal *j;
+
r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY);
if (r < 0) {
- errno = -r;
- fprintf(stderr, "Failed to open journal: %m\n");
+ fprintf(stderr, "Failed to open journal: %s\n", strerror(-r));
return 1;
}
SD_JOURNAL_FOREACH(j) {
@@ -19,8 +19,7 @@ int main(int argc, char *argv[]) {
r = sd_journal_get_data(j, "MESSAGE", (const void **)&d, &l);
if (r < 0) {
- errno = -r;
- fprintf(stderr, "Failed to read message field: %m\n");
+ fprintf(stderr, "Failed to read message field: %s\n", strerror(-r));
continue;
}
diff --git a/man/journal-iterate-poll.c b/man/journal-iterate-poll.c
index d377324b78..6b78296267 100644
--- a/man/journal-iterate-poll.c
+++ b/man/journal-iterate-poll.c
@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: MIT-0 */
+#define _GNU_SOURCE 1
#include <poll.h>
#include <time.h>
#include <systemd/sd-journal.h>
diff --git a/man/journal-iterate-unique.c b/man/journal-iterate-unique.c
index 5fe98b36b7..f44303d75c 100644
--- a/man/journal-iterate-unique.c
+++ b/man/journal-iterate-unique.c
@@ -12,14 +12,12 @@ int main(int argc, char *argv[]) {
r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY);
if (r < 0) {
- errno = -r;
- fprintf(stderr, "Failed to open journal: %m\n");
+ fprintf(stderr, "Failed to open journal: %s\n", strerror(-r));
return 1;
}
r = sd_journal_query_unique(j, "_SYSTEMD_UNIT");
if (r < 0) {
- errno = -r;
- fprintf(stderr, "Failed to query journal: %m\n");
+ fprintf(stderr, "Failed to query journal: %s\n", strerror(-r));
return 1;
}
SD_JOURNAL_FOREACH_UNIQUE(j, d, l)
diff --git a/man/journal-iterate-wait.c b/man/journal-iterate-wait.c
index ac4b60b8e9..69d3cccb34 100644
--- a/man/journal-iterate-wait.c
+++ b/man/journal-iterate-wait.c
@@ -7,39 +7,38 @@
int main(int argc, char *argv[]) {
int r;
sd_journal *j;
+
r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY);
if (r < 0) {
- errno = -r;
- fprintf(stderr, "Failed to open journal: %m\n");
+ fprintf(stderr, "Failed to open journal: %s\n", strerror(-r));
return 1;
}
+
for (;;) {
const void *d;
size_t l;
r = sd_journal_next(j);
if (r < 0) {
- errno = -r;
- fprintf(stderr, "Failed to iterate to next entry: %m\n");
+ fprintf(stderr, "Failed to iterate to next entry: %s\n", strerror(-r));
break;
}
if (r == 0) {
/* Reached the end, let's wait for changes, and try again */
r = sd_journal_wait(j, (uint64_t) -1);
if (r < 0) {
- errno = -r;
- fprintf(stderr, "Failed to wait for changes: %m\n");
+ fprintf(stderr, "Failed to wait for changes: %s\n", strerror(-r));
break;
}
continue;
}
r = sd_journal_get_data(j, "MESSAGE", &d, &l);
if (r < 0) {
- errno = -r;
- fprintf(stderr, "Failed to read message field: %m\n");
+ fprintf(stderr, "Failed to read message field: %s\n", strerror(-r));
continue;
}
printf("%.*s\n", (int) l, (const char*) d);
}
+
sd_journal_close(j);
return 0;
}
diff --git a/man/journal-stream-fd.c b/man/journal-stream-fd.c
index 8aad5ff8c6..595091af81 100644
--- a/man/journal-stream-fd.c
+++ b/man/journal-stream-fd.c
@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: MIT-0 */
+#define _GNU_SOURCE 1
#include <errno.h>
#include <syslog.h>
#include <stdio.h>
@@ -10,15 +11,16 @@
int main(int argc, char *argv[]) {
int fd;
FILE *log;
+
fd = sd_journal_stream_fd("test", LOG_INFO, 1);
if (fd < 0) {
- errno = -fd;
- fprintf(stderr, "Failed to create stream fd: %m\n");
+ fprintf(stderr, "Failed to create stream fd: %s\n", strerror(-fd));
return 1;
}
+
log = fdopen(fd, "w");
if (!log) {
- fprintf(stderr, "Failed to create file object: %m\n");
+ fprintf(stderr, "Failed to create file object: %s\n", strerror(errno));
close(fd);
return 1;
}
diff --git a/man/kernel-command-line.xml b/man/kernel-command-line.xml
index 72003d86f2..28250a2720 100644
--- a/man/kernel-command-line.xml
+++ b/man/kernel-command-line.xml
@@ -590,10 +590,9 @@
<term><varname>resumeflags=</varname></term>
<listitem>
- <para>Enables resume from hibernation using the specified
- device and mount options. All
- <citerefentry project='man-pages'><refentrytitle>fstab</refentrytitle><manvolnum>5</manvolnum></citerefentry>-like
- paths are supported. For details, see
+ <para>Enable resume from hibernation using the specified device and timeout options. All
+ <citerefentry project='man-pages'><refentrytitle>fstab</refentrytitle><manvolnum>5</manvolnum></citerefentry>-style
+ device identifiers are supported. For details, see
<citerefentry><refentrytitle>systemd-hibernate-resume-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
<xi:include href="version-info.xml" xpointer="v217"/>
@@ -601,6 +600,16 @@
</varlistentry>
<varlistentry>
+ <term><varname>resume_offset=</varname></term>
+
+ <listitem><para>Configure the page offset of the swap space from the resume device. For details, see
+ <citerefentry><refentrytitle>systemd-hibernate-resume-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
+ </para>
+
+ <xi:include href="version-info.xml" xpointer="v254"/></listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><varname>systemd.firstboot=</varname></term>
<listitem><para>Takes a boolean argument, defaults to on. If off,
diff --git a/man/logcontrol-example.c b/man/logcontrol-example.c
index c199ec7a0f..23e73846cd 100644
--- a/man/logcontrol-example.c
+++ b/man/logcontrol-example.c
@@ -43,13 +43,10 @@
#define _cleanup_(f) __attribute__((cleanup(f)))
-#define check(log_level, x) ({ \
- int _r = (x); \
- errno = _r < 0 ? -_r : 0; \
- sd_journal_print((log_level), #x ": %m"); \
- if (_r < 0) \
- return EXIT_FAILURE; \
- })
+static int log_error(int log_level, int error, const char *str) {
+ sd_journal_print(log_level, "%s failed: %s", str, strerror(-error));
+ return error;
+}
typedef enum LogTarget {
LOG_TARGET_JOURNAL,
@@ -127,7 +124,8 @@ static int property_set(
return r;
if (strcmp(property, "LogLevel") == 0) {
- for (int i = 0; i < LOG_DEBUG + 1; i++)
+ int i;
+ for (i = 0; i < LOG_DEBUG + 1; i++)
if (strcmp(value, log_level_table[i]) == 0) {
o->log_level = i;
setlogmask(LOG_UPTO(i));
@@ -141,7 +139,8 @@ static int property_set(
}
if (strcmp(property, "LogTarget") == 0) {
- for (LogTarget i = 0; i < _LOG_TARGET_MAX; i++)
+ LogTarget i;
+ for (i = 0; i < _LOG_TARGET_MAX; i++)
if (strcmp(value, log_target_table[i]) == 0) {
o->log_target = i;
return 0;
@@ -193,6 +192,7 @@ int main(int argc, char **argv) {
.log_target = LOG_TARGET_JOURNAL,
.syslog_identifier = "example",
};
+ int r;
/* https://man7.org/linux/man-pages/man3/setlogmask.3.html
* Programs using syslog() instead of sd_journal can use this API to cut logs
@@ -203,37 +203,49 @@ int main(int argc, char **argv) {
/* Acquire a connection to the bus, letting the library work out the details.
* https://www.freedesktop.org/software/systemd/man/sd_bus_default.html
*/
- check(o.log_level, sd_bus_default(&bus));
+ r = sd_bus_default(&bus);
+ if (r < 0)
+ return log_error(o.log_level, r, "sd_bus_default()");
/* Publish an interface on the bus, specifying our well-known object access
* path and public interface name.
* https://www.freedesktop.org/software/systemd/man/sd_bus_add_object.html
* https://dbus.freedesktop.org/doc/dbus-tutorial.html
*/
- check(o.log_level, sd_bus_add_object_vtable(bus, NULL,
- "/org/freedesktop/LogControl1",
- "org.freedesktop.LogControl1",
- vtable,
- &o));
+ r = sd_bus_add_object_vtable(bus, NULL,
+ "/org/freedesktop/LogControl1",
+ "org.freedesktop.LogControl1",
+ vtable,
+ &o);
+ if (r < 0)
+ return log_error(o.log_level, r, "sd_bus_add_object_vtable()");
/* By default the service is assigned an ephemeral name. Also add a fixed
* one, so that clients know whom to call.
* https://www.freedesktop.org/software/systemd/man/sd_bus_request_name.html
*/
- check(o.log_level, sd_bus_request_name(bus, "org.freedesktop.Example", 0));
+ r = sd_bus_request_name(bus, "org.freedesktop.Example", 0);
+ if (r < 0)
+ return log_error(o.log_level, r, "sd_bus_request_name()");
for (;;) {
/* https://www.freedesktop.org/software/systemd/man/sd_bus_wait.html
*/
- check(o.log_level, sd_bus_wait(bus, UINT64_MAX));
+ r = sd_bus_wait(bus, UINT64_MAX);
+ if (r < 0)
+ return log_error(o.log_level, r, "sd_bus_wait()");
/* https://www.freedesktop.org/software/systemd/man/sd_bus_process.html
*/
- check(o.log_level, sd_bus_process(bus, NULL));
+ r = sd_bus_process(bus, NULL);
+ if (r < 0)
+ return log_error(o.log_level, r, "sd_bus_process()");
}
/* https://www.freedesktop.org/software/systemd/man/sd_bus_release_name.html
*/
- check(o.log_level, sd_bus_release_name(bus, "org.freedesktop.Example"));
+ r = sd_bus_release_name(bus, "org.freedesktop.Example");
+ if (r < 0)
+ return log_error(o.log_level, r, "sd_bus_release_name()");
return 0;
}
diff --git a/man/meson.build b/man/meson.build
index 488ff70220..69ea5c403e 100644
--- a/man/meson.build
+++ b/man/meson.build
@@ -248,3 +248,89 @@ update_man_rules = custom_target(
'@0@/man/*.xml'.format(project_source_root),
'@0@/rules/meson.build'.format(meson.current_source_dir())],
depends : man_page_depends)
+
+############################################################
+
+simple_examples = files(
+ 'event-quick-child.c',
+ 'hwdb-usb-device.c',
+ 'id128-app-specific.c',
+ 'inotify-watch-tmp.c',
+ 'journal-enumerate-fields.c',
+ 'journal-iterate-foreach.c',
+ 'journal-iterate-poll.c',
+ 'journal-iterate-unique.c',
+ 'journal-iterate-wait.c',
+ 'journal-stream-fd.c',
+ 'logcontrol-example.c',
+ 'notify-selfcontained-example.c',
+ 'path-documents.c',
+ 'print-unit-path-call-method.c',
+ 'print-unit-path.c',
+ 'sd-bus-container-append.c',
+ 'sd-bus-container-read.c',
+ 'sd_bus_error-example.c',
+ 'sd_bus_service_reconnect.c',
+ 'send-unit-files-changed.c',
+ 'vtable-example.c',
+)
+
+examples = []
+foreach example : simple_examples
+ examples += [ { 'file' : example } ]
+endforeach
+
+if conf.get('HAVE_GLIB') == 1
+ examples += [
+ {
+ 'file' : files('glib-event-glue.c'),
+ 'opts' : [
+ '-I', libglib.get_variable('includedir') / 'glib-2.0',
+ '-I', libglib.get_variable('libdir') / 'glib-2.0/include',
+ ],
+ },
+ ]
+endif
+
+default_args = [
+ cc.cmd_array(),
+ '-c',
+ '-x', 'c',
+ '-pedantic',
+ '-Wall',
+ '-Werror',
+ '-Wextra',
+ '-Wno-unused-parameter',
+ '-o', '/dev/null',
+ '-I', meson.current_source_dir() / '../src',
+]
+
+std_args_in = [
+ [ '-std=c90', '-Wno-pedantic', '-Wno-variadic-macros', ],
+ [ '-std=c99', ],
+ [ '-std=c11', ],
+ [ '-std=c17', ],
+ [ '-std=c23', ],
+ [ '-std=gnu90', '-Wno-pedantic', '-Wno-variadic-macros', ],
+ [ '-std=gnu99', ],
+ [ '-std=gnu11', ],
+ [ '-std=gnu17', ],
+ [ '-std=gnu23', ],
+]
+
+std_args = []
+foreach std : std_args_in
+ if cc.has_argument(std[0])
+ std_args += [std]
+ endif
+endforeach
+
+foreach item : examples
+ foreach std : std_args
+ file = item.get('file')
+ test('cc-' + fs.stem(file) + '-' + std[0].split('=')[1],
+ env,
+ suite : 'example',
+ args : default_args + std + item.get('opts', []) + [file])
+ endforeach
+endforeach
diff --git a/man/notify-selfcontained-example.c b/man/notify-selfcontained-example.c
new file mode 100644
index 0000000000..6bbe4f2e3b
--- /dev/null
+++ b/man/notify-selfcontained-example.c
@@ -0,0 +1,188 @@
+/* SPDX-License-Identifier: MIT-0 */
+
+/* Implement the systemd notify protocol without external dependencies.
+ * Supports both readiness notification on startup and on reloading,
+ * according to the protocol defined at:
+ * https://www.freedesktop.org/software/systemd/man/latest/sd_notify.html
+ * This protocol is guaranteed to be stable as per:
+ * https://systemd.io/PORTABILITY_AND_STABILITY/ */
+
+#define _GNU_SOURCE 1
+#include <errno.h>
+#include <inttypes.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <time.h>
+#include <unistd.h>
+
+#define _cleanup_(f) __attribute__((cleanup(f)))
+
+static void closep(int *fd) {
+ if (!fd || *fd < 0)
+ return;
+
+ close(*fd);
+ *fd = -1;
+}
+
+static int notify(const char *message) {
+ union sockaddr_union {
+ struct sockaddr sa;
+ struct sockaddr_un sun;
+ } socket_addr = {
+ .sun.sun_family = AF_UNIX,
+ };
+ size_t path_length, message_length;
+ _cleanup_(closep) int fd = -1;
+ const char *socket_path;
+
+ /* Verify the argument first */
+ if (!message)
+ return -EINVAL;
+
+ message_length = strlen(message);
+ if (message_length == 0)
+ return -EINVAL;
+
+ /* If the variable is not set, the protocol is a noop */
+ socket_path = getenv("NOTIFY_SOCKET");
+ if (!socket_path)
+ return 0; /* Not set? Nothing to do */
+
+ /* Only AF_UNIX is supported, with path or abstract sockets */
+ if (socket_path[0] != '/' && socket_path[0] != '@')
+ return -EAFNOSUPPORT;
+
+ path_length = strlen(socket_path);
+ /* Ensure there is room for NUL byte */
+ if (path_length >= sizeof(socket_addr.sun.sun_path))
+ return -E2BIG;
+
+ memcpy(socket_addr.sun.sun_path, socket_path, path_length);
+
+ /* Support for abstract socket */
+ if (socket_addr.sun.sun_path[0] == '@')
+ socket_addr.sun.sun_path[0] = 0;
+
+ fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
+ if (fd < 0)
+ return -errno;
+
+ if (connect(fd, &socket_addr.sa, offsetof(struct sockaddr_un, sun_path) + path_length) != 0)
+ return -errno;
+
+ ssize_t written = write(fd, message, message_length);
+ if (written != (ssize_t) message_length)
+ return written < 0 ? -errno : -EPROTO;
+
+ return 1; /* Notified! */
+}
+
+static int notify_ready(void) {
+ return notify("READY=1");
+}
+
+static int notify_reloading(void) {
+ /* A buffer with length sufficient to format the maximum UINT64 value. */
+ char reload_message[sizeof("RELOADING=1\nMONOTONIC_USEC=18446744073709551615")];
+ struct timespec ts;
+ uint64_t now;
+
+ /* Notify systemd that we are reloading, including a CLOCK_MONOTONIC timestamp in usec
+ * so that the program is compatible with a Type=notify-reload service. */
+
+ if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0)
+ return -errno;
+
+ if (ts.tv_sec < 0 || ts.tv_nsec < 0 ||
+ (uint64_t) ts.tv_sec > (UINT64_MAX - (ts.tv_nsec / 1000ULL)) / 1000000ULL)
+ return -EINVAL;
+
+ now = (uint64_t) ts.tv_sec * 1000000ULL + (uint64_t) ts.tv_nsec / 1000ULL;
+
+ if (snprintf(reload_message, sizeof(reload_message), "RELOADING=1\nMONOTONIC_USEC=%" PRIu64, now) < 0)
+ return -EINVAL;
+
+ return notify(reload_message);
+}
+
+static int notify_stopping(void) {
+ return notify("STOPPING=1");
+}
+
+static volatile sig_atomic_t reloading = 0;
+static volatile sig_atomic_t terminating = 0;
+
+static void signal_handler(int sig) {
+ if (sig == SIGHUP)
+ reloading = 1;
+ else if (sig == SIGINT || sig == SIGTERM)
+ terminating = 1;
+}
+
+int main(int argc, char **argv) {
+ struct sigaction sa = {
+ .sa_handler = signal_handler,
+ .sa_flags = SA_RESTART,
+ };
+ int r;
+
+ /* Setup signal handlers */
+ sigemptyset(&sa.sa_mask);
+ sigaction(SIGHUP, &sa, NULL);
+ sigaction(SIGINT, &sa, NULL);
+ sigaction(SIGTERM, &sa, NULL);
+
+ /* Do more service initialization work here … */
+
+ /* Now that all the preparations steps are done, signal readiness */
+
+ r = notify_ready();
+ if (r < 0) {
+ fprintf(stderr, "Failed to notify readiness to $NOTIFY_SOCKET: %s\n", strerror(-r));
+ return EXIT_FAILURE;
+ }
+
+ while (!terminating) {
+ if (reloading) {
+ reloading = false;
+
+ /* As a separate but related feature, we can also notify the manager
+ * when reloading configuration. This allows accurate state-tracking,
+ * and also automated hook-in of 'systemctl reload' without having to
+ * specify manually an ExecReload= line in the unit file. */
+
+ r = notify_reloading();
+ if (r < 0) {
+ fprintf(stderr, "Failed to notify reloading to $NOTIFY_SOCKET: %s\n", strerror(-r));
+ return EXIT_FAILURE;
+ }
+
+ /* Do some reconfiguration work here … */
+
+ r = notify_ready();
+ if (r < 0) {
+ fprintf(stderr, "Failed to notify readiness to $NOTIFY_SOCKET: %s\n", strerror(-r));
+ return EXIT_FAILURE;
+ }
+ }
+
+ /* Do some daemon work here … */
+ sleep(5);
+ }
+
+ r = notify_stopping();
+ if (r < 0) {
+ fprintf(stderr, "Failed to report termination to $NOTIFY_SOCKET: %s\n", strerror(-r));
+ return EXIT_FAILURE;
+ }
+
+ /* Do some shutdown work here … */
+
+ return EXIT_SUCCESS;
+}
diff --git a/man/org.freedesktop.portable1.xml b/man/org.freedesktop.portable1.xml
index 9b49c610d5..c68995d952 100644
--- a/man/org.freedesktop.portable1.xml
+++ b/man/org.freedesktop.portable1.xml
@@ -286,8 +286,7 @@ node /org/freedesktop/portable1 {
<para><function>DetachImageWithExtensions()</function> detaches a portable image from the system.
This method is a superset of <function>DetachImage()</function> with the addition of
a list of extensions as input parameter, which were overlaid on top of the main
- image via <function>AttachImageWithExtensions()</function>.
- The <varname>flag</varname> parameter is currently unused and reserved for future purposes.</para>
+ image via <function>AttachImageWithExtensions()</function>.</para>
<para><function>ReattachImage()</function> combines the effects of the
<function>AttachImage()</function> method and the <function>DetachImage()</function> method.
@@ -304,7 +303,7 @@ node /org/freedesktop/portable1 {
image. For more details on this functionality, see the <varname>MountImages=</varname> entry on
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>
and <citerefentry><refentrytitle>systemd-sysext</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
- The <varname>flag</varname> parameter is currently unused and reserved for future purposes</para>
+ </para>
<para><function>RemoveImage()</function> removes the image with the specified name.</para>
diff --git a/man/path-documents.c b/man/path-documents.c
index a357dd659a..994f20bcf4 100644
--- a/man/path-documents.c
+++ b/man/path-documents.c
@@ -2,7 +2,7 @@
#include <stdio.h>
#include <stdlib.h>
-#include <sd-path.h>
+#include <systemd/sd-path.h>
int main(void) {
int r;
diff --git a/man/print-unit-path-call-method.c b/man/print-unit-path-call-method.c
index f73dd073f9..15e8d3f51b 100644
--- a/man/print-unit-path-call-method.c
+++ b/man/print-unit-path-call-method.c
@@ -21,8 +21,7 @@
#define MEMBER "GetUnitByPID"
static int log_error(int error, const char *message) {
- errno = -error;
- fprintf(stderr, "%s: %m\n", message);
+ fprintf(stderr, "%s: %s\n", message, strerror(-error));
return error;
}
diff --git a/man/print-unit-path.c b/man/print-unit-path.c
index 0b89318736..737244feb0 100644
--- a/man/print-unit-path.c
+++ b/man/print-unit-path.c
@@ -21,8 +21,7 @@
#define MEMBER "GetUnitByPID"
static int log_error(int error, const char *message) {
- errno = -error;
- fprintf(stderr, "%s: %m\n", message);
+ fprintf(stderr, "%s: %s\n", message, strerror(-error));
return error;
}
diff --git a/man/repart.d.xml b/man/repart.d.xml
index 91db8a91d4..0a2ae62491 100644
--- a/man/repart.d.xml
+++ b/man/repart.d.xml
@@ -552,6 +552,22 @@
</varlistentry>
<varlistentry>
+ <term><varname>DefaultSubvolume=</varname></term>
+
+ <listitem><para>Takes an absolute path specifying the default subvolume within the new filesystem.
+ Note that this setting does not create the subvolume itself, that can be configured with
+ <varname>Subvolumes=</varname>.</para>
+
+ <para>Note that this option only takes effect if the target filesystem supports subvolumes, such as
+ <literal>btrfs</literal>.</para>
+
+ <para>Note that due to limitations of <literal>mkfs.btrfs</literal>, this option is only supported
+ when running with <option>--offline=no</option>.</para>
+
+ <xi:include href="version-info.xml" xpointer="v256"/></listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><varname>Encrypt=</varname></term>
<listitem><para>Takes one of <literal>off</literal>, <literal>key-file</literal>,
diff --git a/man/rules/meson.build b/man/rules/meson.build
index e483196c5c..1ca5b105b3 100644
--- a/man/rules/meson.build
+++ b/man/rules/meson.build
@@ -944,7 +944,7 @@ manpages = [
['systemd-hibernate-resume-generator', '8', [], 'ENABLE_HIBERNATE'],
['systemd-hibernate-resume.service',
'8',
- ['systemd-hibernate-resume'],
+ ['systemd-hibernate-clear.service', 'systemd-hibernate-resume'],
'ENABLE_HIBERNATE'],
['systemd-homed.service', '8', ['systemd-homed'], 'ENABLE_HOMED'],
['systemd-hostnamed.service', '8', ['systemd-hostnamed'], 'ENABLE_HOSTNAMED'],
diff --git a/man/sd-bus-container-append.c b/man/sd-bus-container-append.c
index 8bb4f33e86..07a24f24cc 100644
--- a/man/sd-bus-container-append.c
+++ b/man/sd-bus-container-append.c
@@ -3,13 +3,14 @@
#include <systemd/sd-bus.h>
int append_strings_to_message(sd_bus_message *m, const char *const *arr) {
+ const char *s;
int r;
r = sd_bus_message_open_container(m, 'a', "s");
if (r < 0)
return r;
- for (const char *s = *arr; *s; s++) {
+ for (s = *arr; *s; s++) {
r = sd_bus_message_append(m, "s", s);
if (r < 0)
return r;
diff --git a/man/sd-journal.xml b/man/sd-journal.xml
index d143cb4a0f..5908f98e68 100644
--- a/man/sd-journal.xml
+++ b/man/sd-journal.xml
@@ -86,6 +86,17 @@
— are fully thread-safe and may be called from multiple threads in parallel.</para>
</refsect1>
+ <refsect1>
+ <title>Optional dependencies</title>
+
+ <para>Depending on which build-time options are enabled, functions that operate on
+ <structname>sd_journal</structname> objects might cause optional shared libraries to be dynamically
+ loaded via
+ <citerefentry project='man7'><refentrytitle>dlopen</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ such as decompression libraries (xz, lz4, zstd) or cryptographic libraries (gcrypt).
+ </para>
+ </refsect1>
+
<xi:include href="libsystemd-pkgconfig.xml" />
<refsect1>
diff --git a/man/sd_bus_error-example.c b/man/sd_bus_error-example.c
index 9b162eb6cc..3836f5e642 100644
--- a/man/sd_bus_error-example.c
+++ b/man/sd_bus_error-example.c
@@ -3,7 +3,7 @@
#include <errno.h>
#include <string.h>
#include <unistd.h>
-#include <sd-bus.h>
+#include <systemd/sd-bus.h>
int writer_with_negative_errno_return(int fd, sd_bus_error *error) {
const char *message = "Hello, World!\n";
@@ -14,5 +14,5 @@ int writer_with_negative_errno_return(int fd, sd_bus_error *error) {
/* On error, initialize the error structure, and also propagate the errno
* value that write(2) set for us. */
- return sd_bus_error_set_errnof(error, errno, "Failed to write to fd %i: %m", fd);
+ return sd_bus_error_set_errnof(error, errno, "Failed to write to fd %i: %s", fd, strerror(errno));
}
diff --git a/man/sd_bus_service_reconnect.c b/man/sd_bus_service_reconnect.c
index c0818689f2..fc7c3b1a72 100644
--- a/man/sd_bus_service_reconnect.c
+++ b/man/sd_bus_service_reconnect.c
@@ -42,13 +42,10 @@
#define _cleanup_(f) __attribute__((cleanup(f)))
-#define check(x) ({ \
- int _r = (x); \
- errno = _r < 0 ? -_r : 0; \
- printf(#x ": %m\n"); \
- if (_r < 0) \
- return EXIT_FAILURE; \
- })
+static int log_error(int r, const char *str) {
+ fprintf(stderr, "%s failed: %s\n", str, strerror(-r));
+ return r;
+}
typedef struct object {
const char *example;
@@ -90,13 +87,24 @@ static const sd_bus_vtable vtable[] = {
static int setup(object *o);
static int on_disconnect(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
- check(setup((object *)userdata));
- return 0;
+ int r;
+
+ r = setup((object *)userdata);
+ if (r < 0) {
+ object *o = userdata;
+ r = sd_event_exit(*o->event, r);
+ if (r < 0)
+ return log_error(r, "sd_event_exit()");
+ }
+
+ return 1;
}
/* Ensure the event loop exits with a clear error if acquiring the well-known
* service name fails */
static int request_name_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
+ int r;
+
if (!sd_bus_message_is_method_error(m, NULL))
return 1;
@@ -105,21 +113,27 @@ static int request_name_callback(sd_bus_message *m, void *userdata, sd_bus_error
if (sd_bus_error_has_names(error, SD_BUS_ERROR_TIMEOUT, SD_BUS_ERROR_NO_REPLY))
return 1; /* The bus is not available, try again later */
- printf("Failed to request name: %s\n", error->message);
+ fprintf(stderr, "Failed to request name: %s\n", error->message);
object *o = userdata;
- check(sd_event_exit(*o->event, -sd_bus_error_get_errno(error)));
+ r = sd_event_exit(*o->event, -sd_bus_error_get_errno(error));
+ if (r < 0)
+ return log_error(r, "sd_event_exit()");
return 1;
}
static int setup(object *o) {
+ int r;
+
/* If we are reconnecting, then the bus object needs to be closed, detached
* from the event loop and recreated.
* https://www.freedesktop.org/software/systemd/man/sd_bus_detach_event.html
* https://www.freedesktop.org/software/systemd/man/sd_bus_close_unref.html
*/
if (*o->bus) {
- check(sd_bus_detach_event(*o->bus));
+ r = sd_bus_detach_event(*o->bus);
+ if (r < 0)
+ return log_error(r, "sd_bus_detach_event()");
*o->bus = sd_bus_close_unref(*o->bus);
}
@@ -135,55 +149,75 @@ static int setup(object *o) {
* https://www.freedesktop.org/software/systemd/man/sd_bus_set_connected_signal.html
* https://www.freedesktop.org/software/systemd/man/sd_bus_start.html
*/
- check(sd_bus_new(o->bus));
- check(sd_bus_set_address(*o->bus, "unix:path=/run/dbus/system_bus_socket"));
- check(sd_bus_set_bus_client(*o->bus, 1));
- check(sd_bus_negotiate_creds(*o->bus, 1, SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS));
- check(sd_bus_set_watch_bind(*o->bus, 1));
- check(sd_bus_start(*o->bus));
+ r = sd_bus_new(o->bus);
+ if (r < 0)
+ return log_error(r, "sd_bus_new()");
+ r = sd_bus_set_address(*o->bus, "unix:path=/run/dbus/system_bus_socket");
+ if (r < 0)
+ return log_error(r, "sd_bus_set_address()");
+ r = sd_bus_set_bus_client(*o->bus, 1);
+ if (r < 0)
+ return log_error(r, "sd_bus_set_bus_client()");
+ r = sd_bus_negotiate_creds(*o->bus, 1, SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS);
+ if (r < 0)
+ return log_error(r, "sd_bus_negotiate_creds()");
+ r = sd_bus_set_watch_bind(*o->bus, 1);
+ if (r < 0)
+ return log_error(r, "sd_bus_set_watch_bind()");
+ r = sd_bus_start(*o->bus);
+ if (r < 0)
+ return log_error(r, "sd_bus_start()");
/* Publish an interface on the bus, specifying our well-known object access
* path and public interface name.
* https://www.freedesktop.org/software/systemd/man/sd_bus_add_object.html
* https://dbus.freedesktop.org/doc/dbus-tutorial.html
*/
- check(sd_bus_add_object_vtable(*o->bus,
- NULL,
- "/org/freedesktop/ReconnectExample",
- "org.freedesktop.ReconnectExample",
- vtable,
- o));
+ r = sd_bus_add_object_vtable(*o->bus,
+ NULL,
+ "/org/freedesktop/ReconnectExample",
+ "org.freedesktop.ReconnectExample",
+ vtable,
+ o);
+ if (r < 0)
+ return log_error(r, "sd_bus_add_object_vtable()");
/* By default the service is only assigned an ephemeral name. Also add a
* well-known one, so that clients know whom to call. This needs to be
* asynchronous, as D-Bus might not be yet available. The callback will check
* whether the error is expected or not, in case it fails.
* https://www.freedesktop.org/software/systemd/man/sd_bus_request_name.html
*/
- check(sd_bus_request_name_async(*o->bus,
- NULL,
- "org.freedesktop.ReconnectExample",
- 0,
- request_name_callback,
- o));
+ r = sd_bus_request_name_async(*o->bus,
+ NULL,
+ "org.freedesktop.ReconnectExample",
+ 0,
+ request_name_callback,
+ o);
+ if (r < 0)
+ return log_error(r, "sd_bus_request_name_async()");
/* When D-Bus is disconnected this callback will be invoked, which will set up
* the connection again. This needs to be asynchronous, as D-Bus might not yet
* be available.
* https://www.freedesktop.org/software/systemd/man/sd_bus_match_signal_async.html
*/
- check(sd_bus_match_signal_async(*o->bus,
- NULL,
- "org.freedesktop.DBus.Local",
- NULL,
- "org.freedesktop.DBus.Local",
- "Disconnected",
- on_disconnect,
- NULL,
- o));
+ r = sd_bus_match_signal_async(*o->bus,
+ NULL,
+ "org.freedesktop.DBus.Local",
+ NULL,
+ "org.freedesktop.DBus.Local",
+ "Disconnected",
+ on_disconnect,
+ NULL,
+ o);
+ if (r < 0)
+ return log_error(r, "sd_bus_match_signal_async()");
/* Attach the bus object to the event loop so that calls and signals are
* processed.
* https://www.freedesktop.org/software/systemd/man/sd_bus_attach_event.html
*/
- check(sd_bus_attach_event(*o->bus, *o->event, 0));
+ r = sd_bus_attach_event(*o->bus, *o->event, 0);
+ if (r < 0)
+ return log_error(r, "sd_bus_attach_event()");
return 0;
}
@@ -199,28 +233,42 @@ int main(int argc, char **argv) {
.bus = &bus,
.event = &event,
};
+ int r;
/* Create an event loop data structure, with default parameters.
* https://www.freedesktop.org/software/systemd/man/sd_event_default.html
*/
- check(sd_event_default(&event));
+ r = sd_event_default(&event);
+ if (r < 0)
+ return log_error(r, "sd_event_default()");
/* By default the event loop will terminate when all sources have disappeared,
* so we have to keep it 'occupied'. Register signal handling to do so.
* https://www.freedesktop.org/software/systemd/man/sd_event_add_signal.html
*/
- check(sd_event_add_signal(event, NULL, SIGINT|SD_EVENT_SIGNAL_PROCMASK, NULL, NULL));
- check(sd_event_add_signal(event, NULL, SIGTERM|SD_EVENT_SIGNAL_PROCMASK, NULL, NULL));
+ r = sd_event_add_signal(event, NULL, SIGINT|SD_EVENT_SIGNAL_PROCMASK, NULL, NULL);
+ if (r < 0)
+ return log_error(r, "sd_event_add_signal(SIGINT)");
+
+ r = sd_event_add_signal(event, NULL, SIGTERM|SD_EVENT_SIGNAL_PROCMASK, NULL, NULL);
+ if (r < 0)
+ return log_error(r, "sd_event_add_signal(SIGTERM)");
- check(setup(&o));
+ r = setup(&o);
+ if (r < 0)
+ return EXIT_FAILURE;
/* Enter the main loop, it will exit only on sigint/sigterm.
* https://www.freedesktop.org/software/systemd/man/sd_event_loop.html
*/
- check(sd_event_loop(event));
+ r = sd_event_loop(event);
+ if (r < 0)
+ return log_error(r, "sd_event_loop()");
/* https://www.freedesktop.org/software/systemd/man/sd_bus_release_name.html */
- check(sd_bus_release_name(bus, "org.freedesktop.ReconnectExample"));
+ r = sd_bus_release_name(bus, "org.freedesktop.ReconnectExample");
+ if (r < 0)
+ return log_error(r, "sd_bus_release_name()");
return 0;
}
diff --git a/man/sd_notify.xml b/man/sd_notify.xml
index 1e611fe6d8..e1c4073e7f 100644
--- a/man/sd_notify.xml
+++ b/man/sd_notify.xml
@@ -493,6 +493,11 @@
privileged port (i.e.: lower than 1024), as an attempt to address concerns that unprivileged processes in
the guest might try to send malicious notifications to the host, driving it to make destructive decisions
based on them.</para>
+
+ <para>Note that, while using this library should be preferred in order to avoid code duplication, it is
+ also possible to reimplement the simple readiness notification protocol without external dependencies,
+ as demonstrated in the following self-contained example:
+ <programlisting><xi:include href="notify-selfcontained-example.c" parse="text"/></programlisting></para>
</refsect1>
<refsect1>
@@ -528,8 +533,8 @@
<programlisting>
sd_notifyf(0, "READY=1\n"
- "STATUS=Processing requests…\n"
- "MAINPID=%lu",
+ "STATUS=Processing requests…\n"
+ "MAINPID=%lu",
(unsigned long) getpid());</programlisting>
</example>
@@ -540,7 +545,7 @@ sd_notifyf(0, "READY=1\n"
<programlisting>
sd_notifyf(0, "STATUS=Failed to start up: %s\n"
- "ERRNO=%i",
+ "ERRNO=%i",
strerror_r(errnum, (char[1024]){}, 1024),
errnum);</programlisting>
</example>
diff --git a/man/systemd-debug-generator.xml b/man/systemd-debug-generator.xml
index 5d1d5b7e60..af3615175e 100644
--- a/man/systemd-debug-generator.xml
+++ b/man/systemd-debug-generator.xml
@@ -6,7 +6,7 @@
%entities;
]>
<!-- SPDX-License-Identifier: LGPL-2.1-or-later -->
-<refentry id="systemd-debug-generator">
+<refentry id="systemd-debug-generator" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>systemd-debug-generator</title>
@@ -71,6 +71,36 @@
</refsect1>
<refsect1>
+ <title>System Credentials</title>
+
+ <variablelist class='system-credentials'>
+ <varlistentry>
+ <term><varname>systemd.extra-unit.*</varname></term>
+
+ <listitem><para>Credentials prefixed with <literal>systemd.extra-unit.</literal> specify additional
+ units to add to the final system. Note that these additional units are added to both the initrd and
+ the final system. <varname>ConditionPathExists=!/etc/initrd-release</varname> can be used to make
+ sure the unit is conditioned out in the initrd.</para>
+
+ <xi:include href="version-info.xml" xpointer="v256"/></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>systemd.unit-dropin.*</varname></term>
+
+ <listitem><para>Credentials prefixed with <literal>systemd.unit-dropin.</literal> add drop-ins for
+ the corresponding units in the final system. Each credential must be suffixed with the full unit name
+ including the unit extension. Its contents must be a valid unit drop-in file. Only one drop-in per
+ unit can be specified. The name of the generated drop-in will be
+ <literal>50-credential.conf</literal>. Note that these additional drop-ins are added to both the
+ initrd and the final system.</para>
+
+ <xi:include href="version-info.xml" xpointer="v256"/></listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
<title>See Also</title>
<para><simplelist type="inline">
<member><citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry></member>
diff --git a/man/systemd-hibernate-resume.service.xml b/man/systemd-hibernate-resume.service.xml
index f6cdefdd3a..c0c545cc9c 100644
--- a/man/systemd-hibernate-resume.service.xml
+++ b/man/systemd-hibernate-resume.service.xml
@@ -17,12 +17,14 @@
<refnamediv>
<refname>systemd-hibernate-resume.service</refname>
+ <refname>systemd-hibernate-clear.service</refname>
<refname>systemd-hibernate-resume</refname>
<refpurpose>Resume from hibernation</refpurpose>
</refnamediv>
<refsynopsisdiv>
<para><filename>systemd-hibernate-resume.service</filename></para>
+ <para><filename>systemd-hibernate-clear.service</filename></para>
<para><filename>/usr/lib/systemd/systemd-hibernate-resume</filename></para>
</refsynopsisdiv>
@@ -37,6 +39,12 @@
<filename>/sys/power/resume</filename>, along with the offset in memory pages
(<filename>/sys/power/resume_offset</filename>) if supported.</para>
+ <para>The resume device node is either passed directly through arguments, or automatically acquired
+ from kernel command line options and/or <varname>HibernateLocation</varname> EFI variable. The latter
+ will normally be cleared by <filename>systemd-hibernate-resume.service</filename> on resumption.
+ If a stale variable is detected, it would be cleared by
+ <filename>systemd-hibernate-clear.service</filename>.</para>
+
<para>Failing to initiate a resume is not an error condition. It may mean that there was
no resume image (e. g. if the system has been simply powered off and not hibernated).
In such cases, the boot is ordinarily continued.</para>
diff --git a/man/systemd-sleep.conf.xml b/man/systemd-sleep.conf.xml
index 411577d519..7a343975d7 100644
--- a/man/systemd-sleep.conf.xml
+++ b/man/systemd-sleep.conf.xml
@@ -154,6 +154,27 @@
</varlistentry>
<varlistentry>
+ <term><varname>SuspendState=</varname></term>
+
+ <listitem><para>The string to be written to <filename>/sys/power/state</filename> by <citerefentry>
+ <refentrytitle>systemd-suspend.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
+ More than one value can be specified by separating multiple values with whitespace. They will be
+ tried in turn, until one is written without error. If none of the writes succeed, the operation will
+ be aborted.</para>
+
+ <para>The allowed set of values is determined by the kernel and is shown in the file itself (use
+ <command>cat /sys/power/state</command> to display). See <ulink
+ url="https://docs.kernel.org/admin-guide/pm/sleep-states.html#basic-sysfs-interfaces-for-system-suspend-and-hibernation">
+ Basic sysfs Interfaces for System Suspend and Hibernation</ulink> for more details.</para>
+
+ <para>
+ <citerefentry><refentrytitle>systemd-suspend-then-hibernate.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ uses this value when suspending.</para>
+
+ <xi:include href="version-info.xml" xpointer="v203"/></listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><varname>HibernateMode=</varname></term>
<listitem><para>The string to be written to <filename>/sys/power/disk</filename> by <citerefentry>
@@ -175,24 +196,21 @@
</varlistentry>
<varlistentry>
- <term><varname>SuspendState=</varname></term>
+ <term><varname>SleepMemMode=</varname></term>
- <listitem><para>The string to be written to <filename>/sys/power/state</filename> by <citerefentry>
- <refentrytitle>systemd-suspend.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
+ <listitem><para>The string to be written to <filename>/sys/power/mem_sleep</filename>
+ when <option>SuspendState=mem</option> or <command>hybrid-sleep</command> is used.
More than one value can be specified by separating multiple values with whitespace. They will be
tried in turn, until one is written without error. If none of the writes succeed, the operation will
- be aborted.</para>
+ be aborted. Defaults to empty, i.e. the kernel default or kernel command line option
+ <varname>mem_sleep_default=</varname> is respected.</para>
<para>The allowed set of values is determined by the kernel and is shown in the file itself (use
- <command>cat /sys/power/state</command> to display). See <ulink
- url="https://docs.kernel.org/admin-guide/pm/sleep-states.html#basic-sysfs-interfaces-for-system-suspend-and-hibernation">
+ <command>cat /sys/power/mem_sleep</command> to display). See the kernel documentation page
+ <ulink url="https://docs.kernel.org/admin-guide/pm/sleep-states.html#basic-sysfs-interfaces-for-system-suspend-and-hibernation">
Basic sysfs Interfaces for System Suspend and Hibernation</ulink> for more details.</para>
- <para>
- <citerefentry><refentrytitle>systemd-suspend-then-hibernate.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
- uses this value when suspending.</para>
-
- <xi:include href="version-info.xml" xpointer="v203"/></listitem>
+ <xi:include href="version-info.xml" xpointer="v256"/></listitem>
</varlistentry>
<varlistentry>
diff --git a/man/systemd-system.conf.xml b/man/systemd-system.conf.xml
index e6611d04e7..88f13d05b6 100644
--- a/man/systemd-system.conf.xml
+++ b/man/systemd-system.conf.xml
@@ -624,10 +624,12 @@
<term><varname>ReloadLimitIntervalSec=</varname></term>
<term><varname>ReloadLimitBurst=</varname></term>
- <listitem><para>Rate limiting for daemon-reload requests. Default to unset, and any number of daemon-reload
- operations can be requested at any time. <varname>ReloadLimitIntervalSec=</varname> takes a value in seconds
- to configure the rate limit window, and <varname>ReloadLimitBurst=</varname> takes a positive integer to
- configure the maximum allowed number of reloads within the configured time window.</para>
+ <listitem><para>Rate limiting for daemon-reload and (since v256) daemon-reexec requests. The setting
+ applies to both operations, but the rate limits are tracked separately. Defaults to unset, and any
+ number of operations can be requested at any time. <varname>ReloadLimitIntervalSec=</varname> takes
+ a value in seconds to configure the rate limit window, and <varname>ReloadLimitBurst=</varname>
+ takes a positive integer to configure the maximum allowed number of operations within the configured
+ time window.</para>
<xi:include href="version-info.xml" xpointer="v253"/></listitem>
</varlistentry>
diff --git a/man/systemd.service.xml b/man/systemd.service.xml
index 67a3930a28..9a0c8166ef 100644
--- a/man/systemd.service.xml
+++ b/man/systemd.service.xml
@@ -1728,7 +1728,7 @@ SystemdService=simple-dbus-service.service</programlisting>
Description=Simple notifying service
[Service]
-Type=notify
+Type=notify-reload
ExecStart=/usr/sbin/simple-notifying-service
[Install]
@@ -1746,6 +1746,16 @@ WantedBy=multi-user.target</programlisting>
<citerefentry><refentrytitle>systemd.kill</refentrytitle><manvolnum>5</manvolnum></citerefentry>
for details on how you can influence the way systemd terminates
the service.</para>
+
+ <para>To avoid code duplication, it is preferable to use
+ <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ when possible, especially when other APIs provided by
+ <citerefentry><refentrytitle>libsystemd</refentrytitle><manvolnum>3</manvolnum></citerefentry> are
+ also used, but note that the notification protocol is very simple and guaranteed to be stable as per
+ the <ulink url="https://systemd.io/PORTABILITY_AND_STABILITY/">Interface Portability and Stability
+ Promise</ulink>, so it can be reimplemented by services with no external dependencies. For a
+ self-contained example, see
+ <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
</example>
</refsect1>
diff --git a/man/systemd.system-credentials.xml b/man/systemd.system-credentials.xml
index 2a345c47b4..b0fb70c6c5 100644
--- a/man/systemd.system-credentials.xml
+++ b/man/systemd.system-credentials.xml
@@ -367,6 +367,16 @@
<xi:include href="version-info.xml" xpointer="v256"/>
</listitem>
</varlistentry>
+
+ <varlistentry>
+ <term><varname>systemd.extra-unit.*</varname></term>
+ <term><varname>systemd.unit-dropin.*</varname></term>
+
+ <listitem><para>These credentials specify extra units and drop-ins to add to the system. For details
+ see <citerefentry><refentrytitle>systemd-debug-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
+
+ <xi:include href="version-info.xml" xpointer="v256"/></listitem>
+ </varlistentry>
</variablelist>
</refsect1>
diff --git a/man/tmpfiles.d.xml b/man/tmpfiles.d.xml
index 76807b92e5..0aabfa625a 100644
--- a/man/tmpfiles.d.xml
+++ b/man/tmpfiles.d.xml
@@ -538,7 +538,7 @@ w- /proc/sys/vm/swappiness - - - - 10</programlisting></para>
Base64 decoding is applied to the credential contents.</para>
<para>Note that for all line types that result in creation of any kind of file node
- (i.e. <varname>f</varname>/<varname>F</varname>,
+ (i.e. <varname>f</varname>,
<varname>d</varname>/<varname>D</varname>/<varname>v</varname>/<varname>q</varname>/<varname>Q</varname>,
<varname>p</varname>, <varname>L</varname>, <varname>c</varname>/<varname>b</varname> and <varname>C</varname>)
leading directories are implicitly created if needed, owned by root with an access mode of 0755. In order to
@@ -697,7 +697,7 @@ d /tmp/foo/bar - - - bmA:1h -</programlisting></para>
<para>For <varname>L</varname> lines determines the destination path of the symlink. For <varname>c</varname> and
<varname>b</varname>, determines the major/minor of the device node, with major and minor formatted as integers,
- separated by <literal>:</literal>, e.g. <literal>1:3</literal>. For <varname>f</varname>, <varname>F</varname>,
+ separated by <literal>:</literal>, e.g. <literal>1:3</literal>. For <varname>f</varname>
and <varname>w</varname>, the argument may be used to specify a short string that is written to the file,
suffixed by a newline. For <varname>C</varname>, specifies the source file or directory. For <varname>t</varname>
and <varname>T</varname>, determines extended attributes to be set. For <varname>a</varname> and
diff --git a/man/vtable-example.c b/man/vtable-example.c
index e3346a8021..2e8994471a 100644
--- a/man/vtable-example.c
+++ b/man/vtable-example.c
@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: MIT-0 */
+#define _GNU_SOURCE 1
#include <errno.h>
#include <stdbool.h>
#include <stddef.h>
@@ -9,20 +10,14 @@
#define _cleanup_(f) __attribute__((cleanup(f)))
-#define check(x) ({ \
- int r = (x); \
- errno = r < 0 ? -r : 0; \
- printf(#x ": %m\n"); \
- if (r < 0) \
- return EXIT_FAILURE; \
- })
-
typedef struct object {
char *name;
uint32_t number;
} object;
static int method(sd_bus_message *m, void *userdata, sd_bus_error *error) {
+ int r;
+
printf("Got called with userdata=%p\n", userdata);
if (sd_bus_message_is_method_call(m,
@@ -31,8 +26,17 @@ static int method(sd_bus_message *m, void *userdata, sd_bus_error *error) {
return 1;
const char *string;
- check(sd_bus_message_read(m, "s", &string));
- check(sd_bus_reply_method_return(m, "s", string));
+ r = sd_bus_message_read(m, "s", &string);
+ if (r < 0) {
+ fprintf(stderr, "sd_bus_message_read() failed: %s\n", strerror(-r));
+ return 0;
+ }
+
+ r = sd_bus_reply_method_return(m, "s", string);
+ if (r < 0) {
+ fprintf(stderr, "sd_bus_reply_method_return() failed: %s\n", strerror(-r));
+ return 0;
+ }
return 1;
}
@@ -84,28 +88,55 @@ static const sd_bus_vtable vtable[] = {
int main(int argc, char **argv) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+ int r;
sd_bus_default(&bus);
object object = { .number = 666 };
- check((object.name = strdup("name")) != NULL);
+ object.name = strdup("name");
+ if (!object.name) {
+ fprintf(stderr, "OOM\n");
+ return EXIT_FAILURE;
+ }
- check(sd_bus_add_object_vtable(bus, NULL,
- "/org/freedesktop/systemd/VtableExample",
- "org.freedesktop.systemd.VtableExample",
- vtable,
- &object));
+ r = sd_bus_add_object_vtable(bus, NULL,
+ "/org/freedesktop/systemd/VtableExample",
+ "org.freedesktop.systemd.VtableExample",
+ vtable,
+ &object);
+ if (r < 0) {
+ fprintf(stderr, "sd_bus_add_object_vtable() failed: %s\n", strerror(-r));
+ return EXIT_FAILURE;
+ }
- check(sd_bus_request_name(bus,
- "org.freedesktop.systemd.VtableExample",
- 0));
+ r = sd_bus_request_name(bus,
+ "org.freedesktop.systemd.VtableExample",
+ 0);
+ if (r < 0) {
+ fprintf(stderr, "sd_bus_request_name() failed: %s\n", strerror(-r));
+ return EXIT_FAILURE;
+ }
for (;;) {
- check(sd_bus_wait(bus, UINT64_MAX));
- check(sd_bus_process(bus, NULL));
+ r = sd_bus_wait(bus, UINT64_MAX);
+ if (r < 0) {
+ fprintf(stderr, "sd_bus_wait() failed: %s\n", strerror(-r));
+ return EXIT_FAILURE;
+ }
+
+ r = sd_bus_process(bus, NULL);
+ if (r < 0) {
+ fprintf(stderr, "sd_bus_process() failed: %s\n", strerror(-r));
+ return EXIT_FAILURE;
+ }
+ }
+
+ r = sd_bus_release_name(bus, "org.freedesktop.systemd.VtableExample");
+ if (r < 0) {
+ fprintf(stderr, "sd_bus_release_name() failed: %s\n", strerror(-r));
+ return EXIT_FAILURE;
}
- check(sd_bus_release_name(bus, "org.freedesktop.systemd.VtableExample"));
free(object.name);
return 0;
diff --git a/meson.build b/meson.build
index 897b393869..1c4cac82c1 100644
--- a/meson.build
+++ b/meson.build
@@ -210,6 +210,10 @@ if sshdconfdir == ''
sshdconfdir = sysconfdir / 'ssh/sshd_config.d'
endif
+sshdprivsepdir = get_option('sshdprivsepdir')
+conf.set10('CREATE_SSHDPRIVSEPDIR', sshdprivsepdir != 'no' and not sshdprivsepdir.startswith('/usr/'))
+conf.set('SSHDPRIVSEPDIR', sshdprivsepdir, description : 'SSH privilege separation directory')
+
libcryptsetup_plugins_dir = get_option('libcryptsetup-plugins-dir')
if libcryptsetup_plugins_dir == ''
libcryptsetup_plugins_dir = libdir / 'cryptsetup'
@@ -1319,6 +1323,9 @@ if not have
# link to neither of the libs if one is not found
libgcrypt = []
libgpg_error = []
+ libgcrypt_cflags = []
+else
+ libgcrypt_cflags = libgcrypt.partial_dependency(includes: true, compile_args: true)
endif
conf.set10('HAVE_GCRYPT', have)
@@ -1694,6 +1701,7 @@ if conf.get('BPF_FRAMEWORK') == 1
bpf_gcc_flags = [
'-std=gnu11',
'-fno-stack-protector',
+ '-fno-ssa-phiopt',
'-O2',
'-mcpu=v3',
'-mco-re',
@@ -1951,8 +1959,7 @@ libsystemd = shared_library(
include_directories : libsystemd_includes,
link_args : ['-shared',
'-Wl,--version-script=' + libsystemd_sym_path],
- link_with : [libbasic,
- libbasic_gcrypt],
+ link_with : [libbasic],
link_whole : [libsystemd_static],
dependencies : [librt,
threads,
@@ -1968,7 +1975,6 @@ install_libsystemd_static = static_library(
'systemd',
libsystemd_sources,
basic_sources,
- basic_gcrypt_sources,
fundamental_sources,
include_directories : libsystemd_includes,
build_by_default : static_libsystemd != 'false',
@@ -1979,7 +1985,7 @@ install_libsystemd_static = static_library(
dependencies : [libblkid,
libcap,
libdl,
- libgcrypt,
+ libgcrypt_cflags,
liblz4_cflags,
libmount,
libopenssl,
@@ -2722,6 +2728,7 @@ summary({
'PAM modules directory' : pamlibdir,
'PAM configuration directory' : pamconfdir,
'ssh server configuration directory' : sshdconfdir,
+ 'ssh server privilege separation directory' : sshdprivsepdir,
'ssh client configuration directory' : sshconfdir,
'libcryptsetup plugins directory' : libcryptsetup_plugins_dir,
'RPM macros directory' : rpmmacrosdir,
diff --git a/meson_options.txt b/meson_options.txt
index 3a3ab6e7c1..af9a006563 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -215,6 +215,8 @@ option('sshconfdir', type : 'string',
description : 'directory for SSH client configuration ["no" disables]')
option('sshdconfdir', type : 'string',
description : 'directory for SSH server configuration ["no" disables]')
+option('sshdprivsepdir', type : 'string',
+ description : 'directory for SSH privilege separation ["no" disables]', value : '/run/sshd')
option('libcryptsetup-plugins-dir', type : 'string',
description : 'directory for libcryptsetup plugins')
option('docdir', type : 'string',
diff --git a/mkosi.conf b/mkosi.conf
index a5953d7613..cea204961b 100644
--- a/mkosi.conf
+++ b/mkosi.conf
@@ -19,8 +19,6 @@ BuildSourcesEphemeral=yes
[Host]
@Incremental=yes
-# TODO: Drop to 2G again once the next Noble kernel update ships and we can use linux-image-virtual.
-@QemuMem=4G
@RuntimeSize=8G
ToolsTreePackages=virtiofsd
KernelCommandLineExtra=systemd.crash_shell
diff --git a/mkosi.images/system/mkosi.conf b/mkosi.images/system/mkosi.conf
index ccb719a512..303af4acb1 100644
--- a/mkosi.images/system/mkosi.conf
+++ b/mkosi.images/system/mkosi.conf
@@ -14,9 +14,7 @@ Packages=
dosfstools
e2fsprogs
findutils
- gcc # Sanitizer libraries
gdb
- git
grep
gzip
jq
diff --git a/mkosi.images/system/mkosi.conf.d/10-arch/mkosi.conf b/mkosi.images/system/mkosi.conf.d/10-arch/mkosi.conf
index 9cb45cc954..131f7d8e68 100644
--- a/mkosi.images/system/mkosi.conf.d/10-arch/mkosi.conf
+++ b/mkosi.images/system/mkosi.conf.d/10-arch/mkosi.conf
@@ -18,9 +18,11 @@ Packages=
btrfs-progs
compsize
cryptsetup
- dbus
+ dbus-broker
+ dbus-broker-units
dhcp
f2fs-tools
+ git
gnutls
iproute
linux
@@ -30,7 +32,6 @@ Packages=
openssl
pacman
polkit
- qrencode
quota-tools
sbsigntools
shadow
diff --git a/mkosi.images/system/mkosi.conf.d/10-centos-fedora/mkosi.conf b/mkosi.images/system/mkosi.conf.d/10-centos-fedora/mkosi.conf
index a9ee4a2906..c556aa8459 100644
--- a/mkosi.images/system/mkosi.conf.d/10-centos-fedora/mkosi.conf
+++ b/mkosi.images/system/mkosi.conf.d/10-centos-fedora/mkosi.conf
@@ -27,6 +27,7 @@ Packages=
cryptsetup
dhcp-server
dnf
+ git-core
gnutls
integritysetup
iproute
@@ -48,10 +49,12 @@ Packages=
rpm
rpm-build
rpmautospec
+ selinux-policy
+ selinux-policy-targeted
+ setools-console
+ policycoreutils
util-linux
vim-common
InitrdPackages=
- setools
- selinux-policy
tpm2-tools
diff --git a/mkosi.images/system/mkosi.conf.d/10-debian-ubuntu/mkosi.build.chroot b/mkosi.images/system/mkosi.conf.d/10-debian-ubuntu/mkosi.build.chroot
index 106b8ed4e6..e5224b8728 100755
--- a/mkosi.images/system/mkosi.conf.d/10-debian-ubuntu/mkosi.build.chroot
+++ b/mkosi.images/system/mkosi.conf.d/10-debian-ubuntu/mkosi.build.chroot
@@ -28,7 +28,7 @@ fi
# Add a new changelog entry to update the version. We use a fixed date since a dynamic one causes a full
# rebuild every time.
cat >debian/changelog.new <<EOF
-systemd ($(cat meson.version).$(date "+%Y%m%d%H%M%S" --date "@$TS")) UNRELEASED; urgency=low
+systemd ($(cat meson.version)-$(date "+%Y%m%d%H%M%S" --date "@$TS")) UNRELEASED; urgency=low
* Automatic build from mkosi
diff --git a/mkosi.images/system/mkosi.conf.d/10-debian-ubuntu/mkosi.conf b/mkosi.images/system/mkosi.conf.d/10-debian-ubuntu/mkosi.conf
index 07c9b3a805..e2be181fe2 100644
--- a/mkosi.images/system/mkosi.conf.d/10-debian-ubuntu/mkosi.conf
+++ b/mkosi.images/system/mkosi.conf.d/10-debian-ubuntu/mkosi.conf
@@ -26,16 +26,19 @@ Environment=
udev"
Packages=
+ ^libasan[0-9]+$
^libtss2-esys-[0-9.]+-0$
^libtss2-mu-[0-9.]+-0$
+ ^libubsan[0-9]+$
apt
btrfs-progs
cryptsetup-bin
dbus-broker
- default-dbus-session-bus
+ dbus-user-session
dmsetup
f2fs-tools
fdisk
+ git-core
iproute2
isc-dhcp-server
libcap-ng-utils
diff --git a/mkosi.images/system/mkosi.conf.d/10-opensuse/mkosi.conf b/mkosi.images/system/mkosi.conf.d/10-opensuse/mkosi.conf
index 45947a395b..2b14a6db0a 100644
--- a/mkosi.images/system/mkosi.conf.d/10-opensuse/mkosi.conf
+++ b/mkosi.images/system/mkosi.conf.d/10-opensuse/mkosi.conf
@@ -32,10 +32,13 @@ Packages=
docbook-xsl-stylesheets
f2fs-tools
gawk
+ git-core
glibc-locale-base
grep
gzip
kernel-kvmsmall
+ libasan8
+ libubsan1
openssh-clients
openssh-server
pam
diff --git a/mkosi.images/system/mkosi.conf.d/10-ubuntu/mkosi.conf b/mkosi.images/system/mkosi.conf.d/10-ubuntu/mkosi.conf
index 85126a1a37..957d00e429 100644
--- a/mkosi.images/system/mkosi.conf.d/10-ubuntu/mkosi.conf
+++ b/mkosi.images/system/mkosi.conf.d/10-ubuntu/mkosi.conf
@@ -5,7 +5,6 @@ Distribution=ubuntu
[Content]
Packages=
- # We would like to use linux-virtual but it does not have support for SMBIOS credentials.
- linux-image-generic
+ linux-image-virtual
linux-tools-common
- linux-tools-generic
+ linux-tools-virtual
diff --git a/pkg/centos b/pkg/centos
-Subproject 3cf45106c8bc5a050901851be6b2ac85b6f5c57
+Subproject eef64f0d4ddca0f151a9680660a9ba97604e0e8
diff --git a/pkg/debian b/pkg/debian
-Subproject 44fe1d4553f157aea4619a3dfed49f764b44f1a
+Subproject e780b50e79ab60f831d7aca0f01294b67a745a6
diff --git a/rules.d/99-systemd.rules.in b/rules.d/99-systemd.rules.in
index df52415a8f..ad0c7e2fb5 100644
--- a/rules.d/99-systemd.rules.in
+++ b/rules.d/99-systemd.rules.in
@@ -18,19 +18,18 @@ SUBSYSTEM=="ubi", TAG+="systemd"
SUBSYSTEM=="block", TAG+="systemd"
-# We can't make any conclusions about suspended DM devices so let's just import previous SYSTEMD_READY state and skip other rules
-SUBSYSTEM=="block", ENV{DM_SUSPENDED}=="1", IMPORT{db}="SYSTEMD_READY"
-SUBSYSTEM=="block", ENV{DM_SUSPENDED}=="1", GOTO="systemd_end"
+# When a dm device is first created, it's just an empty container. Ignore it.
+# DM_NAME is not set in this case, but it's set on spurious "add" events that occur later.
+SUBSYSTEM=="block", ACTION=="add", KERNEL=="dm-*", ENV{DM_NAME}!="?*", ENV{SYSTEMD_READY}="0"
-SUBSYSTEM=="block", ACTION=="add", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}=="1", ENV{SYSTEMD_READY}="0"
+# DM_UDEV_DISABLE_OTHER_RULES_FLAG==1 means that the device shouldn't be probed.
+# Import previous SYSTEMD_READY state.
+SUBSYSTEM=="block", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}=="1", ENV{SYSTEMD_READY}=="", IMPORT{db}="SYSTEMD_READY"
# Ignore encrypted devices with no identified superblock on it, since
# we are probably still calling mke2fs or mkswap on it.
SUBSYSTEM=="block", ENV{DM_UUID}=="CRYPT-*", ENV{ID_PART_TABLE_TYPE}=="", ENV{ID_FS_USAGE}=="", ENV{SYSTEMD_READY}="0"
-# Explicitly set SYSTEMD_READY=1 for DM devices that don't have it set yet, so that we always have something to import above
-SUBSYSTEM=="block", ENV{DM_UUID}=="?*", ENV{SYSTEMD_READY}=="", ENV{SYSTEMD_READY}="1"
-
# add symlink to GPT root disk
SUBSYSTEM=="block", ENV{ID_PART_GPT_AUTO_ROOT}=="1", ENV{ID_FS_TYPE}!="crypto_LUKS", SYMLINK+="gpt-auto-root"
SUBSYSTEM=="block", ENV{ID_PART_GPT_AUTO_ROOT}=="1", ENV{ID_FS_TYPE}=="crypto_LUKS", SYMLINK+="gpt-auto-root-luks"
diff --git a/src/backlight/backlight.c b/src/backlight/backlight.c
index 6126405994..2de6c2008a 100644
--- a/src/backlight/backlight.c
+++ b/src/backlight/backlight.c
@@ -55,6 +55,10 @@ static int has_multiple_graphics_cards(void) {
if (r < 0)
return r;
+ r = sd_device_enumerator_allow_uninitialized(e);
+ if (r < 0)
+ return r;
+
r = sd_device_enumerator_add_match_subsystem(e, "pci", /* match = */ true);
if (r < 0)
return r;
diff --git a/src/basic/dlfcn-util.c b/src/basic/dlfcn-util.c
index a321df3c67..8022f55294 100644
--- a/src/basic/dlfcn-util.c
+++ b/src/basic/dlfcn-util.c
@@ -49,6 +49,8 @@ int dlopen_many_sym_or_warn_sentinel(void **dlp, const char *filename, int log_l
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"%s is not installed: %s", filename, dlerror());
+ log_debug("Loaded '%s' via dlopen()", filename);
+
va_list ap;
va_start(ap, log_level);
r = dlsym_many_or_warnv(dl, log_level, ap);
diff --git a/src/basic/efivars.c b/src/basic/efivars.c
index fdc6c439bb..43f498de0f 100644
--- a/src/basic/efivars.c
+++ b/src/basic/efivars.c
@@ -177,12 +177,13 @@ static int efi_verify_variable(const char *variable, uint32_t attr, const void *
}
int efi_set_variable(const char *variable, const void *value, size_t size) {
+ static const uint32_t attr = EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS;
+
struct var {
uint32_t attr;
char buf[];
} _packed_ * _cleanup_free_ buf = NULL;
_cleanup_close_ int fd = -EBADF;
- uint32_t attr = EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS;
bool saved_flags_valid = false;
unsigned saved_flags;
int r;
@@ -190,14 +191,14 @@ int efi_set_variable(const char *variable, const void *value, size_t size) {
assert(variable);
assert(value || size == 0);
- const char *p = strjoina("/sys/firmware/efi/efivars/", variable);
-
/* size 0 means removal, empty variable would not be enough for that */
if (size > 0 && efi_verify_variable(variable, attr, value, size) > 0) {
log_debug("Variable '%s' is already in wanted state, skipping write.", variable);
return 0;
}
+ const char *p = strjoina("/sys/firmware/efi/efivars/", variable);
+
/* Newer efivarfs protects variables that are not in an allow list with FS_IMMUTABLE_FL by default,
* to protect them for accidental removal and modification. We are not changing these variables
* accidentally however, hence let's unset the bit first. */
@@ -238,10 +239,10 @@ int efi_set_variable(const char *variable, const void *value, size_t size) {
/* For some reason efivarfs doesn't update mtime automatically. Let's do it manually then. This is
* useful for processes that cache EFI variables to detect when changes occurred. */
- if (futimens(fd, (struct timespec[2]) {
+ if (futimens(fd, (const struct timespec[2]) {
{ .tv_nsec = UTIME_NOW },
{ .tv_nsec = UTIME_NOW }
- }) < 0)
+ }) < 0)
log_debug_errno(errno, "Failed to update mtime/atime on %s, ignoring: %m", p);
r = 0;
diff --git a/src/basic/gcrypt-util.c b/src/basic/gcrypt-util.c
index 41c9362be1..081866537c 100644
--- a/src/basic/gcrypt-util.c
+++ b/src/basic/gcrypt-util.c
@@ -5,41 +5,125 @@
#include "gcrypt-util.h"
#include "hexdecoct.h"
-void initialize_libgcrypt(bool secmem) {
- if (gcry_control(GCRYCTL_INITIALIZATION_FINISHED_P))
- return;
+static void *gcrypt_dl = NULL;
- gcry_control(GCRYCTL_SET_PREFERRED_RNG_TYPE, GCRY_RNG_TYPE_SYSTEM);
- assert_se(gcry_check_version("1.4.5"));
+static DLSYM_FUNCTION(gcry_control);
+static DLSYM_FUNCTION(gcry_check_version);
+DLSYM_FUNCTION(gcry_md_close);
+DLSYM_FUNCTION(gcry_md_copy);
+DLSYM_FUNCTION(gcry_md_ctl);
+DLSYM_FUNCTION(gcry_md_get_algo_dlen);
+DLSYM_FUNCTION(gcry_md_open);
+DLSYM_FUNCTION(gcry_md_read);
+DLSYM_FUNCTION(gcry_md_reset);
+DLSYM_FUNCTION(gcry_md_setkey);
+DLSYM_FUNCTION(gcry_md_write);
+DLSYM_FUNCTION(gcry_mpi_add);
+DLSYM_FUNCTION(gcry_mpi_add_ui);
+DLSYM_FUNCTION(gcry_mpi_cmp);
+DLSYM_FUNCTION(gcry_mpi_cmp_ui);
+DLSYM_FUNCTION(gcry_mpi_get_nbits);
+DLSYM_FUNCTION(gcry_mpi_invm);
+DLSYM_FUNCTION(gcry_mpi_mod);
+DLSYM_FUNCTION(gcry_mpi_mul);
+DLSYM_FUNCTION(gcry_mpi_mulm);
+DLSYM_FUNCTION(gcry_mpi_new);
+DLSYM_FUNCTION(gcry_mpi_powm);
+DLSYM_FUNCTION(gcry_mpi_print);
+DLSYM_FUNCTION(gcry_mpi_release);
+DLSYM_FUNCTION(gcry_mpi_scan);
+DLSYM_FUNCTION(gcry_mpi_set_ui);
+DLSYM_FUNCTION(gcry_mpi_sub);
+DLSYM_FUNCTION(gcry_mpi_subm);
+DLSYM_FUNCTION(gcry_mpi_sub_ui);
+DLSYM_FUNCTION(gcry_prime_check);
+DLSYM_FUNCTION(gcry_randomize);
+DLSYM_FUNCTION(gcry_strerror);
+
+static int dlopen_gcrypt(void) {
+ return dlopen_many_sym_or_warn(
+ &gcrypt_dl,
+ "libgcrypt.so.20", LOG_DEBUG,
+ DLSYM_ARG(gcry_control),
+ DLSYM_ARG(gcry_check_version),
+ DLSYM_ARG(gcry_md_close),
+ DLSYM_ARG(gcry_md_copy),
+ DLSYM_ARG(gcry_md_ctl),
+ DLSYM_ARG(gcry_md_get_algo_dlen),
+ DLSYM_ARG(gcry_md_open),
+ DLSYM_ARG(gcry_md_read),
+ DLSYM_ARG(gcry_md_reset),
+ DLSYM_ARG(gcry_md_setkey),
+ DLSYM_ARG(gcry_md_write),
+ DLSYM_ARG(gcry_mpi_add),
+ DLSYM_ARG(gcry_mpi_add_ui),
+ DLSYM_ARG(gcry_mpi_cmp),
+ DLSYM_ARG(gcry_mpi_cmp_ui),
+ DLSYM_ARG(gcry_mpi_get_nbits),
+ DLSYM_ARG(gcry_mpi_invm),
+ DLSYM_ARG(gcry_mpi_mod),
+ DLSYM_ARG(gcry_mpi_mul),
+ DLSYM_ARG(gcry_mpi_mulm),
+ DLSYM_ARG(gcry_mpi_new),
+ DLSYM_ARG(gcry_mpi_powm),
+ DLSYM_ARG(gcry_mpi_print),
+ DLSYM_ARG(gcry_mpi_release),
+ DLSYM_ARG(gcry_mpi_scan),
+ DLSYM_ARG(gcry_mpi_set_ui),
+ DLSYM_ARG(gcry_mpi_sub),
+ DLSYM_ARG(gcry_mpi_subm),
+ DLSYM_ARG(gcry_mpi_sub_ui),
+ DLSYM_ARG(gcry_prime_check),
+ DLSYM_ARG(gcry_randomize),
+ DLSYM_ARG(gcry_strerror));
+}
+
+int initialize_libgcrypt(bool secmem) {
+ int r;
+
+ r = dlopen_gcrypt();
+ if (r < 0)
+ return r;
+
+ if (sym_gcry_control(GCRYCTL_INITIALIZATION_FINISHED_P))
+ return 0;
+
+ sym_gcry_control(GCRYCTL_SET_PREFERRED_RNG_TYPE, GCRY_RNG_TYPE_SYSTEM);
+ assert_se(sym_gcry_check_version("1.4.5"));
/* Turn off "secmem". Clients which wish to make use of this
* feature should initialize the library manually */
if (!secmem)
- gcry_control(GCRYCTL_DISABLE_SECMEM);
+ sym_gcry_control(GCRYCTL_DISABLE_SECMEM);
- gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
+ sym_gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
+
+ return 0;
}
# if !PREFER_OPENSSL
int string_hashsum(const char *s, size_t len, int md_algorithm, char **out) {
- _cleanup_(gcry_md_closep) gcry_md_hd_t md = NULL;
+ _cleanup_(sym_gcry_md_closep) gcry_md_hd_t md = NULL;
gcry_error_t err;
size_t hash_size;
void *hash;
char *enc;
+ int r;
- initialize_libgcrypt(false);
+ r = initialize_libgcrypt(false);
+ if (r < 0)
+ return r;
- hash_size = gcry_md_get_algo_dlen(md_algorithm);
+ hash_size = sym_gcry_md_get_algo_dlen(md_algorithm);
assert(hash_size > 0);
- err = gcry_md_open(&md, md_algorithm, 0);
+ err = sym_gcry_md_open(&md, md_algorithm, 0);
if (gcry_err_code(err) != GPG_ERR_NO_ERROR || !md)
return -EIO;
- gcry_md_write(md, s, len);
+ sym_gcry_md_write(md, s, len);
- hash = gcry_md_read(md, 0);
+ hash = sym_gcry_md_read(md, 0);
if (!hash)
return -EIO;
diff --git a/src/basic/gcrypt-util.h b/src/basic/gcrypt-util.h
index 4c40cefbed..acb50e84b7 100644
--- a/src/basic/gcrypt-util.h
+++ b/src/basic/gcrypt-util.h
@@ -9,11 +9,59 @@
#if HAVE_GCRYPT
#include <gcrypt.h>
+#include "dlfcn-util.h"
#include "macro.h"
-void initialize_libgcrypt(bool secmem);
+DLSYM_PROTOTYPE(gcry_md_close);
+DLSYM_PROTOTYPE(gcry_md_copy);
+DLSYM_PROTOTYPE(gcry_md_ctl);
+DLSYM_PROTOTYPE(gcry_md_get_algo_dlen);
+DLSYM_PROTOTYPE(gcry_md_open);
+DLSYM_PROTOTYPE(gcry_md_read);
+DLSYM_PROTOTYPE(gcry_md_reset);
+DLSYM_PROTOTYPE(gcry_md_setkey);
+DLSYM_PROTOTYPE(gcry_md_write);
+DLSYM_PROTOTYPE(gcry_mpi_add);
+DLSYM_PROTOTYPE(gcry_mpi_add_ui);
+DLSYM_PROTOTYPE(gcry_mpi_cmp);
+DLSYM_PROTOTYPE(gcry_mpi_cmp_ui);
+DLSYM_PROTOTYPE(gcry_mpi_get_nbits);
+DLSYM_PROTOTYPE(gcry_mpi_invm);
+DLSYM_PROTOTYPE(gcry_mpi_mod);
+DLSYM_PROTOTYPE(gcry_mpi_mul);
+DLSYM_PROTOTYPE(gcry_mpi_mulm);
+DLSYM_PROTOTYPE(gcry_mpi_new);
+DLSYM_PROTOTYPE(gcry_mpi_powm);
+DLSYM_PROTOTYPE(gcry_mpi_print);
+DLSYM_PROTOTYPE(gcry_mpi_release);
+DLSYM_PROTOTYPE(gcry_mpi_scan);
+DLSYM_PROTOTYPE(gcry_mpi_set_ui);
+DLSYM_PROTOTYPE(gcry_mpi_sub);
+DLSYM_PROTOTYPE(gcry_mpi_subm);
+DLSYM_PROTOTYPE(gcry_mpi_sub_ui);
+DLSYM_PROTOTYPE(gcry_prime_check);
+DLSYM_PROTOTYPE(gcry_randomize);
+DLSYM_PROTOTYPE(gcry_strerror);
+int initialize_libgcrypt(bool secmem);
+
+static inline gcry_md_hd_t* sym_gcry_md_closep(gcry_md_hd_t *md) {
+ if (!md || !*md)
+ return NULL;
+ sym_gcry_md_close(*md);
+
+ return NULL;
+}
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(gcry_md_hd_t, gcry_md_close, NULL);
+
+/* Copied from gcry_md_putc from gcrypt.h due to the need to call the sym_ variant */
+#define sym_gcry_md_putc(h,c) \
+ do { \
+ gcry_md_hd_t h__ = (h); \
+ if ((h__)->bufpos == (h__)->bufsize) \
+ sym_gcry_md_write((h__), NULL, 0); \
+ (h__)->buf[(h__)->bufpos++] = (c) & 0xff; \
+ } while(false)
#endif
#if !PREFER_OPENSSL
diff --git a/src/basic/meson.build b/src/basic/meson.build
index ced027ba83..1516a9f7af 100644
--- a/src/basic/meson.build
+++ b/src/basic/meson.build
@@ -35,6 +35,7 @@ basic_sources = files(
'filesystems.c',
'format-util.c',
'fs-util.c',
+ 'gcrypt-util.c',
'glob-util.c',
'glyph-util.c',
'gunicode.c',
@@ -277,6 +278,7 @@ libbasic = static_library(
include_directories : basic_includes,
dependencies : [libcap,
libdl,
+ libgcrypt_cflags,
liblz4_cflags,
libm,
librt,
@@ -286,20 +288,3 @@ libbasic = static_library(
userspace],
c_args : ['-fvisibility=default'],
build_by_default : false)
-
-############################################################
-
-basic_gcrypt_sources = files(
- 'gcrypt-util.c',
-)
-
-# A convenience library that is separate from libbasic to avoid
-# unnecessary linking to libgcrypt.
-libbasic_gcrypt = static_library(
- 'basic-gcrypt',
- basic_gcrypt_sources,
- include_directories : basic_includes,
- dependencies : [libgcrypt,
- userspace],
- c_args : ['-fvisibility=default'],
- build_by_default : false)
diff --git a/src/basic/signal-util.c b/src/basic/signal-util.c
index 661ad00b11..27d094b7bd 100644
--- a/src/basic/signal-util.c
+++ b/src/basic/signal-util.c
@@ -268,7 +268,7 @@ int pop_pending_signal_internal(int sig, ...) {
if (r < 0)
return r;
- r = sigtimedwait(&ss, NULL, &(struct timespec) { 0, 0 });
+ r = sigtimedwait(&ss, NULL, &(const struct timespec) {});
if (r < 0) {
if (errno == EAGAIN)
return 0;
diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c
index 5eb8e4c988..537f1e8c64 100644
--- a/src/basic/socket-util.c
+++ b/src/basic/socket-util.c
@@ -634,7 +634,7 @@ int socknameinfo_pretty(const struct sockaddr *sa, socklen_t salen, char **ret)
int r;
assert(sa);
- assert(salen > sizeof(sa_family_t));
+ assert(salen >= sizeof(sa_family_t));
assert(ret);
r = getnameinfo(sa, salen, host, sizeof(host), /* service= */ NULL, /* service_len= */ 0, IDN_FLAGS);
diff --git a/src/basic/string-util.c b/src/basic/string-util.c
index 7f6c87b461..f3ab2dc222 100644
--- a/src/basic/string-util.c
+++ b/src/basic/string-util.c
@@ -562,7 +562,9 @@ char *cellescape(char *buf, size_t len, const char *s) {
size_t i = 0, last_char_width[4] = {}, k = 0;
+ assert(buf);
assert(len > 0); /* at least a terminating NUL */
+ assert(s);
for (;;) {
char four[4];
@@ -612,7 +614,7 @@ char *cellescape(char *buf, size_t len, const char *s) {
else
assert(i + 1 <= len);
- done:
+done:
buf[i] = '\0';
return buf;
}
@@ -1268,18 +1270,16 @@ int string_extract_line(const char *s, size_t i, char **ret) {
}
}
-int string_contains_word_strv(const char *string, const char *separators, char **words, const char **ret_word) {
- /* In the default mode with no separators specified, we split on whitespace and
- * don't coalesce separators. */
+int string_contains_word_strv(const char *string, const char *separators, char * const *words, const char **ret_word) {
+ /* In the default mode with no separators specified, we split on whitespace and coalesce separators. */
const ExtractFlags flags = separators ? EXTRACT_DONT_COALESCE_SEPARATORS : 0;
-
const char *found = NULL;
+ int r;
- for (const char *p = string;;) {
+ for (;;) {
_cleanup_free_ char *w = NULL;
- int r;
- r = extract_first_word(&p, &w, separators, flags);
+ r = extract_first_word(&string, &w, separators, flags);
if (r < 0)
return r;
if (r == 0)
diff --git a/src/basic/string-util.h b/src/basic/string-util.h
index a68f3c94ab..055ab66668 100644
--- a/src/basic/string-util.h
+++ b/src/basic/string-util.h
@@ -271,7 +271,7 @@ char* string_erase(char *x);
int string_truncate_lines(const char *s, size_t n_lines, char **ret);
int string_extract_line(const char *s, size_t i, char **ret);
-int string_contains_word_strv(const char *string, const char *separators, char **words, const char **ret_word);
+int string_contains_word_strv(const char *string, const char *separators, char * const *words, const char **ret_word);
static inline int string_contains_word(const char *string, const char *separators, const char *word) {
return string_contains_word_strv(string, separators, STRV_MAKE(word), NULL);
}
diff --git a/src/basic/time-util.h b/src/basic/time-util.h
index a3c219ecdd..ebcdc41118 100644
--- a/src/basic/time-util.h
+++ b/src/basic/time-util.h
@@ -71,8 +71,8 @@ typedef enum TimestampStyle {
#define TIME_T_MAX (time_t)((UINTMAX_C(1) << ((sizeof(time_t) << 3) - 1)) - 1)
-#define DUAL_TIMESTAMP_NULL ((struct dual_timestamp) {})
-#define TRIPLE_TIMESTAMP_NULL ((struct triple_timestamp) {})
+#define DUAL_TIMESTAMP_NULL ((dual_timestamp) {})
+#define TRIPLE_TIMESTAMP_NULL ((triple_timestamp) {})
usec_t now(clockid_t clock);
nsec_t now_nsec(clockid_t clock);
diff --git a/src/basic/unit-def.c b/src/basic/unit-def.c
index 9bc4920998..d03363bd37 100644
--- a/src/basic/unit-def.c
+++ b/src/basic/unit-def.c
@@ -99,7 +99,7 @@ static const char* const unit_load_state_table[_UNIT_LOAD_STATE_MAX] = {
[UNIT_BAD_SETTING] = "bad-setting",
[UNIT_ERROR] = "error",
[UNIT_MERGED] = "merged",
- [UNIT_MASKED] = "masked"
+ [UNIT_MASKED] = "masked",
};
DEFINE_STRING_TABLE_LOOKUP(unit_load_state, UnitLoadState);
@@ -155,7 +155,7 @@ static const char* const automount_state_table[_AUTOMOUNT_STATE_MAX] = {
[AUTOMOUNT_DEAD] = "dead",
[AUTOMOUNT_WAITING] = "waiting",
[AUTOMOUNT_RUNNING] = "running",
- [AUTOMOUNT_FAILED] = "failed"
+ [AUTOMOUNT_FAILED] = "failed",
};
DEFINE_STRING_TABLE_LOOKUP(automount_state, AutomountState);
@@ -189,7 +189,7 @@ static const char* const path_state_table[_PATH_STATE_MAX] = {
[PATH_DEAD] = "dead",
[PATH_WAITING] = "waiting",
[PATH_RUNNING] = "running",
- [PATH_FAILED] = "failed"
+ [PATH_FAILED] = "failed",
};
DEFINE_STRING_TABLE_LOOKUP(path_state, PathState);
@@ -238,7 +238,7 @@ DEFINE_STRING_TABLE_LOOKUP(service_state, ServiceState);
static const char* const slice_state_table[_SLICE_STATE_MAX] = {
[SLICE_DEAD] = "dead",
- [SLICE_ACTIVE] = "active"
+ [SLICE_ACTIVE] = "active",
};
DEFINE_STRING_TABLE_LOOKUP(slice_state, SliceState);
@@ -278,7 +278,7 @@ DEFINE_STRING_TABLE_LOOKUP(swap_state, SwapState);
static const char* const target_state_table[_TARGET_STATE_MAX] = {
[TARGET_DEAD] = "dead",
- [TARGET_ACTIVE] = "active"
+ [TARGET_ACTIVE] = "active",
};
DEFINE_STRING_TABLE_LOOKUP(target_state, TargetState);
@@ -288,7 +288,7 @@ static const char* const timer_state_table[_TIMER_STATE_MAX] = {
[TIMER_WAITING] = "waiting",
[TIMER_RUNNING] = "running",
[TIMER_ELAPSED] = "elapsed",
- [TIMER_FAILED] = "failed"
+ [TIMER_FAILED] = "failed",
};
DEFINE_STRING_TABLE_LOOKUP(timer_state, TimerState);
@@ -333,7 +333,7 @@ static const char* const notify_access_table[_NOTIFY_ACCESS_MAX] = {
[NOTIFY_NONE] = "none",
[NOTIFY_MAIN] = "main",
[NOTIFY_EXEC] = "exec",
- [NOTIFY_ALL] = "all"
+ [NOTIFY_ALL] = "all",
};
DEFINE_STRING_TABLE_LOOKUP(notify_access, NotifyAccess);
diff --git a/src/core/automount.c b/src/core/automount.c
index 8c5a57588d..6cb9d525c2 100644
--- a/src/core/automount.c
+++ b/src/core/automount.c
@@ -38,10 +38,10 @@
#include "unit.h"
static const UnitActiveState state_translation_table[_AUTOMOUNT_STATE_MAX] = {
- [AUTOMOUNT_DEAD] = UNIT_INACTIVE,
+ [AUTOMOUNT_DEAD] = UNIT_INACTIVE,
[AUTOMOUNT_WAITING] = UNIT_ACTIVE,
[AUTOMOUNT_RUNNING] = UNIT_ACTIVE,
- [AUTOMOUNT_FAILED] = UNIT_FAILED
+ [AUTOMOUNT_FAILED] = UNIT_FAILED,
};
static int open_dev_autofs(Manager *m);
diff --git a/src/core/cgroup.c b/src/core/cgroup.c
index fdca434df9..852a16622f 100644
--- a/src/core/cgroup.c
+++ b/src/core/cgroup.c
@@ -5128,7 +5128,7 @@ int unit_cgroup_freezer_action(Unit *u, FreezerAction action) {
CGroupRuntime *crt = unit_get_cgroup_runtime(u);
if (!crt || !crt->cgroup_realized)
- return -EBUSY;
+ return 0; /* No cgroup = nothing running to freeze */
unit_next_freezer_state(u, action, &next, &target);
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
index bba466b900..fa85a5e698 100644
--- a/src/core/dbus-manager.c
+++ b/src/core/dbus-manager.c
@@ -1599,7 +1599,7 @@ static int method_reload(sd_bus_message *message, void *userdata, sd_bus_error *
log_caller(message, m, "Reloading");
/* Check the rate limit after the authorization succeeds, to avoid denial-of-service issues. */
- if (!ratelimit_below(&m->reload_ratelimit)) {
+ if (!ratelimit_below(&m->reload_reexec_ratelimit)) {
log_warning("Reloading request rejected due to rate limit.");
return sd_bus_error_setf(error,
SD_BUS_ERROR_LIMITS_EXCEEDED,
@@ -1644,6 +1644,14 @@ static int method_reexecute(sd_bus_message *message, void *userdata, sd_bus_erro
/* Write a log message noting the unit or process who requested the Reexecute() */
log_caller(message, m, "Reexecuting");
+ /* Check the rate limit after the authorization succeeds, to avoid denial-of-service issues. */
+ if (!ratelimit_below(&m->reload_reexec_ratelimit)) {
+ log_warning("Reexecuting request rejected due to rate limit.");
+ return sd_bus_error_setf(error,
+ SD_BUS_ERROR_LIMITS_EXCEEDED,
+ "Reexecute() request rejected due to rate limit.");
+ }
+
/* We don't send a reply back here, the client should
* just wait for us disconnecting. */
diff --git a/src/core/device.c b/src/core/device.c
index 93cab92b8c..d8567676a7 100644
--- a/src/core/device.c
+++ b/src/core/device.c
@@ -1051,6 +1051,9 @@ static void device_enumerate(Manager *m) {
_cleanup_set_free_ Set *ready_units = NULL, *not_ready_units = NULL;
Device *d;
+ if (device_is_processed(dev) <= 0)
+ continue;
+
if (device_setup_units(m, dev, &ready_units, &not_ready_units) < 0)
continue;
diff --git a/src/core/emergency-action.c b/src/core/emergency-action.c
index e2cd931671..3083320966 100644
--- a/src/core/emergency-action.c
+++ b/src/core/emergency-action.c
@@ -13,22 +13,22 @@
#include "virt.h"
static const char* const emergency_action_table[_EMERGENCY_ACTION_MAX] = {
- [EMERGENCY_ACTION_NONE] = "none",
- [EMERGENCY_ACTION_REBOOT] = "reboot",
- [EMERGENCY_ACTION_REBOOT_FORCE] = "reboot-force",
- [EMERGENCY_ACTION_REBOOT_IMMEDIATE] = "reboot-immediate",
- [EMERGENCY_ACTION_POWEROFF] = "poweroff",
- [EMERGENCY_ACTION_POWEROFF_FORCE] = "poweroff-force",
+ [EMERGENCY_ACTION_NONE] = "none",
+ [EMERGENCY_ACTION_REBOOT] = "reboot",
+ [EMERGENCY_ACTION_REBOOT_FORCE] = "reboot-force",
+ [EMERGENCY_ACTION_REBOOT_IMMEDIATE] = "reboot-immediate",
+ [EMERGENCY_ACTION_POWEROFF] = "poweroff",
+ [EMERGENCY_ACTION_POWEROFF_FORCE] = "poweroff-force",
[EMERGENCY_ACTION_POWEROFF_IMMEDIATE] = "poweroff-immediate",
- [EMERGENCY_ACTION_EXIT] = "exit",
- [EMERGENCY_ACTION_EXIT_FORCE] = "exit-force",
- [EMERGENCY_ACTION_SOFT_REBOOT] = "soft-reboot",
- [EMERGENCY_ACTION_SOFT_REBOOT_FORCE] = "soft-reboot-force",
- [EMERGENCY_ACTION_KEXEC] = "kexec",
- [EMERGENCY_ACTION_KEXEC_FORCE] = "kexec-force",
- [EMERGENCY_ACTION_HALT] = "halt",
- [EMERGENCY_ACTION_HALT_FORCE] = "halt-force",
- [EMERGENCY_ACTION_HALT_IMMEDIATE] = "halt-immediate",
+ [EMERGENCY_ACTION_EXIT] = "exit",
+ [EMERGENCY_ACTION_EXIT_FORCE] = "exit-force",
+ [EMERGENCY_ACTION_SOFT_REBOOT] = "soft-reboot",
+ [EMERGENCY_ACTION_SOFT_REBOOT_FORCE] = "soft-reboot-force",
+ [EMERGENCY_ACTION_KEXEC] = "kexec",
+ [EMERGENCY_ACTION_KEXEC_FORCE] = "kexec-force",
+ [EMERGENCY_ACTION_HALT] = "halt",
+ [EMERGENCY_ACTION_HALT_FORCE] = "halt-force",
+ [EMERGENCY_ACTION_HALT_IMMEDIATE] = "halt-immediate",
};
static void log_and_status(Manager *m, bool warn, const char *message, const char *reason) {
diff --git a/src/core/exec-invoke.c b/src/core/exec-invoke.c
index 47339bddaf..ee2c1247a9 100644
--- a/src/core/exec-invoke.c
+++ b/src/core/exec-invoke.c
@@ -1771,10 +1771,10 @@ static const char *exec_directory_env_name_to_string(ExecDirectoryType t);
/* And this table also maps ExecDirectoryType, to the environment variable we pass the selected directory to
* the service payload in. */
static const char* const exec_directory_env_name_table[_EXEC_DIRECTORY_TYPE_MAX] = {
- [EXEC_DIRECTORY_RUNTIME] = "RUNTIME_DIRECTORY",
- [EXEC_DIRECTORY_STATE] = "STATE_DIRECTORY",
- [EXEC_DIRECTORY_CACHE] = "CACHE_DIRECTORY",
- [EXEC_DIRECTORY_LOGS] = "LOGS_DIRECTORY",
+ [EXEC_DIRECTORY_RUNTIME] = "RUNTIME_DIRECTORY",
+ [EXEC_DIRECTORY_STATE] = "STATE_DIRECTORY",
+ [EXEC_DIRECTORY_CACHE] = "CACHE_DIRECTORY",
+ [EXEC_DIRECTORY_LOGS] = "LOGS_DIRECTORY",
[EXEC_DIRECTORY_CONFIGURATION] = "CONFIGURATION_DIRECTORY",
};
@@ -2269,10 +2269,10 @@ static int setup_exec_directory(
int *exit_status) {
static const int exit_status_table[_EXEC_DIRECTORY_TYPE_MAX] = {
- [EXEC_DIRECTORY_RUNTIME] = EXIT_RUNTIME_DIRECTORY,
- [EXEC_DIRECTORY_STATE] = EXIT_STATE_DIRECTORY,
- [EXEC_DIRECTORY_CACHE] = EXIT_CACHE_DIRECTORY,
- [EXEC_DIRECTORY_LOGS] = EXIT_LOGS_DIRECTORY,
+ [EXEC_DIRECTORY_RUNTIME] = EXIT_RUNTIME_DIRECTORY,
+ [EXEC_DIRECTORY_STATE] = EXIT_STATE_DIRECTORY,
+ [EXEC_DIRECTORY_CACHE] = EXIT_CACHE_DIRECTORY,
+ [EXEC_DIRECTORY_LOGS] = EXIT_LOGS_DIRECTORY,
[EXEC_DIRECTORY_CONFIGURATION] = EXIT_CONFIGURATION_DIRECTORY,
};
int r;
@@ -4302,13 +4302,20 @@ int exec_invoke(
return log_exec_error_errno(context, params, r, "Failed to set up standard input: %m");
}
- r = setup_output(context, params, STDOUT_FILENO, socket_fd, named_iofds, basename(command->path), uid, gid, &journal_stream_dev, &journal_stream_ino);
+ _cleanup_free_ char *fname = NULL;
+ r = path_extract_filename(command->path, &fname);
+ if (r < 0) {
+ *exit_status = EXIT_STDOUT;
+ return log_exec_error_errno(context, params, r, "Failed to extract filename from path %s: %m", command->path);
+ }
+
+ r = setup_output(context, params, STDOUT_FILENO, socket_fd, named_iofds, fname, uid, gid, &journal_stream_dev, &journal_stream_ino);
if (r < 0) {
*exit_status = EXIT_STDOUT;
return log_exec_error_errno(context, params, r, "Failed to set up standard output: %m");
}
- r = setup_output(context, params, STDERR_FILENO, socket_fd, named_iofds, basename(command->path), uid, gid, &journal_stream_dev, &journal_stream_ino);
+ r = setup_output(context, params, STDERR_FILENO, socket_fd, named_iofds, fname, uid, gid, &journal_stream_dev, &journal_stream_ino);
if (r < 0) {
*exit_status = EXIT_STDERR;
return log_exec_error_errno(context, params, r, "Failed to set up standard error output: %m");
diff --git a/src/core/execute-serialize.c b/src/core/execute-serialize.c
index 1ae77f39fb..9e402e5e69 100644
--- a/src/core/execute-serialize.c
+++ b/src/core/execute-serialize.c
@@ -2544,14 +2544,14 @@ static int exec_context_serialize(const ExecContext *c, FILE *f) {
if (base64mem(sc->data, sc->size, &data) < 0)
return log_oom_debug();
- r = serialize_item_format(f, "exec-context-set-credentials", "%s %s %s", sc->id, yes_no(sc->encrypted), data);
+ r = serialize_item_format(f, "exec-context-set-credentials", "%s %s %s", sc->id, data, yes_no(sc->encrypted));
if (r < 0)
return r;
}
ExecLoadCredential *lc;
HASHMAP_FOREACH(lc, c->load_credentials) {
- r = serialize_item_format(f, "exec-context-load-credentials", "%s %s %s", lc->id, yes_no(lc->encrypted), lc->path);
+ r = serialize_item_format(f, "exec-context-load-credentials", "%s %s %s", lc->id, lc->path, yes_no(lc->encrypted));
if (r < 0)
return r;
}
@@ -3668,7 +3668,7 @@ static int exec_context_deserialize(ExecContext *c, FILE *f) {
_cleanup_(exec_set_credential_freep) ExecSetCredential *sc = NULL;
_cleanup_free_ char *id = NULL, *encrypted = NULL, *data = NULL;
- r = extract_many_words(&val, " ", 0, &id, &encrypted, &data);
+ r = extract_many_words(&val, " ", EXTRACT_DONT_COALESCE_SEPARATORS, &id, &data, &encrypted);
if (r < 0)
return r;
if (r != 3)
@@ -3700,7 +3700,7 @@ static int exec_context_deserialize(ExecContext *c, FILE *f) {
_cleanup_(exec_load_credential_freep) ExecLoadCredential *lc = NULL;
_cleanup_free_ char *id = NULL, *encrypted = NULL, *path = NULL;
- r = extract_many_words(&val, " ", 0, &id, &encrypted, &path);
+ r = extract_many_words(&val, " ", EXTRACT_DONT_COALESCE_SEPARATORS, &id, &path, &encrypted);
if (r < 0)
return r;
if (r != 3)
diff --git a/src/core/execute.c b/src/core/execute.c
index 41b3b3f2b5..2ddfa7423d 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -2659,46 +2659,46 @@ ExecCleanMask exec_clean_mask_from_string(const char *s) {
}
static const char* const exec_input_table[_EXEC_INPUT_MAX] = {
- [EXEC_INPUT_NULL] = "null",
- [EXEC_INPUT_TTY] = "tty",
+ [EXEC_INPUT_NULL] = "null",
+ [EXEC_INPUT_TTY] = "tty",
[EXEC_INPUT_TTY_FORCE] = "tty-force",
- [EXEC_INPUT_TTY_FAIL] = "tty-fail",
- [EXEC_INPUT_SOCKET] = "socket",
- [EXEC_INPUT_NAMED_FD] = "fd",
- [EXEC_INPUT_DATA] = "data",
- [EXEC_INPUT_FILE] = "file",
+ [EXEC_INPUT_TTY_FAIL] = "tty-fail",
+ [EXEC_INPUT_SOCKET] = "socket",
+ [EXEC_INPUT_NAMED_FD] = "fd",
+ [EXEC_INPUT_DATA] = "data",
+ [EXEC_INPUT_FILE] = "file",
};
DEFINE_STRING_TABLE_LOOKUP(exec_input, ExecInput);
static const char* const exec_output_table[_EXEC_OUTPUT_MAX] = {
- [EXEC_OUTPUT_INHERIT] = "inherit",
- [EXEC_OUTPUT_NULL] = "null",
- [EXEC_OUTPUT_TTY] = "tty",
- [EXEC_OUTPUT_KMSG] = "kmsg",
- [EXEC_OUTPUT_KMSG_AND_CONSOLE] = "kmsg+console",
- [EXEC_OUTPUT_JOURNAL] = "journal",
+ [EXEC_OUTPUT_INHERIT] = "inherit",
+ [EXEC_OUTPUT_NULL] = "null",
+ [EXEC_OUTPUT_TTY] = "tty",
+ [EXEC_OUTPUT_KMSG] = "kmsg",
+ [EXEC_OUTPUT_KMSG_AND_CONSOLE] = "kmsg+console",
+ [EXEC_OUTPUT_JOURNAL] = "journal",
[EXEC_OUTPUT_JOURNAL_AND_CONSOLE] = "journal+console",
- [EXEC_OUTPUT_SOCKET] = "socket",
- [EXEC_OUTPUT_NAMED_FD] = "fd",
- [EXEC_OUTPUT_FILE] = "file",
- [EXEC_OUTPUT_FILE_APPEND] = "append",
- [EXEC_OUTPUT_FILE_TRUNCATE] = "truncate",
+ [EXEC_OUTPUT_SOCKET] = "socket",
+ [EXEC_OUTPUT_NAMED_FD] = "fd",
+ [EXEC_OUTPUT_FILE] = "file",
+ [EXEC_OUTPUT_FILE_APPEND] = "append",
+ [EXEC_OUTPUT_FILE_TRUNCATE] = "truncate",
};
DEFINE_STRING_TABLE_LOOKUP(exec_output, ExecOutput);
static const char* const exec_utmp_mode_table[_EXEC_UTMP_MODE_MAX] = {
- [EXEC_UTMP_INIT] = "init",
+ [EXEC_UTMP_INIT] = "init",
[EXEC_UTMP_LOGIN] = "login",
- [EXEC_UTMP_USER] = "user",
+ [EXEC_UTMP_USER] = "user",
};
DEFINE_STRING_TABLE_LOOKUP(exec_utmp_mode, ExecUtmpMode);
static const char* const exec_preserve_mode_table[_EXEC_PRESERVE_MODE_MAX] = {
- [EXEC_PRESERVE_NO] = "no",
- [EXEC_PRESERVE_YES] = "yes",
+ [EXEC_PRESERVE_NO] = "no",
+ [EXEC_PRESERVE_YES] = "yes",
[EXEC_PRESERVE_RESTART] = "restart",
};
@@ -2706,10 +2706,10 @@ DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(exec_preserve_mode, ExecPreserveMode, EX
/* This table maps ExecDirectoryType to the setting it is configured with in the unit */
static const char* const exec_directory_type_table[_EXEC_DIRECTORY_TYPE_MAX] = {
- [EXEC_DIRECTORY_RUNTIME] = "RuntimeDirectory",
- [EXEC_DIRECTORY_STATE] = "StateDirectory",
- [EXEC_DIRECTORY_CACHE] = "CacheDirectory",
- [EXEC_DIRECTORY_LOGS] = "LogsDirectory",
+ [EXEC_DIRECTORY_RUNTIME] = "RuntimeDirectory",
+ [EXEC_DIRECTORY_STATE] = "StateDirectory",
+ [EXEC_DIRECTORY_CACHE] = "CacheDirectory",
+ [EXEC_DIRECTORY_LOGS] = "LogsDirectory",
[EXEC_DIRECTORY_CONFIGURATION] = "ConfigurationDirectory",
};
@@ -2740,10 +2740,10 @@ DEFINE_STRING_TABLE_LOOKUP(exec_directory_type_mode, ExecDirectoryType);
* one is supposed to be generic enough to be used for unit types that don't use ExecContext and per-unit
* directories, specifically .timer units with their timestamp touch file. */
static const char* const exec_resource_type_table[_EXEC_DIRECTORY_TYPE_MAX] = {
- [EXEC_DIRECTORY_RUNTIME] = "runtime",
- [EXEC_DIRECTORY_STATE] = "state",
- [EXEC_DIRECTORY_CACHE] = "cache",
- [EXEC_DIRECTORY_LOGS] = "logs",
+ [EXEC_DIRECTORY_RUNTIME] = "runtime",
+ [EXEC_DIRECTORY_STATE] = "state",
+ [EXEC_DIRECTORY_CACHE] = "cache",
+ [EXEC_DIRECTORY_LOGS] = "logs",
[EXEC_DIRECTORY_CONFIGURATION] = "configuration",
};
@@ -2752,7 +2752,7 @@ DEFINE_STRING_TABLE_LOOKUP(exec_resource_type, ExecDirectoryType);
static const char* const exec_keyring_mode_table[_EXEC_KEYRING_MODE_MAX] = {
[EXEC_KEYRING_INHERIT] = "inherit",
[EXEC_KEYRING_PRIVATE] = "private",
- [EXEC_KEYRING_SHARED] = "shared",
+ [EXEC_KEYRING_SHARED] = "shared",
};
DEFINE_STRING_TABLE_LOOKUP(exec_keyring_mode, ExecKeyringMode);
diff --git a/src/core/main.c b/src/core/main.c
index 1aeab10ddb..6f91a15b22 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -810,8 +810,8 @@ static void set_manager_settings(Manager *m) {
m->cad_burst_action = arg_cad_burst_action;
/* Note that we don't do structured initialization here, otherwise it will reset the rate limit
* counter on every daemon-reload. */
- m->reload_ratelimit.interval = arg_reload_limit_interval_sec;
- m->reload_ratelimit.burst = arg_reload_limit_burst;
+ m->reload_reexec_ratelimit.interval = arg_reload_limit_interval_sec;
+ m->reload_reexec_ratelimit.burst = arg_reload_limit_burst;
manager_set_watchdog(m, WATCHDOG_RUNTIME, arg_runtime_watchdog);
manager_set_watchdog(m, WATCHDOG_REBOOT, arg_reboot_watchdog);
diff --git a/src/core/manager-serialize.c b/src/core/manager-serialize.c
index 284f4987a2..884332b324 100644
--- a/src/core/manager-serialize.c
+++ b/src/core/manager-serialize.c
@@ -156,6 +156,7 @@ int manager_serialize(
}
(void) serialize_ratelimit(f, "dump-ratelimit", &m->dump_ratelimit);
+ (void) serialize_ratelimit(f, "reload-reexec-ratelimit", &m->reload_reexec_ratelimit);
bus_track_serialize(m->subscribed, f, "subscribed");
@@ -519,6 +520,8 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
(void) varlink_server_deserialize_one(m->varlink_server, val, fds);
} else if ((val = startswith(l, "dump-ratelimit=")))
deserialize_ratelimit(&m->dump_ratelimit, "dump-ratelimit", val);
+ else if ((val = startswith(l, "reload-reexec-ratelimit=")))
+ deserialize_ratelimit(&m->reload_reexec_ratelimit, "reload-reexec-ratelimit", val);
else if ((val = startswith(l, "soft-reboots-count="))) {
unsigned n;
diff --git a/src/core/manager.c b/src/core/manager.c
index 97e54d68a4..0103c582b5 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -710,18 +710,18 @@ static int manager_setup_prefix(Manager *m) {
};
static const struct table_entry paths_system[_EXEC_DIRECTORY_TYPE_MAX] = {
- [EXEC_DIRECTORY_RUNTIME] = { SD_PATH_SYSTEM_RUNTIME, NULL },
- [EXEC_DIRECTORY_STATE] = { SD_PATH_SYSTEM_STATE_PRIVATE, NULL },
- [EXEC_DIRECTORY_CACHE] = { SD_PATH_SYSTEM_STATE_CACHE, NULL },
- [EXEC_DIRECTORY_LOGS] = { SD_PATH_SYSTEM_STATE_LOGS, NULL },
+ [EXEC_DIRECTORY_RUNTIME] = { SD_PATH_SYSTEM_RUNTIME, NULL },
+ [EXEC_DIRECTORY_STATE] = { SD_PATH_SYSTEM_STATE_PRIVATE, NULL },
+ [EXEC_DIRECTORY_CACHE] = { SD_PATH_SYSTEM_STATE_CACHE, NULL },
+ [EXEC_DIRECTORY_LOGS] = { SD_PATH_SYSTEM_STATE_LOGS, NULL },
[EXEC_DIRECTORY_CONFIGURATION] = { SD_PATH_SYSTEM_CONFIGURATION, NULL },
};
static const struct table_entry paths_user[_EXEC_DIRECTORY_TYPE_MAX] = {
- [EXEC_DIRECTORY_RUNTIME] = { SD_PATH_USER_RUNTIME, NULL },
- [EXEC_DIRECTORY_STATE] = { SD_PATH_USER_STATE_PRIVATE, NULL },
- [EXEC_DIRECTORY_CACHE] = { SD_PATH_USER_STATE_CACHE, NULL },
- [EXEC_DIRECTORY_LOGS] = { SD_PATH_USER_STATE_PRIVATE, "log" },
+ [EXEC_DIRECTORY_RUNTIME] = { SD_PATH_USER_RUNTIME, NULL },
+ [EXEC_DIRECTORY_STATE] = { SD_PATH_USER_STATE_PRIVATE, NULL },
+ [EXEC_DIRECTORY_CACHE] = { SD_PATH_USER_STATE_CACHE, NULL },
+ [EXEC_DIRECTORY_LOGS] = { SD_PATH_USER_STATE_PRIVATE, "log" },
[EXEC_DIRECTORY_CONFIGURATION] = { SD_PATH_USER_CONFIGURATION, NULL },
};
@@ -2586,22 +2586,17 @@ static void manager_invoke_notify_message(
UNIT_VTABLE(u)->notify_message(u, ucred, tags, fds);
else if (DEBUG_LOGGING) {
- _cleanup_free_ char *buf = NULL, *x = NULL, *y = NULL;
+ _cleanup_free_ char *joined = strv_join(tags, ", ");
+ char buf[CELLESCAPE_DEFAULT_LENGTH];
- buf = strv_join(tags, ", ");
- if (buf)
- x = ellipsize(buf, 20, 90);
- if (x)
- y = cescape(x);
-
- log_unit_debug(u, "Got notification message \"%s\", ignoring.", strnull(y));
+ log_unit_debug(u, "Got notification message from unexpected unit type, ignoring: %s",
+ joined ? cellescape(buf, sizeof(buf), joined) : "(null)");
}
}
static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
-
- _cleanup_fdset_free_ FDSet *fds = NULL;
Manager *m = ASSERT_PTR(userdata);
+ _cleanup_fdset_free_ FDSet *fds = NULL;
char buf[NOTIFY_BUFFER_MAX+1];
struct iovec iovec = {
.iov_base = buf,
@@ -3008,9 +3003,9 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t
const char *target;
JobMode mode;
} target_table[] = {
- [0] = { SPECIAL_DEFAULT_TARGET, JOB_ISOLATE },
- [1] = { SPECIAL_RESCUE_TARGET, JOB_ISOLATE },
- [2] = { SPECIAL_EMERGENCY_TARGET, JOB_ISOLATE },
+ [0] = { SPECIAL_DEFAULT_TARGET, JOB_ISOLATE },
+ [1] = { SPECIAL_RESCUE_TARGET, JOB_ISOLATE },
+ [2] = { SPECIAL_EMERGENCY_TARGET, JOB_ISOLATE },
[3] = { SPECIAL_HALT_TARGET, JOB_REPLACE_IRREVERSIBLY },
[4] = { SPECIAL_POWEROFF_TARGET, JOB_REPLACE_IRREVERSIBLY },
[5] = { SPECIAL_REBOOT_TARGET, JOB_REPLACE_IRREVERSIBLY },
@@ -3915,8 +3910,8 @@ static int manager_run_environment_generators(Manager *m) {
_cleanup_strv_free_ char **paths = NULL;
void* args[] = {
[STDOUT_GENERATE] = &tmp,
- [STDOUT_COLLECT] = &tmp,
- [STDOUT_CONSUME] = &m->transient_environment,
+ [STDOUT_COLLECT] = &tmp,
+ [STDOUT_CONSUME] = &m->transient_environment,
};
int r;
diff --git a/src/core/manager.h b/src/core/manager.h
index 0e2531a4a7..9541a5e0b4 100644
--- a/src/core/manager.h
+++ b/src/core/manager.h
@@ -491,8 +491,8 @@ struct Manager {
/* Reference to RestrictFileSystems= BPF program */
struct restrict_fs_bpf *restrict_fs;
- /* Allow users to configure a rate limit for Reload() operations */
- RateLimit reload_ratelimit;
+ /* Allow users to configure a rate limit for Reload()/Reexecute() operations */
+ RateLimit reload_reexec_ratelimit;
/* Dump*() are slow, so always rate limit them to 10 per 10 minutes */
RateLimit dump_ratelimit;
diff --git a/src/core/mount.c b/src/core/mount.c
index 175af5498a..886ef8974c 100644
--- a/src/core/mount.c
+++ b/src/core/mount.c
@@ -39,23 +39,23 @@
#define RETRY_UMOUNT_MAX 32
static const UnitActiveState state_translation_table[_MOUNT_STATE_MAX] = {
- [MOUNT_DEAD] = UNIT_INACTIVE,
- [MOUNT_MOUNTING] = UNIT_ACTIVATING,
- [MOUNT_MOUNTING_DONE] = UNIT_ACTIVATING,
- [MOUNT_MOUNTED] = UNIT_ACTIVE,
- [MOUNT_REMOUNTING] = UNIT_RELOADING,
- [MOUNT_UNMOUNTING] = UNIT_DEACTIVATING,
+ [MOUNT_DEAD] = UNIT_INACTIVE,
+ [MOUNT_MOUNTING] = UNIT_ACTIVATING,
+ [MOUNT_MOUNTING_DONE] = UNIT_ACTIVATING,
+ [MOUNT_MOUNTED] = UNIT_ACTIVE,
+ [MOUNT_REMOUNTING] = UNIT_RELOADING,
+ [MOUNT_UNMOUNTING] = UNIT_DEACTIVATING,
[MOUNT_REMOUNTING_SIGTERM] = UNIT_RELOADING,
[MOUNT_REMOUNTING_SIGKILL] = UNIT_RELOADING,
[MOUNT_UNMOUNTING_SIGTERM] = UNIT_DEACTIVATING,
[MOUNT_UNMOUNTING_SIGKILL] = UNIT_DEACTIVATING,
- [MOUNT_FAILED] = UNIT_FAILED,
- [MOUNT_CLEANING] = UNIT_MAINTENANCE,
+ [MOUNT_FAILED] = UNIT_FAILED,
+ [MOUNT_CLEANING] = UNIT_MAINTENANCE,
};
static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
-static void mount_enter_dead(Mount *m, MountResult f);
+static void mount_enter_dead(Mount *m, MountResult f, bool flush_result);
static void mount_enter_mounted(Mount *m, MountResult f);
static void mount_cycle_clear(Mount *m);
static int mount_process_proc_self_mountinfo(Manager *m);
@@ -800,7 +800,7 @@ static void mount_catchup(Unit *u) {
break;
case MOUNT_MOUNTED:
assert(!pidref_is_set(&m->control_pid));
- mount_enter_dead(m, MOUNT_SUCCESS);
+ mount_enter_dead(m, MOUNT_SUCCESS, /* flush_result = */ false);
break;
default:
break;
@@ -899,10 +899,10 @@ static int mount_spawn(Mount *m, ExecCommand *c, PidRef *ret_pid) {
return 0;
}
-static void mount_enter_dead(Mount *m, MountResult f) {
+static void mount_enter_dead(Mount *m, MountResult f, bool flush_result) {
assert(m);
- if (m->result == MOUNT_SUCCESS)
+ if (m->result == MOUNT_SUCCESS || flush_result)
m->result = f;
unit_log_result(UNIT(m), m->result == MOUNT_SUCCESS, mount_result_to_string(m->result));
@@ -930,17 +930,20 @@ static void mount_enter_mounted(Mount *m, MountResult f) {
mount_set_state(m, MOUNT_MOUNTED);
}
-static void mount_enter_dead_or_mounted(Mount *m, MountResult f) {
+static void mount_enter_dead_or_mounted(Mount *m, MountResult f, bool flush_result) {
assert(m);
- /* Enter DEAD or MOUNTED state, depending on what the kernel currently says about the mount point. We use this
- * whenever we executed an operation, so that our internal state reflects what the kernel says again, after all
- * ultimately we just mirror the kernel's internal state on this. */
+ /* Enter DEAD or MOUNTED state, depending on what the kernel currently says about the mount point.
+ * We use this whenever we executed an operation, so that our internal state reflects what
+ * the kernel says again, after all ultimately we just mirror the kernel's internal state on this.
+ *
+ * Note that flush_result only applies to mount_enter_dead(), since that's when the result gets
+ * turned into unit end state. */
if (m->from_proc_self_mountinfo)
mount_enter_mounted(m, f);
else
- mount_enter_dead(m, f);
+ mount_enter_dead(m, f, flush_result);
}
static int state_to_kill_operation(MountState state) {
@@ -990,12 +993,12 @@ static void mount_enter_signal(Mount *m, MountState state, MountResult f) {
else if (state == MOUNT_UNMOUNTING_SIGTERM && m->kill_context.send_sigkill)
mount_enter_signal(m, MOUNT_UNMOUNTING_SIGKILL, MOUNT_SUCCESS);
else
- mount_enter_dead_or_mounted(m, MOUNT_SUCCESS);
+ mount_enter_dead_or_mounted(m, MOUNT_SUCCESS, /* flush_result = */ false);
return;
fail:
- mount_enter_dead_or_mounted(m, MOUNT_FAILURE_RESOURCES);
+ mount_enter_dead_or_mounted(m, MOUNT_FAILURE_RESOURCES, /* flush_result = */ false);
}
static int mount_set_umount_command(Mount *m, ExecCommand *c) {
@@ -1057,7 +1060,7 @@ static void mount_enter_unmounting(Mount *m) {
return;
fail:
- mount_enter_dead_or_mounted(m, MOUNT_FAILURE_RESOURCES);
+ mount_enter_dead_or_mounted(m, MOUNT_FAILURE_RESOURCES, /* flush_result = */ false);
}
static int mount_set_mount_command(Mount *m, ExecCommand *c, const MountParameters *p) {
@@ -1201,7 +1204,7 @@ static void mount_enter_mounting(Mount *m) {
return;
fail:
- mount_enter_dead_or_mounted(m, MOUNT_FAILURE_RESOURCES);
+ mount_enter_dead_or_mounted(m, MOUNT_FAILURE_RESOURCES, /* flush_result = */ false);
}
static void mount_set_reload_result(Mount *m, MountResult result) {
@@ -1267,7 +1270,7 @@ static void mount_enter_remounting(Mount *m) {
fail:
mount_set_reload_result(m, MOUNT_FAILURE_RESOURCES);
- mount_enter_dead_or_mounted(m, MOUNT_SUCCESS);
+ mount_enter_dead_or_mounted(m, MOUNT_SUCCESS, /* flush_result = */ false);
}
static void mount_cycle_clear(Mount *m) {
@@ -1435,8 +1438,8 @@ static int mount_deserialize_item(Unit *u, const char *key, const char *value, F
} else if (streq(key, "control-pid")) {
- pidref_done(&m->control_pid);
- (void) deserialize_pidref(fds, value, &m->control_pid);
+ if (!pidref_is_set(&m->control_pid))
+ (void) deserialize_pidref(fds, value, &m->control_pid);
} else if (streq(key, "control-command")) {
MountExecCommand id;
@@ -1547,7 +1550,7 @@ static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) {
log_unit_warning(UNIT(m), "Mount process finished, but there is no mount.");
f = MOUNT_FAILURE_PROTOCOL;
}
- mount_enter_dead(m, f);
+ mount_enter_dead(m, f, /* flush_result = */ false);
break;
case MOUNT_MOUNTING_DONE:
@@ -1557,7 +1560,7 @@ static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) {
case MOUNT_REMOUNTING:
case MOUNT_REMOUNTING_SIGTERM:
case MOUNT_REMOUNTING_SIGKILL:
- mount_enter_dead_or_mounted(m, MOUNT_SUCCESS);
+ mount_enter_dead_or_mounted(m, MOUNT_SUCCESS, /* flush_result = */ false);
break;
case MOUNT_UNMOUNTING:
@@ -1572,28 +1575,33 @@ static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) {
mount_enter_unmounting(m);
} else {
log_unit_warning(u, "Mount still present after %u attempts to unmount, giving up.", m->n_retry_umount);
- mount_enter_mounted(m, f);
+ mount_enter_mounted(m, MOUNT_FAILURE_PROTOCOL);
}
} else if (f == MOUNT_FAILURE_EXIT_CODE && !m->from_proc_self_mountinfo) {
/* Hmm, umount process spawned by us failed, but the mount disappeared anyway?
* Maybe someone else is trying to unmount at the same time. */
log_unit_notice(u, "Mount disappeared even though umount process failed, continuing.");
- mount_enter_dead(m, MOUNT_SUCCESS);
+ mount_enter_dead(m, MOUNT_SUCCESS, /* flush_result = */ true);
} else
- mount_enter_dead_or_mounted(m, f);
+ /* At this point, either the unmount succeeded or unexpected error occurred. We usually
+ * remember the first error in 'result', but here let's update that forcibly, since
+ * there could previous failed attempts yet we only care about the most recent
+ * attempt. IOW, if we eventually managed to unmount the stuff, don't enter failed
+ * end state. */
+ mount_enter_dead_or_mounted(m, f, /* flush_result = */ true);
break;
case MOUNT_UNMOUNTING_SIGTERM:
case MOUNT_UNMOUNTING_SIGKILL:
- mount_enter_dead_or_mounted(m, f);
+ mount_enter_dead_or_mounted(m, f, /* flush_result = */ false);
break;
case MOUNT_CLEANING:
if (m->clean_result == MOUNT_SUCCESS)
m->clean_result = f;
- mount_enter_dead(m, MOUNT_SUCCESS);
+ mount_enter_dead(m, MOUNT_SUCCESS, /* flush_result = */ false);
break;
default:
@@ -1631,7 +1639,7 @@ static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *user
mount_enter_signal(m, MOUNT_REMOUNTING_SIGKILL, MOUNT_SUCCESS);
} else {
log_unit_warning(UNIT(m), "Remounting timed out. Skipping SIGKILL. Ignoring.");
- mount_enter_dead_or_mounted(m, MOUNT_SUCCESS);
+ mount_enter_dead_or_mounted(m, MOUNT_SUCCESS, /* flush_result = */ false);
}
break;
@@ -1639,7 +1647,7 @@ static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *user
mount_set_reload_result(m, MOUNT_FAILURE_TIMEOUT);
log_unit_warning(UNIT(m), "Mount process still around after SIGKILL. Ignoring.");
- mount_enter_dead_or_mounted(m, MOUNT_SUCCESS);
+ mount_enter_dead_or_mounted(m, MOUNT_SUCCESS, /* flush_result = */ false);
break;
case MOUNT_UNMOUNTING:
@@ -1653,13 +1661,13 @@ static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *user
mount_enter_signal(m, MOUNT_UNMOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT);
} else {
log_unit_warning(UNIT(m), "Mount process timed out. Skipping SIGKILL. Ignoring.");
- mount_enter_dead_or_mounted(m, MOUNT_FAILURE_TIMEOUT);
+ mount_enter_dead_or_mounted(m, MOUNT_FAILURE_TIMEOUT, /* flush_result = */ false);
}
break;
case MOUNT_UNMOUNTING_SIGKILL:
log_unit_warning(UNIT(m), "Mount process still around after SIGKILL. Ignoring.");
- mount_enter_dead_or_mounted(m, MOUNT_FAILURE_TIMEOUT);
+ mount_enter_dead_or_mounted(m, MOUNT_FAILURE_TIMEOUT, /* flush_result = */ false);
break;
case MOUNT_CLEANING:
@@ -2121,8 +2129,11 @@ static int mount_process_proc_self_mountinfo(Manager *m) {
switch (mount->state) {
case MOUNT_MOUNTED:
- /* This has just been unmounted by somebody else, follow the state change. */
- mount_enter_dead(mount, MOUNT_SUCCESS);
+ /* This has just been unmounted by somebody else, follow the state change.
+ * Also explicitly override the result (see the comment in mount_sigchld_event()),
+ * but more aggressively here since the state change is extrinsic. */
+ mount_cycle_clear(mount);
+ mount_enter_dead(mount, MOUNT_SUCCESS, /* flush_result = */ true);
break;
case MOUNT_MOUNTING_DONE:
@@ -2290,7 +2301,7 @@ static int mount_can_start(Unit *u) {
r = unit_test_start_limit(u);
if (r < 0) {
- mount_enter_dead(m, MOUNT_FAILURE_START_LIMIT_HIT);
+ mount_enter_dead(m, MOUNT_FAILURE_START_LIMIT_HIT, /* flush_result = */ false);
return r;
}
diff --git a/src/core/scope.c b/src/core/scope.c
index edce590154..08319ac8f4 100644
--- a/src/core/scope.c
+++ b/src/core/scope.c
@@ -23,13 +23,13 @@
#include "user-util.h"
static const UnitActiveState state_translation_table[_SCOPE_STATE_MAX] = {
- [SCOPE_DEAD] = UNIT_INACTIVE,
- [SCOPE_START_CHOWN] = UNIT_ACTIVATING,
- [SCOPE_RUNNING] = UNIT_ACTIVE,
- [SCOPE_ABANDONED] = UNIT_ACTIVE,
+ [SCOPE_DEAD] = UNIT_INACTIVE,
+ [SCOPE_START_CHOWN] = UNIT_ACTIVATING,
+ [SCOPE_RUNNING] = UNIT_ACTIVE,
+ [SCOPE_ABANDONED] = UNIT_ACTIVE,
[SCOPE_STOP_SIGTERM] = UNIT_DEACTIVATING,
[SCOPE_STOP_SIGKILL] = UNIT_DEACTIVATING,
- [SCOPE_FAILED] = UNIT_FAILED,
+ [SCOPE_FAILED] = UNIT_FAILED,
};
static int scope_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
diff --git a/src/core/service.c b/src/core/service.c
index be38ec73d8..37025b4be2 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -50,61 +50,61 @@
#define service_spawn(...) service_spawn_internal(__func__, __VA_ARGS__)
static const UnitActiveState state_translation_table[_SERVICE_STATE_MAX] = {
- [SERVICE_DEAD] = UNIT_INACTIVE,
- [SERVICE_CONDITION] = UNIT_ACTIVATING,
- [SERVICE_START_PRE] = UNIT_ACTIVATING,
- [SERVICE_START] = UNIT_ACTIVATING,
- [SERVICE_START_POST] = UNIT_ACTIVATING,
- [SERVICE_RUNNING] = UNIT_ACTIVE,
- [SERVICE_EXITED] = UNIT_ACTIVE,
- [SERVICE_RELOAD] = UNIT_RELOADING,
- [SERVICE_RELOAD_SIGNAL] = UNIT_RELOADING,
- [SERVICE_RELOAD_NOTIFY] = UNIT_RELOADING,
- [SERVICE_STOP] = UNIT_DEACTIVATING,
- [SERVICE_STOP_WATCHDOG] = UNIT_DEACTIVATING,
- [SERVICE_STOP_SIGTERM] = UNIT_DEACTIVATING,
- [SERVICE_STOP_SIGKILL] = UNIT_DEACTIVATING,
- [SERVICE_STOP_POST] = UNIT_DEACTIVATING,
- [SERVICE_FINAL_WATCHDOG] = UNIT_DEACTIVATING,
- [SERVICE_FINAL_SIGTERM] = UNIT_DEACTIVATING,
- [SERVICE_FINAL_SIGKILL] = UNIT_DEACTIVATING,
- [SERVICE_FAILED] = UNIT_FAILED,
- [SERVICE_DEAD_BEFORE_AUTO_RESTART] = UNIT_INACTIVE,
+ [SERVICE_DEAD] = UNIT_INACTIVE,
+ [SERVICE_CONDITION] = UNIT_ACTIVATING,
+ [SERVICE_START_PRE] = UNIT_ACTIVATING,
+ [SERVICE_START] = UNIT_ACTIVATING,
+ [SERVICE_START_POST] = UNIT_ACTIVATING,
+ [SERVICE_RUNNING] = UNIT_ACTIVE,
+ [SERVICE_EXITED] = UNIT_ACTIVE,
+ [SERVICE_RELOAD] = UNIT_RELOADING,
+ [SERVICE_RELOAD_SIGNAL] = UNIT_RELOADING,
+ [SERVICE_RELOAD_NOTIFY] = UNIT_RELOADING,
+ [SERVICE_STOP] = UNIT_DEACTIVATING,
+ [SERVICE_STOP_WATCHDOG] = UNIT_DEACTIVATING,
+ [SERVICE_STOP_SIGTERM] = UNIT_DEACTIVATING,
+ [SERVICE_STOP_SIGKILL] = UNIT_DEACTIVATING,
+ [SERVICE_STOP_POST] = UNIT_DEACTIVATING,
+ [SERVICE_FINAL_WATCHDOG] = UNIT_DEACTIVATING,
+ [SERVICE_FINAL_SIGTERM] = UNIT_DEACTIVATING,
+ [SERVICE_FINAL_SIGKILL] = UNIT_DEACTIVATING,
+ [SERVICE_FAILED] = UNIT_FAILED,
+ [SERVICE_DEAD_BEFORE_AUTO_RESTART] = UNIT_INACTIVE,
[SERVICE_FAILED_BEFORE_AUTO_RESTART] = UNIT_FAILED,
- [SERVICE_DEAD_RESOURCES_PINNED] = UNIT_INACTIVE,
- [SERVICE_AUTO_RESTART] = UNIT_ACTIVATING,
- [SERVICE_AUTO_RESTART_QUEUED] = UNIT_ACTIVATING,
- [SERVICE_CLEANING] = UNIT_MAINTENANCE,
+ [SERVICE_DEAD_RESOURCES_PINNED] = UNIT_INACTIVE,
+ [SERVICE_AUTO_RESTART] = UNIT_ACTIVATING,
+ [SERVICE_AUTO_RESTART_QUEUED] = UNIT_ACTIVATING,
+ [SERVICE_CLEANING] = UNIT_MAINTENANCE,
};
/* For Type=idle we never want to delay any other jobs, hence we
* consider idle jobs active as soon as we start working on them */
static const UnitActiveState state_translation_table_idle[_SERVICE_STATE_MAX] = {
- [SERVICE_DEAD] = UNIT_INACTIVE,
- [SERVICE_CONDITION] = UNIT_ACTIVE,
- [SERVICE_START_PRE] = UNIT_ACTIVE,
- [SERVICE_START] = UNIT_ACTIVE,
- [SERVICE_START_POST] = UNIT_ACTIVE,
- [SERVICE_RUNNING] = UNIT_ACTIVE,
- [SERVICE_EXITED] = UNIT_ACTIVE,
- [SERVICE_RELOAD] = UNIT_RELOADING,
- [SERVICE_RELOAD_SIGNAL] = UNIT_RELOADING,
- [SERVICE_RELOAD_NOTIFY] = UNIT_RELOADING,
- [SERVICE_STOP] = UNIT_DEACTIVATING,
- [SERVICE_STOP_WATCHDOG] = UNIT_DEACTIVATING,
- [SERVICE_STOP_SIGTERM] = UNIT_DEACTIVATING,
- [SERVICE_STOP_SIGKILL] = UNIT_DEACTIVATING,
- [SERVICE_STOP_POST] = UNIT_DEACTIVATING,
- [SERVICE_FINAL_WATCHDOG] = UNIT_DEACTIVATING,
- [SERVICE_FINAL_SIGTERM] = UNIT_DEACTIVATING,
- [SERVICE_FINAL_SIGKILL] = UNIT_DEACTIVATING,
- [SERVICE_FAILED] = UNIT_FAILED,
- [SERVICE_DEAD_BEFORE_AUTO_RESTART] = UNIT_INACTIVE,
+ [SERVICE_DEAD] = UNIT_INACTIVE,
+ [SERVICE_CONDITION] = UNIT_ACTIVE,
+ [SERVICE_START_PRE] = UNIT_ACTIVE,
+ [SERVICE_START] = UNIT_ACTIVE,
+ [SERVICE_START_POST] = UNIT_ACTIVE,
+ [SERVICE_RUNNING] = UNIT_ACTIVE,
+ [SERVICE_EXITED] = UNIT_ACTIVE,
+ [SERVICE_RELOAD] = UNIT_RELOADING,
+ [SERVICE_RELOAD_SIGNAL] = UNIT_RELOADING,
+ [SERVICE_RELOAD_NOTIFY] = UNIT_RELOADING,
+ [SERVICE_STOP] = UNIT_DEACTIVATING,
+ [SERVICE_STOP_WATCHDOG] = UNIT_DEACTIVATING,
+ [SERVICE_STOP_SIGTERM] = UNIT_DEACTIVATING,
+ [SERVICE_STOP_SIGKILL] = UNIT_DEACTIVATING,
+ [SERVICE_STOP_POST] = UNIT_DEACTIVATING,
+ [SERVICE_FINAL_WATCHDOG] = UNIT_DEACTIVATING,
+ [SERVICE_FINAL_SIGTERM] = UNIT_DEACTIVATING,
+ [SERVICE_FINAL_SIGKILL] = UNIT_DEACTIVATING,
+ [SERVICE_FAILED] = UNIT_FAILED,
+ [SERVICE_DEAD_BEFORE_AUTO_RESTART] = UNIT_INACTIVE,
[SERVICE_FAILED_BEFORE_AUTO_RESTART] = UNIT_FAILED,
- [SERVICE_DEAD_RESOURCES_PINNED] = UNIT_INACTIVE,
- [SERVICE_AUTO_RESTART] = UNIT_ACTIVATING,
- [SERVICE_AUTO_RESTART_QUEUED] = UNIT_ACTIVATING,
- [SERVICE_CLEANING] = UNIT_MAINTENANCE,
+ [SERVICE_DEAD_RESOURCES_PINNED] = UNIT_INACTIVE,
+ [SERVICE_AUTO_RESTART] = UNIT_ACTIVATING,
+ [SERVICE_AUTO_RESTART_QUEUED] = UNIT_ACTIVATING,
+ [SERVICE_CLEANING] = UNIT_MAINTENANCE,
};
static int service_dispatch_inotify_io(sd_event_source *source, int fd, uint32_t events, void *userdata);
@@ -1992,7 +1992,7 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart)
} else if (s->result == SERVICE_SKIP_CONDITION) {
unit_log_skip(UNIT(s), service_result_to_string(s->result));
end_state = service_determine_dead_state(s);
- restart_state = SERVICE_DEAD_BEFORE_AUTO_RESTART;
+ restart_state = _SERVICE_STATE_INVALID; /* Never restart if skipped due to condition failure */
} else {
unit_log_failure(UNIT(s), service_result_to_string(s->result));
end_state = SERVICE_FAILED;
@@ -2014,6 +2014,8 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart)
if (allow_restart) {
usec_t restart_usec_next;
+ assert(restart_state >= 0 && restart_state < _SERVICE_STATE_MAX);
+
/* We make two state changes here: one that maps to the high-level UNIT_INACTIVE/UNIT_FAILED
* state (i.e. a state indicating deactivation), and then one that that maps to the
* high-level UNIT_STARTING state (i.e. a state indicating activation). We do this so that
@@ -2513,7 +2515,6 @@ static void service_enter_condition(Service *s) {
service_exec_flags(s->control_command_id, /* cred_flag = */ 0),
s->timeout_start_usec,
&s->control_pid);
-
if (r < 0) {
log_unit_warning_errno(UNIT(s), r, "Failed to spawn 'exec-condition' task: %m");
goto fail;
@@ -3187,9 +3188,9 @@ static int service_deserialize_item(Unit *u, const char *key, const char *value,
s->reload_result = f;
} else if (streq(key, "control-pid")) {
- pidref_done(&s->control_pid);
- (void) deserialize_pidref(fds, value, &s->control_pid);
+ if (!pidref_is_set(&s->control_pid))
+ (void) deserialize_pidref(fds, value, &s->control_pid);
} else if (streq(key, "main-pid")) {
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
@@ -5029,7 +5030,7 @@ DEFINE_STRING_TABLE_LOOKUP(service_restart, ServiceRestart);
static const char* const service_restart_mode_table[_SERVICE_RESTART_MODE_MAX] = {
[SERVICE_RESTART_MODE_NORMAL] = "normal",
- [SERVICE_RESTART_MODE_DIRECT] = "direct",
+ [SERVICE_RESTART_MODE_DIRECT] = "direct",
};
DEFINE_STRING_TABLE_LOOKUP(service_restart_mode, ServiceRestartMode);
diff --git a/src/core/slice.c b/src/core/slice.c
index 63ea1758b0..a99c0d70b3 100644
--- a/src/core/slice.c
+++ b/src/core/slice.c
@@ -16,8 +16,8 @@
#include "unit.h"
static const UnitActiveState state_translation_table[_SLICE_STATE_MAX] = {
- [SLICE_DEAD] = UNIT_INACTIVE,
- [SLICE_ACTIVE] = UNIT_ACTIVE
+ [SLICE_DEAD] = UNIT_INACTIVE,
+ [SLICE_ACTIVE] = UNIT_ACTIVE,
};
static void slice_init(Unit *u) {
diff --git a/src/core/socket.c b/src/core/socket.c
index 5dbbd5a1d2..36d458f35c 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -57,20 +57,20 @@ struct SocketPeer {
};
static const UnitActiveState state_translation_table[_SOCKET_STATE_MAX] = {
- [SOCKET_DEAD] = UNIT_INACTIVE,
- [SOCKET_START_PRE] = UNIT_ACTIVATING,
- [SOCKET_START_CHOWN] = UNIT_ACTIVATING,
- [SOCKET_START_POST] = UNIT_ACTIVATING,
- [SOCKET_LISTENING] = UNIT_ACTIVE,
- [SOCKET_RUNNING] = UNIT_ACTIVE,
- [SOCKET_STOP_PRE] = UNIT_DEACTIVATING,
+ [SOCKET_DEAD] = UNIT_INACTIVE,
+ [SOCKET_START_PRE] = UNIT_ACTIVATING,
+ [SOCKET_START_CHOWN] = UNIT_ACTIVATING,
+ [SOCKET_START_POST] = UNIT_ACTIVATING,
+ [SOCKET_LISTENING] = UNIT_ACTIVE,
+ [SOCKET_RUNNING] = UNIT_ACTIVE,
+ [SOCKET_STOP_PRE] = UNIT_DEACTIVATING,
[SOCKET_STOP_PRE_SIGTERM] = UNIT_DEACTIVATING,
[SOCKET_STOP_PRE_SIGKILL] = UNIT_DEACTIVATING,
- [SOCKET_STOP_POST] = UNIT_DEACTIVATING,
- [SOCKET_FINAL_SIGTERM] = UNIT_DEACTIVATING,
- [SOCKET_FINAL_SIGKILL] = UNIT_DEACTIVATING,
- [SOCKET_FAILED] = UNIT_FAILED,
- [SOCKET_CLEANING] = UNIT_MAINTENANCE,
+ [SOCKET_STOP_POST] = UNIT_DEACTIVATING,
+ [SOCKET_FINAL_SIGTERM] = UNIT_DEACTIVATING,
+ [SOCKET_FINAL_SIGKILL] = UNIT_DEACTIVATING,
+ [SOCKET_FAILED] = UNIT_FAILED,
+ [SOCKET_CLEANING] = UNIT_MAINTENANCE,
};
static int socket_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
@@ -2631,8 +2631,9 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
else
s->n_refused += k;
} else if (streq(key, "control-pid")) {
- pidref_done(&s->control_pid);
- (void) deserialize_pidref(fds, value, &s->control_pid);
+
+ if (!pidref_is_set(&s->control_pid))
+ (void) deserialize_pidref(fds, value, &s->control_pid);
} else if (streq(key, "control-command")) {
SocketExecCommand id;
@@ -3476,7 +3477,7 @@ static const char* const socket_exec_command_table[_SOCKET_EXEC_COMMAND_MAX] = {
[SOCKET_EXEC_START_CHOWN] = "ExecStartChown",
[SOCKET_EXEC_START_POST] = "ExecStartPost",
[SOCKET_EXEC_STOP_PRE] = "ExecStopPre",
- [SOCKET_EXEC_STOP_POST] = "ExecStopPost"
+ [SOCKET_EXEC_STOP_POST] = "ExecStopPost",
};
DEFINE_STRING_TABLE_LOOKUP(socket_exec_command, SocketExecCommand);
@@ -3490,7 +3491,7 @@ static const char* const socket_result_table[_SOCKET_RESULT_MAX] = {
[SOCKET_FAILURE_CORE_DUMP] = "core-dump",
[SOCKET_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
[SOCKET_FAILURE_TRIGGER_LIMIT_HIT] = "trigger-limit-hit",
- [SOCKET_FAILURE_SERVICE_START_LIMIT_HIT] = "service-start-limit-hit"
+ [SOCKET_FAILURE_SERVICE_START_LIMIT_HIT] = "service-start-limit-hit",
};
DEFINE_STRING_TABLE_LOOKUP(socket_result, SocketResult);
diff --git a/src/core/swap.c b/src/core/swap.c
index 9e200086f3..820dfdff81 100644
--- a/src/core/swap.c
+++ b/src/core/swap.c
@@ -30,15 +30,15 @@
#include "virt.h"
static const UnitActiveState state_translation_table[_SWAP_STATE_MAX] = {
- [SWAP_DEAD] = UNIT_INACTIVE,
- [SWAP_ACTIVATING] = UNIT_ACTIVATING,
- [SWAP_ACTIVATING_DONE] = UNIT_ACTIVE,
- [SWAP_ACTIVE] = UNIT_ACTIVE,
- [SWAP_DEACTIVATING] = UNIT_DEACTIVATING,
+ [SWAP_DEAD] = UNIT_INACTIVE,
+ [SWAP_ACTIVATING] = UNIT_ACTIVATING,
+ [SWAP_ACTIVATING_DONE] = UNIT_ACTIVE,
+ [SWAP_ACTIVE] = UNIT_ACTIVE,
+ [SWAP_DEACTIVATING] = UNIT_DEACTIVATING,
[SWAP_DEACTIVATING_SIGTERM] = UNIT_DEACTIVATING,
[SWAP_DEACTIVATING_SIGKILL] = UNIT_DEACTIVATING,
- [SWAP_FAILED] = UNIT_FAILED,
- [SWAP_CLEANING] = UNIT_MAINTENANCE,
+ [SWAP_FAILED] = UNIT_FAILED,
+ [SWAP_CLEANING] = UNIT_MAINTENANCE,
};
static int swap_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
@@ -955,8 +955,8 @@ static int swap_deserialize_item(Unit *u, const char *key, const char *value, FD
s->result = f;
} else if (streq(key, "control-pid")) {
- pidref_done(&s->control_pid);
- (void) deserialize_pidref(fds, value, &s->control_pid);
+ if (!pidref_is_set(&s->control_pid))
+ (void) deserialize_pidref(fds, value, &s->control_pid);
} else if (streq(key, "control-command")) {
SwapExecCommand id;
diff --git a/src/core/target.c b/src/core/target.c
index bbaa5d313c..3351b1fc2b 100644
--- a/src/core/target.c
+++ b/src/core/target.c
@@ -11,8 +11,8 @@
#include "unit.h"
static const UnitActiveState state_translation_table[_TARGET_STATE_MAX] = {
- [TARGET_DEAD] = UNIT_INACTIVE,
- [TARGET_ACTIVE] = UNIT_ACTIVE
+ [TARGET_DEAD] = UNIT_INACTIVE,
+ [TARGET_ACTIVE] = UNIT_ACTIVE,
};
static void target_set_state(Target *t, TargetState state) {
diff --git a/src/core/timer.c b/src/core/timer.c
index 0c451c020c..d7ce4733c0 100644
--- a/src/core/timer.c
+++ b/src/core/timer.c
@@ -25,11 +25,11 @@
#include "virt.h"
static const UnitActiveState state_translation_table[_TIMER_STATE_MAX] = {
- [TIMER_DEAD] = UNIT_INACTIVE,
+ [TIMER_DEAD] = UNIT_INACTIVE,
[TIMER_WAITING] = UNIT_ACTIVE,
[TIMER_RUNNING] = UNIT_ACTIVE,
[TIMER_ELAPSED] = UNIT_ACTIVE,
- [TIMER_FAILED] = UNIT_FAILED
+ [TIMER_FAILED] = UNIT_FAILED,
};
static int timer_dispatch(sd_event_source *s, uint64_t usec, void *userdata);
@@ -993,7 +993,7 @@ static const char* const timer_base_table[_TIMER_BASE_MAX] = {
[TIMER_STARTUP] = "OnStartupSec",
[TIMER_UNIT_ACTIVE] = "OnUnitActiveSec",
[TIMER_UNIT_INACTIVE] = "OnUnitInactiveSec",
- [TIMER_CALENDAR] = "OnCalendar"
+ [TIMER_CALENDAR] = "OnCalendar",
};
DEFINE_STRING_TABLE_LOOKUP(timer_base, TimerBase);
diff --git a/src/core/unit.c b/src/core/unit.c
index 9c0794b886..f26c1c248e 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -79,17 +79,17 @@
#define NOTICEWORTHY_IP_BYTES (128 * U64_MB)
const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX] = {
- [UNIT_SERVICE] = &service_vtable,
- [UNIT_SOCKET] = &socket_vtable,
- [UNIT_TARGET] = &target_vtable,
- [UNIT_DEVICE] = &device_vtable,
- [UNIT_MOUNT] = &mount_vtable,
+ [UNIT_SERVICE] = &service_vtable,
+ [UNIT_SOCKET] = &socket_vtable,
+ [UNIT_TARGET] = &target_vtable,
+ [UNIT_DEVICE] = &device_vtable,
+ [UNIT_MOUNT] = &mount_vtable,
[UNIT_AUTOMOUNT] = &automount_vtable,
- [UNIT_SWAP] = &swap_vtable,
- [UNIT_TIMER] = &timer_vtable,
- [UNIT_PATH] = &path_vtable,
- [UNIT_SLICE] = &slice_vtable,
- [UNIT_SCOPE] = &scope_vtable,
+ [UNIT_SWAP] = &swap_vtable,
+ [UNIT_TIMER] = &timer_vtable,
+ [UNIT_PATH] = &path_vtable,
+ [UNIT_SLICE] = &slice_vtable,
+ [UNIT_SCOPE] = &scope_vtable,
};
Unit* unit_new(Manager *m, size_t size) {
@@ -1249,10 +1249,10 @@ int unit_add_exec_dependencies(Unit *u, ExecContext *c) {
if (!u->manager->prefix[dt])
continue;
- for (size_t i = 0; i < c->directories[dt].n_items; i++) {
+ FOREACH_ARRAY(i, c->directories[dt].items, c->directories[dt].n_items) {
_cleanup_free_ char *p = NULL;
- p = path_join(u->manager->prefix[dt], c->directories[dt].items[i].path);
+ p = path_join(u->manager->prefix[dt], i->path);
if (!p)
return -ENOMEM;
@@ -6311,7 +6311,7 @@ Condition *unit_find_failed_condition(Unit *u) {
}
static const char* const collect_mode_table[_COLLECT_MODE_MAX] = {
- [COLLECT_INACTIVE] = "inactive",
+ [COLLECT_INACTIVE] = "inactive",
[COLLECT_INACTIVE_OR_FAILED] = "inactive-or-failed",
};
@@ -6461,7 +6461,7 @@ int unit_compare_priority(Unit *a, Unit *b) {
}
const ActivationDetailsVTable * const activation_details_vtable[_UNIT_TYPE_MAX] = {
- [UNIT_PATH] = &activation_details_path_vtable,
+ [UNIT_PATH] = &activation_details_path_vtable,
[UNIT_TIMER] = &activation_details_timer_vtable,
};
diff --git a/src/cryptsetup/cryptsetup-tokens/luks2-tpm2.h b/src/cryptsetup/cryptsetup-tokens/luks2-tpm2.h
index 4900cd5362..c3a01dfb3e 100644
--- a/src/cryptsetup/cryptsetup-tokens/luks2-tpm2.h
+++ b/src/cryptsetup/cryptsetup-tokens/luks2-tpm2.h
@@ -13,8 +13,8 @@ int acquire_luks2_key(
const struct iovec *pubkey,
uint32_t pubkey_pcr_mask,
const char *signature_path,
- const char *pcrlock_path,
const char *pin,
+ const char *pcrlock_path,
uint16_t primary_alg,
const struct iovec *key_data,
const struct iovec *policy_hash,
diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c
index 7099f68f88..34ad9ebd14 100644
--- a/src/cryptsetup/cryptsetup.c
+++ b/src/cryptsetup/cryptsetup.c
@@ -530,7 +530,7 @@ static int parse_one_option(const char *option) {
* - text descriptions prefixed with "%:" or "%keyring:".
* - text description with no prefix.
* - numeric keyring id (ignored in current patch set). */
- if (*val == '@' || *val == '%')
+ if (IN_SET(*val, '@', '%'))
keyring = strndup(val, sep - val);
else
/* add type prefix if missing (crypt_set_keyring_to_link() expects it) */
diff --git a/src/debug-generator/debug-generator.c b/src/debug-generator/debug-generator.c
index 741b59f320..3526b84dee 100644
--- a/src/debug-generator/debug-generator.c
+++ b/src/debug-generator/debug-generator.c
@@ -3,13 +3,17 @@
#include <unistd.h>
#include "alloc-util.h"
+#include "creds-util.h"
#include "dropin.h"
+#include "errno-util.h"
+#include "fd-util.h"
+#include "fileio-label.h"
#include "generator.h"
#include "initrd-util.h"
-#include "mkdir-label.h"
#include "parse-util.h"
#include "path-util.h"
#include "proc-cmdline.h"
+#include "recurse-dir.h"
#include "special.h"
#include "string-util.h"
#include "strv.h"
@@ -141,14 +145,14 @@ static int generate_wants_symlinks(void) {
return r;
}
-static void install_debug_shell_dropin(const char *dir) {
+static void install_debug_shell_dropin(void) {
const char *tty = arg_debug_tty ?: arg_default_debug_tty;
int r;
if (!tty || path_equal(tty, skip_dev_prefix(DEBUGTTY)))
return;
- r = write_drop_in_format(dir, "debug-shell.service", 50, "tty",
+ r = write_drop_in_format(arg_dest, "debug-shell.service", 50, "tty",
"[Unit]\n"
"Description=Early root shell on /dev/%s FOR DEBUGGING ONLY\n"
"ConditionPathExists=\n"
@@ -159,8 +163,74 @@ static void install_debug_shell_dropin(const char *dir) {
log_warning_errno(r, "Failed to write drop-in for debug-shell.service, ignoring: %m");
}
+static int process_unit_credentials(const char *credentials_dir) {
+ int r;
+
+ assert(credentials_dir);
+
+ _cleanup_free_ DirectoryEntries *des = NULL;
+ r = readdir_all_at(AT_FDCWD, credentials_dir, RECURSE_DIR_SORT|RECURSE_DIR_IGNORE_DOT|RECURSE_DIR_ENSURE_TYPE, &des);
+ if (r < 0)
+ return log_error_errno(r, "Failed to enumerate credentials from credentials directory '%s': %m", credentials_dir);
+
+ FOREACH_ARRAY(i, des->entries, des->n_entries) {
+ _cleanup_free_ void *d = NULL;
+ struct dirent *de = *i;
+ const char *unit, *dropin;
+
+ if (de->d_type != DT_REG)
+ continue;
+
+ unit = startswith(de->d_name, "systemd.extra-unit.");
+ dropin = startswith(de->d_name, "systemd.unit-dropin.");
+
+ if (!unit && !dropin)
+ continue;
+
+ if (!unit_name_is_valid(unit ?: dropin, UNIT_NAME_ANY)) {
+ log_warning("Invalid unit name '%s' in credential '%s', ignoring.",
+ unit ?: dropin, de->d_name);
+ continue;
+ }
+
+ r = read_credential_with_decryption(de->d_name, &d, NULL);
+ if (r < 0)
+ continue;
+
+ if (unit) {
+ _cleanup_free_ char *p = NULL;
+
+ p = path_join(arg_dest, unit);
+ if (!p)
+ return log_oom();
+
+ r = write_string_file_atomic_label(p, d);
+ if (r < 0) {
+ log_warning_errno(r, "Failed to write unit file '%s' from credential '%s', ignoring: %m",
+ unit, de->d_name);
+ continue;
+ }
+
+ log_debug("Wrote unit file '%s' from credential '%s'", unit, de->d_name);
+
+ } else {
+ r = write_drop_in(arg_dest, dropin, 50, "credential", d);
+ if (r < 0) {
+ log_warning_errno(r, "Failed to write drop-in for unit '%s' from credential '%s', ignoring: %m",
+ dropin, de->d_name);
+ continue;
+ }
+
+ log_debug("Wrote drop-in for unit '%s' from credential '%s'", dropin, de->d_name);
+ }
+ }
+
+ return 0;
+}
+
static int run(const char *dest, const char *dest_early, const char *dest_late) {
- int r, q;
+ const char *credentials_dir;
+ int r = 0;
assert_se(arg_dest = dest_early);
@@ -173,13 +243,19 @@ static int run(const char *dest, const char *dest_early, const char *dest_late)
if (r < 0)
return log_oom();
- install_debug_shell_dropin(arg_dest);
+ install_debug_shell_dropin();
}
- r = generate_mask_symlinks();
- q = generate_wants_symlinks();
+ if (get_credentials_dir(&credentials_dir) >= 0)
+ RET_GATHER(r, process_unit_credentials(credentials_dir));
+
+ if (get_encrypted_credentials_dir(&credentials_dir) >= 0)
+ RET_GATHER(r, process_unit_credentials(credentials_dir));
- return r < 0 ? r : q;
+ RET_GATHER(r, generate_mask_symlinks());
+ RET_GATHER(r, generate_wants_symlinks());
+
+ return r;
}
DEFINE_MAIN_GENERATOR_FUNCTION(run);
diff --git a/src/hibernate-resume/hibernate-resume-config.c b/src/hibernate-resume/hibernate-resume-config.c
index c6db83a9d3..504d27a396 100644
--- a/src/hibernate-resume/hibernate-resume-config.c
+++ b/src/hibernate-resume/hibernate-resume-config.c
@@ -28,20 +28,7 @@ static KernelHibernateLocation* kernel_hibernate_location_free(KernelHibernateLo
DEFINE_TRIVIAL_CLEANUP_FUNC(KernelHibernateLocation*, kernel_hibernate_location_free);
-typedef struct EFIHibernateLocation {
- char *device;
-
- sd_id128_t uuid;
- uint64_t offset;
-
- char *kernel_version;
- char *id;
- char *image_id;
- char *version_id;
- char *image_version;
-} EFIHibernateLocation;
-
-static EFIHibernateLocation* efi_hibernate_location_free(EFIHibernateLocation *e) {
+EFIHibernateLocation* efi_hibernate_location_free(EFIHibernateLocation *e) {
if (!e)
return NULL;
@@ -55,8 +42,6 @@ static EFIHibernateLocation* efi_hibernate_location_free(EFIHibernateLocation *e
return mfree(e);
}
-DEFINE_TRIVIAL_CLEANUP_FUNC(EFIHibernateLocation*, efi_hibernate_location_free);
-
void hibernate_info_done(HibernateInfo *info) {
assert(info);
@@ -140,7 +125,7 @@ static bool validate_efi_hibernate_location(EFIHibernateLocation *e) {
if (!streq_ptr(id, e->id) ||
!streq_ptr(image_id, e->image_id)) {
- log_notice("HibernateLocation system identifier doesn't match currently running system, not resuming from it.");
+ log_notice("HibernateLocation system identifier doesn't match currently running system, would not resume from it.");
return false;
}
@@ -152,8 +137,9 @@ static bool validate_efi_hibernate_location(EFIHibernateLocation *e) {
return true;
}
+#endif
-static int get_efi_hibernate_location(EFIHibernateLocation **ret) {
+int get_efi_hibernate_location(EFIHibernateLocation **ret) {
static const JsonDispatch dispatch_table[] = {
{ "uuid", JSON_VARIANT_STRING, json_dispatch_id128, offsetof(EFIHibernateLocation, uuid), JSON_MANDATORY },
@@ -171,8 +157,6 @@ static int get_efi_hibernate_location(EFIHibernateLocation **ret) {
_cleanup_free_ char *location_str = NULL;
int r;
- assert(ret);
-
if (!is_efi_boot())
goto skip;
@@ -211,15 +195,18 @@ static int get_efi_hibernate_location(EFIHibernateLocation **ret) {
if (asprintf(&e->device, "/dev/disk/by-uuid/" SD_ID128_UUID_FORMAT_STR, SD_ID128_FORMAT_VAL(e->uuid)) < 0)
return log_oom();
- *ret = TAKE_PTR(e);
+ if (ret)
+ *ret = TAKE_PTR(e);
return 1;
skip:
- *ret = NULL;
+ if (ret)
+ *ret = NULL;
return 0;
}
void compare_hibernate_location_and_warn(const HibernateInfo *info) {
+#if ENABLE_EFI
int r;
assert(info);
@@ -243,8 +230,8 @@ void compare_hibernate_location_and_warn(const HibernateInfo *info) {
if (info->cmdline->offset != info->efi->offset)
log_warning("resume_offset=%" PRIu64 " doesn't match with EFI HibernateLocation offset %" PRIu64 ", proceeding anyway with resume_offset=.",
info->cmdline->offset, info->efi->offset);
-}
#endif
+}
int acquire_hibernate_info(HibernateInfo *ret) {
_cleanup_(hibernate_info_done) HibernateInfo i = {};
@@ -254,11 +241,9 @@ int acquire_hibernate_info(HibernateInfo *ret) {
if (r < 0)
return r;
-#if ENABLE_EFI
r = get_efi_hibernate_location(&i.efi);
if (r < 0)
return r;
-#endif
if (i.cmdline) {
i.device = i.cmdline->device;
diff --git a/src/hibernate-resume/hibernate-resume-config.h b/src/hibernate-resume/hibernate-resume-config.h
index c0aa9e00ad..68ef075355 100644
--- a/src/hibernate-resume/hibernate-resume-config.h
+++ b/src/hibernate-resume/hibernate-resume-config.h
@@ -5,8 +5,27 @@
#include "sd-id128.h"
+#include "macro.h"
+
typedef struct KernelHibernateLocation KernelHibernateLocation;
-typedef struct EFIHibernateLocation EFIHibernateLocation;
+
+typedef struct EFIHibernateLocation {
+ char *device;
+
+ sd_id128_t uuid;
+ uint64_t offset;
+
+ char *kernel_version;
+ char *id;
+ char *image_id;
+ char *version_id;
+ char *image_version;
+} EFIHibernateLocation;
+
+EFIHibernateLocation* efi_hibernate_location_free(EFIHibernateLocation *e);
+DEFINE_TRIVIAL_CLEANUP_FUNC(EFIHibernateLocation*, efi_hibernate_location_free);
+
+int get_efi_hibernate_location(EFIHibernateLocation **ret);
typedef struct HibernateInfo {
const char *device;
@@ -20,14 +39,4 @@ void hibernate_info_done(HibernateInfo *info);
int acquire_hibernate_info(HibernateInfo *ret);
-#if ENABLE_EFI
-
void compare_hibernate_location_and_warn(const HibernateInfo *info);
-
-#else
-
-static inline void compare_hibernate_location_and_warn(const HibernateInfo *info) {
- return;
-}
-
-#endif
diff --git a/src/hibernate-resume/hibernate-resume.c b/src/hibernate-resume/hibernate-resume.c
index 3f45836d59..c6494b99a9 100644
--- a/src/hibernate-resume/hibernate-resume.c
+++ b/src/hibernate-resume/hibernate-resume.c
@@ -1,8 +1,10 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <errno.h>
+#include <getopt.h>
#include <sys/stat.h>
+#include "build.h"
#include "devnum-util.h"
#include "hibernate-resume-config.h"
#include "hibernate-util.h"
@@ -10,12 +12,84 @@
#include "log.h"
#include "main-func.h"
#include "parse-util.h"
+#include "pretty-print.h"
#include "static-destruct.h"
+#include "terminal-util.h"
static HibernateInfo arg_info = {};
+static bool arg_clear = false;
STATIC_DESTRUCTOR_REGISTER(arg_info, hibernate_info_done);
+static int help(void) {
+ _cleanup_free_ char *link = NULL;
+ int r;
+
+ r = terminal_urlify_man("systemd-hibernate-resume", "8", &link);
+ if (r < 0)
+ return log_oom();
+
+ printf("%s [OPTIONS...] [DEVICE [OFFSET]]\n"
+ "\n%sInitiate resume from hibernation.%s\n\n"
+ " -h --help Show this help\n"
+ " --version Show package version\n"
+ " --clear Clear hibernation storage information from EFI and exit\n"
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ ansi_highlight(),
+ ansi_normal(),
+ link);
+
+ return 0;
+}
+
+static int parse_argv(int argc, char *argv[]) {
+
+ enum {
+ ARG_VERSION = 0x100,
+ ARG_CLEAR,
+ };
+
+ static const struct option options[] = {
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, ARG_VERSION },
+ { "clear", no_argument, NULL, ARG_CLEAR },
+ {}
+ };
+
+ int c;
+
+ assert(argc >= 0);
+ assert(argv);
+
+ while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
+
+ switch (c) {
+
+ case 'h':
+ return help();
+
+ case ARG_VERSION:
+ return version();
+
+ case ARG_CLEAR:
+ arg_clear = true;
+ break;
+
+ case '?':
+ return -EINVAL;
+
+ default:
+ assert_not_reached();
+ }
+
+ if (argc > optind && arg_clear)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Extraneous arguments specified with --clear, refusing.");
+
+ return 1;
+}
+
static int setup_hibernate_info_and_warn(void) {
int r;
@@ -32,42 +106,68 @@ static int setup_hibernate_info_and_warn(void) {
return 1;
}
+static int action_clear(void) {
+ int r;
+
+ assert(arg_clear);
+
+ /* Let's insist that the system identifier is verified still. After all if things don't match,
+ * the resume wouldn't get triggered in the first place. We should not erase the var if booted
+ * from LiveCD/portable systems/... */
+ r = get_efi_hibernate_location(/* ret = */ NULL);
+ if (r <= 0)
+ return r;
+
+ r = clear_efi_hibernate_location_and_warn();
+ if (r > 0)
+ log_notice("Successfully cleared HibernateLocation EFI variable.");
+ return r;
+}
+
static int run(int argc, char *argv[]) {
struct stat st;
int r;
log_setup();
- if (argc < 1 || argc > 3)
+ r = parse_argv(argc, argv);
+ if (r <= 0)
+ return r;
+
+ if (argc - optind > 2)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This program expects zero, one, or two arguments.");
umask(0022);
- if (!in_initrd())
- return 0;
+ if (arg_clear)
+ return action_clear();
- if (argc > 1) {
- arg_info.device = argv[1];
+ if (!in_initrd())
+ return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
+ "Not running in initrd, refusing to initiate resume from hibernation.");
- if (argc == 3) {
- r = safe_atou64(argv[2], &arg_info.offset);
- if (r < 0)
- return log_error_errno(r, "Failed to parse resume offset %s: %m", argv[2]);
- }
- } else {
+ if (argc <= optind) {
r = setup_hibernate_info_and_warn();
if (r <= 0)
return r;
if (arg_info.efi)
- clear_efi_hibernate_location_and_warn();
+ (void) clear_efi_hibernate_location_and_warn();
+ } else {
+ arg_info.device = ASSERT_PTR(argv[optind]);
+
+ if (argc - optind == 2) {
+ r = safe_atou64(argv[optind + 1], &arg_info.offset);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse resume offset %s: %m", argv[optind + 1]);
+ }
}
if (stat(arg_info.device, &st) < 0)
return log_error_errno(errno, "Failed to stat resume device '%s': %m", arg_info.device);
if (!S_ISBLK(st.st_mode))
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ return log_error_errno(SYNTHETIC_ERRNO(ENOTBLK),
"Resume device '%s' is not a block device.", arg_info.device);
/* The write shall not return if a resume takes place. */
diff --git a/src/home/homed-manager.c b/src/home/homed-manager.c
index 5f345b3d40..90fd91c8a7 100644
--- a/src/home/homed-manager.c
+++ b/src/home/homed-manager.c
@@ -1365,8 +1365,11 @@ static int manager_enumerate_devices(Manager *m) {
if (r < 0)
return r;
- FOREACH_DEVICE(e, d)
+ FOREACH_DEVICE(e, d) {
+ if (device_is_processed(d) <= 0)
+ continue;
(void) manager_add_device(m, d);
+ }
return 0;
}
diff --git a/src/import/pull-job.c b/src/import/pull-job.c
index a4feda4081..848255179b 100644
--- a/src/import/pull-job.c
+++ b/src/import/pull-job.c
@@ -431,7 +431,9 @@ static int pull_job_open_disk(PullJob *j) {
return log_error_errno(SYNTHETIC_ERRNO(EIO),
"Failed to initialize hash context.");
#else
- initialize_libgcrypt(false);
+ r = initialize_libgcrypt(false);
+ if (r < 0)
+ return log_error_errno(r, "Failed to load libgcrypt: %m");
if (gcry_md_open(&j->checksum_ctx, GCRY_MD_SHA256, 0) != 0)
return log_error_errno(SYNTHETIC_ERRNO(EIO),
diff --git a/src/journal/journalctl-authenticate.c b/src/journal/journalctl-authenticate.c
index 40d1032388..10630f5e6c 100644
--- a/src/journal/journalctl-authenticate.c
+++ b/src/journal/journalctl-authenticate.c
@@ -102,10 +102,14 @@ int action_setup_keys(void) {
return log_error_errno(r, "Failed to acquire random seed: %m");
log_info("Generating key pair...");
- FSPRG_GenMK(NULL, mpk, seed, seed_size, FSPRG_RECOMMENDED_SECPAR);
+ r = FSPRG_GenMK(NULL, mpk, seed, seed_size, FSPRG_RECOMMENDED_SECPAR);
+ if (r < 0)
+ return log_error_errno(r, "Failed to generate key pair: %m");
log_info("Generating sealing key...");
- FSPRG_GenState0(state, mpk, seed, seed_size);
+ r = FSPRG_GenState0(state, mpk, seed, seed_size);
+ if (r < 0)
+ return log_error_errno(r, "Failed to generate sealing key: %m");
assert(arg_interval > 0);
n = now(CLOCK_REALTIME);
diff --git a/src/journal/meson.build b/src/journal/meson.build
index 11bb6fa1f2..7d87754e0e 100644
--- a/src/journal/meson.build
+++ b/src/journal/meson.build
@@ -47,7 +47,6 @@ if get_option('link-journalctl-shared')
journalctl_link_with = [libshared]
else
journalctl_link_with = [
- libbasic_gcrypt,
libshared_static,
libsystemd_static,
]
diff --git a/src/kernel-install/90-loaderentry.install.in b/src/kernel-install/90-loaderentry.install.in
index 610460b829..766d321595 100755
--- a/src/kernel-install/90-loaderentry.install.in
+++ b/src/kernel-install/90-loaderentry.install.in
@@ -66,7 +66,7 @@ elif [ -f /usr/lib/os-release ]; then
. /usr/lib/os-release
fi
-[ -n "$PRETTY_NAME" ] || PRETTY_NAME="Linux"
+[ -n "$PRETTY_NAME" ] || PRETTY_NAME="Linux $KERNEL_VERSION"
SORT_KEY="$IMAGE_ID"
[ -z "$SORT_KEY" ] && SORT_KEY="$ID"
@@ -182,7 +182,7 @@ mkdir -p "${LOADER_ENTRY%/*}" || {
{
echo "# Boot Loader Specification type#1 entry"
echo "# File created by $0 (systemd {{VERSION_TAG}})"
- echo "title $PRETTY_NAME $KERNEL_VERSION"
+ echo "title $PRETTY_NAME"
echo "version $KERNEL_VERSION"
if [ "$ENTRY_TOKEN" = "$MACHINE_ID" ]; then
# See similar logic above for the systemd.machine_id= kernel command line option
diff --git a/src/libsystemd-network/fuzz-ndisc-rs.c b/src/libsystemd-network/fuzz-ndisc-rs.c
index 8a720e628e..c52043a13b 100644
--- a/src/libsystemd-network/fuzz-ndisc-rs.c
+++ b/src/libsystemd-network/fuzz-ndisc-rs.c
@@ -62,7 +62,7 @@ static void test_with_icmp6_packet(const uint8_t *data, size_t size) {
if (icmp6_packet_receive(fd_pair[0], &packet) < 0)
return;
- (void) ndisc_parse_options(packet, &options);
+ assert_se(ndisc_parse_options(packet, &options) >= 0);
}
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
diff --git a/src/libsystemd-network/icmp6-util.c b/src/libsystemd-network/icmp6-util.c
index 7b3786e518..44c15f9044 100644
--- a/src/libsystemd-network/icmp6-util.c
+++ b/src/libsystemd-network/icmp6-util.c
@@ -42,6 +42,7 @@ int icmp6_bind(int ifindex, bool is_router) {
.ipv6mr_interface = ifindex,
};
ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filter);
+ ICMP6_FILTER_SETPASS(ND_NEIGHBOR_ADVERT, &filter);
}
s = socket(AF_INET6, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, IPPROTO_ICMPV6);
diff --git a/src/libsystemd-network/meson.build b/src/libsystemd-network/meson.build
index e4340f9957..46a6119c6b 100644
--- a/src/libsystemd-network/meson.build
+++ b/src/libsystemd-network/meson.build
@@ -28,6 +28,7 @@ sources = files(
'sd-lldp-rx.c',
'sd-lldp-tx.c',
'sd-ndisc.c',
+ 'sd-ndisc-neighbor.c',
'sd-ndisc-router.c',
'sd-radv.c',
)
diff --git a/src/libsystemd-network/ndisc-neighbor-internal.h b/src/libsystemd-network/ndisc-neighbor-internal.h
new file mode 100644
index 0000000000..aee655665e
--- /dev/null
+++ b/src/libsystemd-network/ndisc-neighbor-internal.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include "sd-ndisc.h"
+
+#include "icmp6-packet.h"
+#include "set.h"
+
+struct sd_ndisc_neighbor {
+ unsigned n_ref;
+
+ ICMP6Packet *packet;
+
+ uint32_t flags;
+ struct in6_addr target_address;
+
+ Set *options;
+};
+
+sd_ndisc_neighbor* ndisc_neighbor_new(ICMP6Packet *packet);
+int ndisc_neighbor_parse(sd_ndisc *nd, sd_ndisc_neighbor *na);
diff --git a/src/libsystemd-network/sd-ndisc-neighbor.c b/src/libsystemd-network/sd-ndisc-neighbor.c
new file mode 100644
index 0000000000..1bb6ebf610
--- /dev/null
+++ b/src/libsystemd-network/sd-ndisc-neighbor.c
@@ -0,0 +1,126 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include <netinet/icmp6.h>
+
+#include "sd-ndisc.h"
+
+#include "alloc-util.h"
+#include "in-addr-util.h"
+#include "ndisc-internal.h"
+#include "ndisc-neighbor-internal.h"
+#include "ndisc-option.h"
+
+static sd_ndisc_neighbor* ndisc_neighbor_free(sd_ndisc_neighbor *na) {
+ if (!na)
+ return NULL;
+
+ icmp6_packet_unref(na->packet);
+ set_free(na->options);
+ return mfree(na);
+}
+
+DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_ndisc_neighbor, sd_ndisc_neighbor, ndisc_neighbor_free);
+
+sd_ndisc_neighbor* ndisc_neighbor_new(ICMP6Packet *packet) {
+ sd_ndisc_neighbor *na;
+
+ assert(packet);
+
+ na = new(sd_ndisc_neighbor, 1);
+ if (!na)
+ return NULL;
+
+ *na = (sd_ndisc_neighbor) {
+ .n_ref = 1,
+ .packet = icmp6_packet_ref(packet),
+ };
+
+ return na;
+}
+
+int ndisc_neighbor_parse(sd_ndisc *nd, sd_ndisc_neighbor *na) {
+ int r;
+
+ assert(na);
+
+ if (na->packet->raw_size < sizeof(struct nd_neighbor_advert))
+ return log_ndisc_errno(nd, SYNTHETIC_ERRNO(EBADMSG),
+ "Too small to be a neighbor advertisement, ignoring datagram.");
+
+ /* Neighbor advertisement packets are neatly aligned to 64-bit boundaries, hence we can access them directly */
+ const struct nd_neighbor_advert *a = (const struct nd_neighbor_advert*) na->packet->raw_packet;
+ assert(a->nd_na_type == ND_NEIGHBOR_ADVERT);
+ assert(a->nd_na_code == 0);
+
+ na->flags = a->nd_na_flags_reserved; /* the first 3 bits */
+ na->target_address = a->nd_na_target;
+
+ /* RFC 4861 section 4.4:
+ * For solicited advertisements, the Target Address field in the Neighbor Solicitation message that
+ * prompted this advertisement. For an unsolicited advertisement, the address whose link-layer
+ * address has changed. The Target Address MUST NOT be a multicast address.
+ *
+ * Here, we only check if the target address is a link-layer address (or a null address, for safety)
+ * when the message is an unsolicited neighbor advertisement. */
+ if (!FLAGS_SET(na->flags, ND_NA_FLAG_SOLICITED))
+ if (!in6_addr_is_link_local(&na->target_address) && !in6_addr_is_null(&na->target_address))
+ return log_ndisc_errno(nd, SYNTHETIC_ERRNO(EBADMSG),
+ "Received ND packet with an invalid target address (%s), ignoring datagram.",
+ IN6_ADDR_TO_STRING(&na->target_address));
+
+ r = ndisc_parse_options(na->packet, &na->options);
+ if (r < 0)
+ return log_ndisc_errno(nd, r, "Failed to parse NDisc options in neighbor advertisement message, ignoring: %m");
+
+ return 0;
+}
+
+int sd_ndisc_neighbor_get_sender_address(sd_ndisc_neighbor *na, struct in6_addr *ret) {
+ assert_return(na, -EINVAL);
+
+ return icmp6_packet_get_sender_address(na->packet, ret);
+}
+
+int sd_ndisc_neighbor_get_target_address(sd_ndisc_neighbor *na, struct in6_addr *ret) {
+ assert_return(na, -EINVAL);
+
+ if (in6_addr_is_null(&na->target_address))
+ /* fall back to the sender address, for safety. */
+ return sd_ndisc_neighbor_get_sender_address(na, ret);
+
+ if (ret)
+ *ret = na->target_address;
+ return 0;
+}
+
+int sd_ndisc_neighbor_get_target_mac(sd_ndisc_neighbor *na, struct ether_addr *ret) {
+ assert_return(na, -EINVAL);
+
+ return ndisc_option_get_mac(na->options, SD_NDISC_OPTION_TARGET_LL_ADDRESS, ret);
+}
+
+int sd_ndisc_neighbor_get_flags(sd_ndisc_neighbor *na, uint32_t *ret) {
+ assert_return(na, -EINVAL);
+
+ if (ret)
+ *ret = na->flags;
+ return 0;
+}
+
+int sd_ndisc_neighbor_is_router(sd_ndisc_neighbor *na) {
+ assert_return(na, -EINVAL);
+
+ return FLAGS_SET(na->flags, ND_NA_FLAG_ROUTER);
+}
+
+int sd_ndisc_neighbor_is_solicited(sd_ndisc_neighbor *na) {
+ assert_return(na, -EINVAL);
+
+ return FLAGS_SET(na->flags, ND_NA_FLAG_SOLICITED);
+}
+
+int sd_ndisc_neighbor_is_override(sd_ndisc_neighbor *na) {
+ assert_return(na, -EINVAL);
+
+ return FLAGS_SET(na->flags, ND_NA_FLAG_OVERRIDE);
+}
diff --git a/src/libsystemd-network/sd-ndisc.c b/src/libsystemd-network/sd-ndisc.c
index 18752a94e7..373e7a45ce 100644
--- a/src/libsystemd-network/sd-ndisc.c
+++ b/src/libsystemd-network/sd-ndisc.c
@@ -16,6 +16,7 @@
#include "in-addr-util.h"
#include "memory-util.h"
#include "ndisc-internal.h"
+#include "ndisc-neighbor-internal.h"
#include "ndisc-router-internal.h"
#include "network-common.h"
#include "random-util.h"
@@ -26,8 +27,9 @@
#define NDISC_TIMEOUT_NO_RA_USEC (NDISC_ROUTER_SOLICITATION_INTERVAL * NDISC_MAX_ROUTER_SOLICITATIONS)
static const char * const ndisc_event_table[_SD_NDISC_EVENT_MAX] = {
- [SD_NDISC_EVENT_TIMEOUT] = "timeout",
- [SD_NDISC_EVENT_ROUTER] = "router",
+ [SD_NDISC_EVENT_TIMEOUT] = "timeout",
+ [SD_NDISC_EVENT_ROUTER] = "router",
+ [SD_NDISC_EVENT_NEIGHBOR] = "neighbor",
};
DEFINE_STRING_TABLE_LOOKUP(ndisc_event, sd_ndisc_event_t);
@@ -225,6 +227,36 @@ static int ndisc_handle_router(sd_ndisc *nd, ICMP6Packet *packet) {
return 0;
}
+static int ndisc_handle_neighbor(sd_ndisc *nd, ICMP6Packet *packet) {
+ _cleanup_(sd_ndisc_neighbor_unrefp) sd_ndisc_neighbor *na = NULL;
+ struct in6_addr a;
+ int r;
+
+ assert(nd);
+ assert(packet);
+
+ na = ndisc_neighbor_new(packet);
+ if (!na)
+ return -ENOMEM;
+
+ r = ndisc_neighbor_parse(nd, na);
+ if (r < 0)
+ return r;
+
+ r = sd_ndisc_neighbor_get_sender_address(na, &a);
+ if (r < 0)
+ return r;
+
+ log_ndisc(nd, "Received Neighbor Advertisement from %s: Router=%s, Solicited=%s, Override=%s",
+ IN6_ADDR_TO_STRING(&a),
+ yes_no(sd_ndisc_neighbor_is_router(na) > 0),
+ yes_no(sd_ndisc_neighbor_is_solicited(na) > 0),
+ yes_no(sd_ndisc_neighbor_is_override(na) > 0));
+
+ ndisc_callback(nd, SD_NDISC_EVENT_NEIGHBOR, na);
+ return 0;
+}
+
static int ndisc_recv(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
_cleanup_(icmp6_packet_unrefp) ICMP6Packet *packet = NULL;
sd_ndisc *nd = ASSERT_PTR(userdata);
@@ -262,6 +294,10 @@ static int ndisc_recv(sd_event_source *s, int fd, uint32_t revents, void *userda
(void) ndisc_handle_router(nd, packet);
break;
+ case ND_NEIGHBOR_ADVERT:
+ (void) ndisc_handle_neighbor(nd, packet);
+ break;
+
default:
log_ndisc(nd, "Received an ICMPv6 packet with unexpected type %i, ignoring.", r);
}
diff --git a/src/libsystemd-network/test-ndisc-rs.c b/src/libsystemd-network/test-ndisc-rs.c
index 5bf3e84db9..5ad2c92b49 100644
--- a/src/libsystemd-network/test-ndisc-rs.c
+++ b/src/libsystemd-network/test-ndisc-rs.c
@@ -195,7 +195,7 @@ static int send_ra(uint8_t flags) {
return 0;
}
-static void test_callback(sd_ndisc *nd, sd_ndisc_event_t event, void *message, void *userdata) {
+static void test_callback_ra(sd_ndisc *nd, sd_ndisc_event_t event, void *message, void *userdata) {
sd_event *e = userdata;
static unsigned idx = 0;
uint64_t flags_array[] = {
@@ -253,7 +253,7 @@ TEST(rs) {
assert_se(sd_ndisc_set_ifindex(nd, 42) >= 0);
assert_se(sd_ndisc_set_mac(nd, &mac_addr) >= 0);
- assert_se(sd_ndisc_set_callback(nd, test_callback, e) >= 0);
+ assert_se(sd_ndisc_set_callback(nd, test_callback_ra, e) >= 0);
assert_se(sd_event_add_time_relative(e, NULL, CLOCK_BOOTTIME,
30 * USEC_PER_SEC, 0,
@@ -342,7 +342,7 @@ TEST(invalid_domain) {
assert_se(sd_ndisc_set_ifindex(nd, 42) >= 0);
assert_se(sd_ndisc_set_mac(nd, &mac_addr) >= 0);
- assert_se(sd_ndisc_set_callback(nd, test_callback, e) >= 0);
+ assert_se(sd_ndisc_set_callback(nd, test_callback_ra, e) >= 0);
assert_se(sd_event_add_time_relative(e, NULL, CLOCK_BOOTTIME,
30 * USEC_PER_SEC, 0,
@@ -358,6 +358,120 @@ TEST(invalid_domain) {
test_fd[1] = -EBADF;
}
+static void neighbor_dump(sd_ndisc_neighbor *na) {
+ struct in6_addr addr;
+ uint32_t flags;
+
+ assert_se(na);
+
+ log_info("--");
+ assert_se(sd_ndisc_neighbor_get_sender_address(na, &addr) >= 0);
+ log_info("Sender: %s", IN6_ADDR_TO_STRING(&addr));
+
+ assert_se(sd_ndisc_neighbor_get_flags(na, &flags) >= 0);
+ log_info("Flags: Router:%s, Solicited:%s, Override: %s",
+ yes_no(flags & ND_NA_FLAG_ROUTER),
+ yes_no(flags & ND_NA_FLAG_SOLICITED),
+ yes_no(flags & ND_NA_FLAG_OVERRIDE));
+
+ assert_se(sd_ndisc_neighbor_is_router(na) == FLAGS_SET(flags, ND_NA_FLAG_ROUTER));
+ assert_se(sd_ndisc_neighbor_is_solicited(na) == FLAGS_SET(flags, ND_NA_FLAG_SOLICITED));
+ assert_se(sd_ndisc_neighbor_is_override(na) == FLAGS_SET(flags, ND_NA_FLAG_OVERRIDE));
+}
+
+static int send_na(uint32_t flags) {
+ uint8_t advertisement[] = {
+ /* struct nd_neighbor_advert */
+ 0x88, 0x00, 0xde, 0x83, 0x00, 0x00, 0x00, 0x00,
+ 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ /* type = 0x02 (SD_NDISC_OPTION_TARGET_LL_ADDRESS), length = 8 */
+ 0x01, 0x01, 'A', 'B', 'C', '1', '2', '3',
+ };
+
+ ((struct nd_neighbor_advert*) advertisement)->nd_na_flags_reserved = flags;
+
+ assert_se(write(test_fd[1], advertisement, sizeof(advertisement)) == sizeof(advertisement));
+ if (verbose)
+ printf(" sent NA with flag 0x%02x\n", flags);
+
+ return 0;
+}
+
+static void test_callback_na(sd_ndisc *nd, sd_ndisc_event_t event, void *message, void *userdata) {
+ sd_event *e = userdata;
+ static unsigned idx = 0;
+ uint32_t flags_array[] = {
+ 0,
+ 0,
+ ND_NA_FLAG_ROUTER,
+ ND_NA_FLAG_SOLICITED,
+ ND_NA_FLAG_SOLICITED | ND_NA_FLAG_OVERRIDE,
+ };
+ uint32_t flags;
+
+ assert_se(nd);
+
+ if (event != SD_NDISC_EVENT_NEIGHBOR)
+ return;
+
+ sd_ndisc_neighbor *rt = ASSERT_PTR(message);
+
+ neighbor_dump(rt);
+
+ assert_se(sd_ndisc_neighbor_get_flags(rt, &flags) >= 0);
+ assert_se(flags == flags_array[idx]);
+ idx++;
+
+ if (verbose)
+ printf(" got event 0x%02" PRIx32 "\n", flags);
+
+ if (idx < ELEMENTSOF(flags_array)) {
+ send_na(flags_array[idx]);
+ return;
+ }
+
+ idx = 0;
+ sd_event_exit(e, 0);
+}
+
+static int on_recv_rs_na(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
+ _cleanup_(icmp6_packet_unrefp) ICMP6Packet *packet = NULL;
+ assert_se(icmp6_packet_receive(fd, &packet) >= 0);
+
+ return send_na(0);
+}
+
+TEST(na) {
+ _cleanup_(sd_event_unrefp) sd_event *e = NULL;
+ _cleanup_(sd_event_source_unrefp) sd_event_source *s = NULL;
+ _cleanup_(sd_ndisc_unrefp) sd_ndisc *nd = NULL;
+
+ assert_se(sd_event_new(&e) >= 0);
+
+ assert_se(sd_ndisc_new(&nd) >= 0);
+ assert_se(nd);
+
+ assert_se(sd_ndisc_attach_event(nd, e, 0) >= 0);
+
+ assert_se(sd_ndisc_set_ifindex(nd, 42) >= 0);
+ assert_se(sd_ndisc_set_mac(nd, &mac_addr) >= 0);
+ assert_se(sd_ndisc_set_callback(nd, test_callback_na, e) >= 0);
+
+ assert_se(sd_event_add_time_relative(e, NULL, CLOCK_BOOTTIME,
+ 30 * USEC_PER_SEC, 0,
+ NULL, INT_TO_PTR(-ETIMEDOUT)) >= 0);
+
+ assert_se(sd_ndisc_start(nd) >= 0);
+
+ assert_se(sd_event_add_io(e, &s, test_fd[1], EPOLLIN, on_recv_rs_na, nd) >= 0);
+ assert_se(sd_event_source_set_io_fd_own(s, true) >= 0);
+
+ assert_se(sd_event_loop(e) >= 0);
+
+ test_fd[1] = -EBADF;
+}
+
static int on_recv_rs_timeout(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
_cleanup_(icmp6_packet_unrefp) ICMP6Packet *packet = NULL;
sd_ndisc *nd = ASSERT_PTR(userdata);
diff --git a/src/libsystemd/sd-journal/fsprg.c b/src/libsystemd/sd-journal/fsprg.c
index e86be6af35..5321bb89bf 100644
--- a/src/libsystemd/sd-journal/fsprg.c
+++ b/src/libsystemd/sd-journal/fsprg.c
@@ -50,11 +50,11 @@ static void mpi_export(void *buf, size_t buflen, const gcry_mpi_t x) {
unsigned len;
size_t nwritten;
- assert(gcry_mpi_cmp_ui(x, 0) >= 0);
- len = (gcry_mpi_get_nbits(x) + 7) / 8;
+ assert(sym_gcry_mpi_cmp_ui(x, 0) >= 0);
+ len = (sym_gcry_mpi_get_nbits(x) + 7) / 8;
assert(len <= buflen);
memzero(buf, buflen);
- gcry_mpi_print(GCRYMPI_FMT_USG, buf + (buflen - len), len, &nwritten, x);
+ sym_gcry_mpi_print(GCRYMPI_FMT_USG, buf + (buflen - len), len, &nwritten, x);
assert(nwritten == len);
}
@@ -62,10 +62,10 @@ static gcry_mpi_t mpi_import(const void *buf, size_t buflen) {
gcry_mpi_t h;
_unused_ unsigned len;
- assert_se(gcry_mpi_scan(&h, GCRYMPI_FMT_USG, buf, buflen, NULL) == 0);
- len = (gcry_mpi_get_nbits(h) + 7) / 8;
+ assert_se(sym_gcry_mpi_scan(&h, GCRYMPI_FMT_USG, buf, buflen, NULL) == 0);
+ len = (sym_gcry_mpi_get_nbits(h) + 7) / 8;
assert(len <= buflen);
- assert(gcry_mpi_cmp_ui(h, 0) >= 0);
+ assert(sym_gcry_mpi_cmp_ui(h, 0) >= 0);
return h;
}
@@ -102,30 +102,30 @@ static void det_randomize(void *buf, size_t buflen, const void *seed, size_t see
gcry_error_t err;
uint32_t ctr;
- olen = gcry_md_get_algo_dlen(RND_HASH);
- err = gcry_md_open(&hd, RND_HASH, 0);
+ olen = sym_gcry_md_get_algo_dlen(RND_HASH);
+ err = sym_gcry_md_open(&hd, RND_HASH, 0);
assert_se(gcry_err_code(err) == GPG_ERR_NO_ERROR); /* This shouldn't happen */
- gcry_md_write(hd, seed, seedlen);
- gcry_md_putc(hd, (idx >> 24) & 0xff);
- gcry_md_putc(hd, (idx >> 16) & 0xff);
- gcry_md_putc(hd, (idx >> 8) & 0xff);
- gcry_md_putc(hd, (idx >> 0) & 0xff);
+ sym_gcry_md_write(hd, seed, seedlen);
+ sym_gcry_md_putc(hd, (idx >> 24) & 0xff);
+ sym_gcry_md_putc(hd, (idx >> 16) & 0xff);
+ sym_gcry_md_putc(hd, (idx >> 8) & 0xff);
+ sym_gcry_md_putc(hd, (idx >> 0) & 0xff);
for (ctr = 0; buflen; ctr++) {
- err = gcry_md_copy(&hd2, hd);
+ err = sym_gcry_md_copy(&hd2, hd);
assert_se(gcry_err_code(err) == GPG_ERR_NO_ERROR); /* This shouldn't happen */
- gcry_md_putc(hd2, (ctr >> 24) & 0xff);
- gcry_md_putc(hd2, (ctr >> 16) & 0xff);
- gcry_md_putc(hd2, (ctr >> 8) & 0xff);
- gcry_md_putc(hd2, (ctr >> 0) & 0xff);
- gcry_md_final(hd2);
+ sym_gcry_md_putc(hd2, (ctr >> 24) & 0xff);
+ sym_gcry_md_putc(hd2, (ctr >> 16) & 0xff);
+ sym_gcry_md_putc(hd2, (ctr >> 8) & 0xff);
+ sym_gcry_md_putc(hd2, (ctr >> 0) & 0xff);
+ sym_gcry_md_ctl(hd2, GCRYCTL_FINALIZE, NULL, 0);
cpylen = (buflen < olen) ? buflen : olen;
- memcpy(buf, gcry_md_read(hd2, RND_HASH), cpylen);
- gcry_md_close(hd2);
+ memcpy(buf, sym_gcry_md_read(hd2, RND_HASH), cpylen);
+ sym_gcry_md_close(hd2);
buf += cpylen;
buflen -= cpylen;
}
- gcry_md_close(hd);
+ sym_gcry_md_close(hd);
}
/* deterministically generate from seed/idx a prime of length `bits' that is 3 (mod 4) */
@@ -142,8 +142,8 @@ static gcry_mpi_t genprime3mod4(int bits, const void *seed, size_t seedlen, uint
buf[buflen - 1] |= 0x03; /* set lower two bits, to have result 3 (mod 4) */
p = mpi_import(buf, buflen);
- while (gcry_prime_check(p, 0))
- gcry_mpi_add_ui(p, p, 4);
+ while (sym_gcry_prime_check(p, 0))
+ sym_gcry_mpi_add_ui(p, p, 4);
return p;
}
@@ -157,8 +157,8 @@ static gcry_mpi_t gensquare(const gcry_mpi_t n, const void *seed, size_t seedlen
det_randomize(buf, buflen, seed, seedlen, idx);
buf[0] &= 0x7f; /* clear upper bit, so that we have x < n */
x = mpi_import(buf, buflen);
- assert(gcry_mpi_cmp(x, n) < 0);
- gcry_mpi_mulm(x, x, x, n);
+ assert(sym_gcry_mpi_cmp(x, n) < 0);
+ sym_gcry_mpi_mulm(x, x, x, n);
return x;
}
@@ -167,51 +167,51 @@ static gcry_mpi_t twopowmodphi(uint64_t m, const gcry_mpi_t p) {
gcry_mpi_t phi, r;
int n;
- phi = gcry_mpi_new(0);
- gcry_mpi_sub_ui(phi, p, 1);
+ phi = sym_gcry_mpi_new(0);
+ sym_gcry_mpi_sub_ui(phi, p, 1);
/* count number of used bits in m */
for (n = 0; (1ULL << n) <= m; n++)
;
- r = gcry_mpi_new(0);
- gcry_mpi_set_ui(r, 1);
+ r = sym_gcry_mpi_new(0);
+ sym_gcry_mpi_set_ui(r, 1);
while (n) { /* square and multiply algorithm for fast exponentiation */
n--;
- gcry_mpi_mulm(r, r, r, phi);
+ sym_gcry_mpi_mulm(r, r, r, phi);
if (m & ((uint64_t)1 << n)) {
- gcry_mpi_add(r, r, r);
- if (gcry_mpi_cmp(r, phi) >= 0)
- gcry_mpi_sub(r, r, phi);
+ sym_gcry_mpi_add(r, r, r);
+ if (sym_gcry_mpi_cmp(r, phi) >= 0)
+ sym_gcry_mpi_sub(r, r, phi);
}
}
- gcry_mpi_release(phi);
+ sym_gcry_mpi_release(phi);
return r;
}
/* Decompose $x \in Z_n$ into $(xp,xq) \in Z_p \times Z_q$ using Chinese Remainder Theorem */
static void CRT_decompose(gcry_mpi_t *xp, gcry_mpi_t *xq, const gcry_mpi_t x, const gcry_mpi_t p, const gcry_mpi_t q) {
- *xp = gcry_mpi_new(0);
- *xq = gcry_mpi_new(0);
- gcry_mpi_mod(*xp, x, p);
- gcry_mpi_mod(*xq, x, q);
+ *xp = sym_gcry_mpi_new(0);
+ *xq = sym_gcry_mpi_new(0);
+ sym_gcry_mpi_mod(*xp, x, p);
+ sym_gcry_mpi_mod(*xq, x, q);
}
/* Compose $(xp,xq) \in Z_p \times Z_q$ into $x \in Z_n$ using Chinese Remainder Theorem */
static void CRT_compose(gcry_mpi_t *x, const gcry_mpi_t xp, const gcry_mpi_t xq, const gcry_mpi_t p, const gcry_mpi_t q) {
gcry_mpi_t a, u;
- a = gcry_mpi_new(0);
- u = gcry_mpi_new(0);
- *x = gcry_mpi_new(0);
- gcry_mpi_subm(a, xq, xp, q);
- gcry_mpi_invm(u, p, q);
- gcry_mpi_mulm(a, a, u, q); /* a = (xq - xp) / p (mod q) */
- gcry_mpi_mul(*x, p, a);
- gcry_mpi_add(*x, *x, xp); /* x = p * ((xq - xp) / p mod q) + xp */
- gcry_mpi_release(a);
- gcry_mpi_release(u);
+ a = sym_gcry_mpi_new(0);
+ u = sym_gcry_mpi_new(0);
+ *x = sym_gcry_mpi_new(0);
+ sym_gcry_mpi_subm(a, xq, xp, q);
+ sym_gcry_mpi_invm(u, p, q);
+ sym_gcry_mpi_mulm(a, a, u, q); /* a = (xq - xp) / p (mod q) */
+ sym_gcry_mpi_mul(*x, p, a);
+ sym_gcry_mpi_add(*x, *x, xp); /* x = p * ((xq - xp) / p mod q) + xp */
+ sym_gcry_mpi_release(a);
+ sym_gcry_mpi_release(u);
}
/******************************************************************************/
@@ -245,18 +245,21 @@ static uint16_t read_secpar(const void *buf) {
return 16 * (secpar + 1);
}
-void FSPRG_GenMK(void *msk, void *mpk, const void *seed, size_t seedlen, unsigned _secpar) {
+int FSPRG_GenMK(void *msk, void *mpk, const void *seed, size_t seedlen, unsigned _secpar) {
uint8_t iseed[FSPRG_RECOMMENDED_SEEDLEN];
gcry_mpi_t n, p, q;
uint16_t secpar;
+ int r;
VALIDATE_SECPAR(_secpar);
secpar = _secpar;
- initialize_libgcrypt(false);
+ r = initialize_libgcrypt(false);
+ if (r < 0)
+ return r;
if (!seed) {
- gcry_randomize(iseed, FSPRG_RECOMMENDED_SEEDLEN, GCRY_STRONG_RANDOM);
+ sym_gcry_randomize(iseed, FSPRG_RECOMMENDED_SEEDLEN, GCRY_STRONG_RANDOM);
seed = iseed;
seedlen = FSPRG_RECOMMENDED_SEEDLEN;
}
@@ -271,25 +274,30 @@ void FSPRG_GenMK(void *msk, void *mpk, const void *seed, size_t seedlen, unsigne
}
if (mpk) {
- n = gcry_mpi_new(0);
- gcry_mpi_mul(n, p, q);
- assert(gcry_mpi_get_nbits(n) == secpar);
+ n = sym_gcry_mpi_new(0);
+ sym_gcry_mpi_mul(n, p, q);
+ assert(sym_gcry_mpi_get_nbits(n) == secpar);
store_secpar(mpk + 0, secpar);
mpi_export(mpk + 2, secpar / 8, n);
- gcry_mpi_release(n);
+ sym_gcry_mpi_release(n);
}
- gcry_mpi_release(p);
- gcry_mpi_release(q);
+ sym_gcry_mpi_release(p);
+ sym_gcry_mpi_release(q);
+
+ return 0;
}
-void FSPRG_GenState0(void *state, const void *mpk, const void *seed, size_t seedlen) {
+int FSPRG_GenState0(void *state, const void *mpk, const void *seed, size_t seedlen) {
gcry_mpi_t n, x;
uint16_t secpar;
+ int r;
- initialize_libgcrypt(false);
+ r = initialize_libgcrypt(false);
+ if (r < 0)
+ return r;
secpar = read_secpar(mpk + 0);
n = mpi_import(mpk + 2, secpar / 8);
@@ -299,30 +307,37 @@ void FSPRG_GenState0(void *state, const void *mpk, const void *seed, size_t seed
mpi_export(state + 2 + 1 * secpar / 8, secpar / 8, x);
memzero(state + 2 + 2 * secpar / 8, 8);
- gcry_mpi_release(n);
- gcry_mpi_release(x);
+ sym_gcry_mpi_release(n);
+ sym_gcry_mpi_release(x);
+
+ return 0;
}
-void FSPRG_Evolve(void *state) {
+int FSPRG_Evolve(void *state) {
gcry_mpi_t n, x;
uint16_t secpar;
uint64_t epoch;
+ int r;
- initialize_libgcrypt(false);
+ r = initialize_libgcrypt(false);
+ if (r < 0)
+ return r;
secpar = read_secpar(state + 0);
n = mpi_import(state + 2 + 0 * secpar / 8, secpar / 8);
x = mpi_import(state + 2 + 1 * secpar / 8, secpar / 8);
epoch = uint64_import(state + 2 + 2 * secpar / 8, 8);
- gcry_mpi_mulm(x, x, x, n);
+ sym_gcry_mpi_mulm(x, x, x, n);
epoch++;
mpi_export(state + 2 + 1 * secpar / 8, secpar / 8, x);
uint64_export(state + 2 + 2 * secpar / 8, 8, epoch);
- gcry_mpi_release(n);
- gcry_mpi_release(x);
+ sym_gcry_mpi_release(n);
+ sym_gcry_mpi_release(x);
+
+ return 0;
}
uint64_t FSPRG_GetEpoch(const void *state) {
@@ -331,18 +346,21 @@ uint64_t FSPRG_GetEpoch(const void *state) {
return uint64_import(state + 2 + 2 * secpar / 8, 8);
}
-void FSPRG_Seek(void *state, uint64_t epoch, const void *msk, const void *seed, size_t seedlen) {
+int FSPRG_Seek(void *state, uint64_t epoch, const void *msk, const void *seed, size_t seedlen) {
gcry_mpi_t p, q, n, x, xp, xq, kp, kq, xm;
uint16_t secpar;
+ int r;
- initialize_libgcrypt(false);
+ r = initialize_libgcrypt(false);
+ if (r < 0)
+ return r;
secpar = read_secpar(msk + 0);
p = mpi_import(msk + 2 + 0 * (secpar / 2) / 8, (secpar / 2) / 8);
q = mpi_import(msk + 2 + 1 * (secpar / 2) / 8, (secpar / 2) / 8);
- n = gcry_mpi_new(0);
- gcry_mpi_mul(n, p, q);
+ n = sym_gcry_mpi_new(0);
+ sym_gcry_mpi_mul(n, p, q);
x = gensquare(n, seed, seedlen, RND_GEN_X, secpar);
CRT_decompose(&xp, &xq, x, p, q); /* split (mod n) into (mod p) and (mod q) using CRT */
@@ -350,8 +368,8 @@ void FSPRG_Seek(void *state, uint64_t epoch, const void *msk, const void *seed,
kp = twopowmodphi(epoch, p); /* compute 2^epoch (mod phi(p)) */
kq = twopowmodphi(epoch, q); /* compute 2^epoch (mod phi(q)) */
- gcry_mpi_powm(xp, xp, kp, p); /* compute x^(2^epoch) (mod p) */
- gcry_mpi_powm(xq, xq, kq, q); /* compute x^(2^epoch) (mod q) */
+ sym_gcry_mpi_powm(xp, xp, kp, p); /* compute x^(2^epoch) (mod p) */
+ sym_gcry_mpi_powm(xq, xq, kq, q); /* compute x^(2^epoch) (mod q) */
CRT_compose(&xm, xp, xq, p, q); /* combine (mod p) and (mod q) to (mod n) using CRT */
@@ -360,22 +378,29 @@ void FSPRG_Seek(void *state, uint64_t epoch, const void *msk, const void *seed,
mpi_export(state + 2 + 1 * secpar / 8, secpar / 8, xm);
uint64_export(state + 2 + 2 * secpar / 8, 8, epoch);
- gcry_mpi_release(p);
- gcry_mpi_release(q);
- gcry_mpi_release(n);
- gcry_mpi_release(x);
- gcry_mpi_release(xp);
- gcry_mpi_release(xq);
- gcry_mpi_release(kp);
- gcry_mpi_release(kq);
- gcry_mpi_release(xm);
+ sym_gcry_mpi_release(p);
+ sym_gcry_mpi_release(q);
+ sym_gcry_mpi_release(n);
+ sym_gcry_mpi_release(x);
+ sym_gcry_mpi_release(xp);
+ sym_gcry_mpi_release(xq);
+ sym_gcry_mpi_release(kp);
+ sym_gcry_mpi_release(kq);
+ sym_gcry_mpi_release(xm);
+
+ return 0;
}
-void FSPRG_GetKey(const void *state, void *key, size_t keylen, uint32_t idx) {
+int FSPRG_GetKey(const void *state, void *key, size_t keylen, uint32_t idx) {
uint16_t secpar;
+ int r;
- initialize_libgcrypt(false);
+ r = initialize_libgcrypt(false);
+ if (r < 0)
+ return r;
secpar = read_secpar(state + 0);
det_randomize(key, keylen, state + 2, 2 * secpar / 8 + 8, idx);
+
+ return 0;
}
diff --git a/src/libsystemd/sd-journal/fsprg.h b/src/libsystemd/sd-journal/fsprg.h
index d3d88aab31..5884488549 100644
--- a/src/libsystemd/sd-journal/fsprg.h
+++ b/src/libsystemd/sd-journal/fsprg.h
@@ -39,22 +39,22 @@ size_t FSPRG_mpkinbytes(unsigned secpar) _const_;
size_t FSPRG_stateinbytes(unsigned secpar) _const_;
/* Setup msk and mpk. Providing seed != NULL makes this algorithm deterministic. */
-void FSPRG_GenMK(void *msk, void *mpk, const void *seed, size_t seedlen, unsigned secpar);
+int FSPRG_GenMK(void *msk, void *mpk, const void *seed, size_t seedlen, unsigned secpar);
/* Initialize state deterministically in dependence on seed. */
/* Note: in case one wants to run only one GenState0 per GenMK it is safe to use
the same seed for both GenMK and GenState0.
*/
-void FSPRG_GenState0(void *state, const void *mpk, const void *seed, size_t seedlen);
+int FSPRG_GenState0(void *state, const void *mpk, const void *seed, size_t seedlen);
-void FSPRG_Evolve(void *state);
+int FSPRG_Evolve(void *state);
uint64_t FSPRG_GetEpoch(const void *state) _pure_;
/* Seek to any arbitrary state (by providing msk together with seed from GenState0). */
-void FSPRG_Seek(void *state, uint64_t epoch, const void *msk, const void *seed, size_t seedlen);
+int FSPRG_Seek(void *state, uint64_t epoch, const void *msk, const void *seed, size_t seedlen);
-void FSPRG_GetKey(const void *state, void *key, size_t keylen, uint32_t idx);
+int FSPRG_GetKey(const void *state, void *key, size_t keylen, uint32_t idx);
#ifdef __cplusplus
}
diff --git a/src/libsystemd/sd-journal/journal-authenticate.c b/src/libsystemd/sd-journal/journal-authenticate.c
index 8e7533eee3..64f5739ba8 100644
--- a/src/libsystemd/sd-journal/journal-authenticate.c
+++ b/src/libsystemd/sd-journal/journal-authenticate.c
@@ -71,7 +71,7 @@ int journal_file_append_tag(JournalFile *f) {
return r;
/* Get the HMAC tag and store it in the object */
- memcpy(o->tag.tag, gcry_md_read(f->hmac, 0), TAG_LENGTH);
+ memcpy(o->tag.tag, sym_gcry_md_read(f->hmac, 0), TAG_LENGTH);
f->hmac_running = false;
return 0;
@@ -80,6 +80,7 @@ int journal_file_append_tag(JournalFile *f) {
int journal_file_hmac_start(JournalFile *f) {
uint8_t key[256 / 8]; /* Let's pass 256 bit from FSPRG to HMAC */
gcry_error_t err;
+ int r;
assert(f);
@@ -90,13 +91,17 @@ int journal_file_hmac_start(JournalFile *f) {
return 0;
/* Prepare HMAC for next cycle */
- gcry_md_reset(f->hmac);
- FSPRG_GetKey(f->fsprg_state, key, sizeof(key), 0);
- err = gcry_md_setkey(f->hmac, key, sizeof(key));
+ sym_gcry_md_reset(f->hmac);
+
+ r = FSPRG_GetKey(f->fsprg_state, key, sizeof(key), 0);
+ if (r < 0)
+ return r;
+
+ err = sym_gcry_md_setkey(f->hmac, key, sizeof(key));
if (gcry_err_code(err) != GPG_ERR_NO_ERROR)
return log_debug_errno(SYNTHETIC_ERRNO(EIO),
- "gcry_md_setkey() failed with error code: %s",
- gcry_strerror(err));
+ "sym_gcry_md_setkey() failed with error code: %s",
+ sym_gcry_strerror(err));
f->hmac_running = true;
@@ -167,7 +172,10 @@ int journal_file_fsprg_evolve(JournalFile *f, uint64_t realtime) {
if (epoch == goal)
return 0;
- FSPRG_Evolve(f->fsprg_state);
+ r = FSPRG_Evolve(f->fsprg_state);
+ if (r < 0)
+ return r;
+
epoch = FSPRG_GetEpoch(f->fsprg_state);
if (epoch < goal) {
r = journal_file_append_tag(f);
@@ -180,6 +188,7 @@ int journal_file_fsprg_evolve(JournalFile *f, uint64_t realtime) {
int journal_file_fsprg_seek(JournalFile *f, uint64_t goal) {
void *msk;
uint64_t epoch;
+ int r;
assert(f);
@@ -195,10 +204,8 @@ int journal_file_fsprg_seek(JournalFile *f, uint64_t goal) {
if (goal == epoch)
return 0;
- if (goal == epoch + 1) {
- FSPRG_Evolve(f->fsprg_state);
- return 0;
- }
+ if (goal == epoch + 1)
+ return FSPRG_Evolve(f->fsprg_state);
} else {
f->fsprg_state_size = FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR);
f->fsprg_state = malloc(f->fsprg_state_size);
@@ -209,10 +216,12 @@ int journal_file_fsprg_seek(JournalFile *f, uint64_t goal) {
log_debug("Seeking FSPRG key to %"PRIu64".", goal);
msk = alloca_safe(FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR));
- FSPRG_GenMK(msk, NULL, f->fsprg_seed, f->fsprg_seed_size, FSPRG_RECOMMENDED_SECPAR);
- FSPRG_Seek(f->fsprg_state, goal, msk, f->fsprg_seed, f->fsprg_seed_size);
- return 0;
+ r = FSPRG_GenMK(msk, NULL, f->fsprg_seed, f->fsprg_seed_size, FSPRG_RECOMMENDED_SECPAR);
+ if (r < 0)
+ return r;
+
+ return FSPRG_Seek(f->fsprg_state, goal, msk, f->fsprg_seed, f->fsprg_seed_size);
}
int journal_file_maybe_append_tag(JournalFile *f, uint64_t realtime) {
@@ -260,25 +269,25 @@ int journal_file_hmac_put_object(JournalFile *f, ObjectType type, Object *o, uin
} else if (type > OBJECT_UNUSED && o->object.type != type)
return -EBADMSG;
- gcry_md_write(f->hmac, o, offsetof(ObjectHeader, payload));
+ sym_gcry_md_write(f->hmac, o, offsetof(ObjectHeader, payload));
switch (o->object.type) {
case OBJECT_DATA:
/* All but hash and payload are mutable */
- gcry_md_write(f->hmac, &o->data.hash, sizeof(o->data.hash));
- gcry_md_write(f->hmac, journal_file_data_payload_field(f, o), le64toh(o->object.size) - journal_file_data_payload_offset(f));
+ sym_gcry_md_write(f->hmac, &o->data.hash, sizeof(o->data.hash));
+ sym_gcry_md_write(f->hmac, journal_file_data_payload_field(f, o), le64toh(o->object.size) - journal_file_data_payload_offset(f));
break;
case OBJECT_FIELD:
/* Same here */
- gcry_md_write(f->hmac, &o->field.hash, sizeof(o->field.hash));
- gcry_md_write(f->hmac, o->field.payload, le64toh(o->object.size) - offsetof(Object, field.payload));
+ sym_gcry_md_write(f->hmac, &o->field.hash, sizeof(o->field.hash));
+ sym_gcry_md_write(f->hmac, o->field.payload, le64toh(o->object.size) - offsetof(Object, field.payload));
break;
case OBJECT_ENTRY:
/* All */
- gcry_md_write(f->hmac, &o->entry.seqnum, le64toh(o->object.size) - offsetof(Object, entry.seqnum));
+ sym_gcry_md_write(f->hmac, &o->entry.seqnum, le64toh(o->object.size) - offsetof(Object, entry.seqnum));
break;
case OBJECT_FIELD_HASH_TABLE:
@@ -289,8 +298,8 @@ int journal_file_hmac_put_object(JournalFile *f, ObjectType type, Object *o, uin
case OBJECT_TAG:
/* All but the tag itself */
- gcry_md_write(f->hmac, &o->tag.seqnum, sizeof(o->tag.seqnum));
- gcry_md_write(f->hmac, &o->tag.epoch, sizeof(o->tag.epoch));
+ sym_gcry_md_write(f->hmac, &o->tag.seqnum, sizeof(o->tag.seqnum));
+ sym_gcry_md_write(f->hmac, &o->tag.epoch, sizeof(o->tag.epoch));
break;
default:
return -EINVAL;
@@ -318,10 +327,10 @@ int journal_file_hmac_put_header(JournalFile *f) {
* tail_entry_monotonic, n_data, n_fields, n_tags,
* n_entry_arrays. */
- gcry_md_write(f->hmac, f->header->signature, offsetof(Header, state) - offsetof(Header, signature));
- gcry_md_write(f->hmac, &f->header->file_id, offsetof(Header, tail_entry_boot_id) - offsetof(Header, file_id));
- gcry_md_write(f->hmac, &f->header->seqnum_id, offsetof(Header, arena_size) - offsetof(Header, seqnum_id));
- gcry_md_write(f->hmac, &f->header->data_hash_table_offset, offsetof(Header, tail_object_offset) - offsetof(Header, data_hash_table_offset));
+ sym_gcry_md_write(f->hmac, f->header->signature, offsetof(Header, state) - offsetof(Header, signature));
+ sym_gcry_md_write(f->hmac, &f->header->file_id, offsetof(Header, tail_entry_boot_id) - offsetof(Header, file_id));
+ sym_gcry_md_write(f->hmac, &f->header->seqnum_id, offsetof(Header, arena_size) - offsetof(Header, seqnum_id));
+ sym_gcry_md_write(f->hmac, &f->header->data_hash_table_offset, offsetof(Header, tail_object_offset) - offsetof(Header, data_hash_table_offset));
return 0;
}
@@ -406,13 +415,16 @@ int journal_file_fss_load(JournalFile *f) {
int journal_file_hmac_setup(JournalFile *f) {
gcry_error_t e;
+ int r;
if (!JOURNAL_HEADER_SEALED(f->header))
return 0;
- initialize_libgcrypt(true);
+ r = initialize_libgcrypt(true);
+ if (r < 0)
+ return r;
- e = gcry_md_open(&f->hmac, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC);
+ e = sym_gcry_md_open(&f->hmac, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC);
if (e != 0)
return -EOPNOTSUPP;
diff --git a/src/libsystemd/sd-journal/journal-file.c b/src/libsystemd/sd-journal/journal-file.c
index 6f29b47ff2..c6652f2359 100644
--- a/src/libsystemd/sd-journal/journal-file.c
+++ b/src/libsystemd/sd-journal/journal-file.c
@@ -20,6 +20,7 @@
#include "fd-util.h"
#include "format-util.h"
#include "fs-util.h"
+#include "gcrypt-util.h"
#include "id128-util.h"
#include "journal-authenticate.h"
#include "journal-def.h"
@@ -307,7 +308,7 @@ JournalFile* journal_file_close(JournalFile *f) {
free(f->fsprg_seed);
if (f->hmac)
- gcry_md_close(f->hmac);
+ sym_gcry_md_close(f->hmac);
#endif
return mfree(f);
@@ -637,7 +638,7 @@ static int journal_file_verify_header(JournalFile *f) {
return -ENODATA;
if (!VALID_REALTIME(le64toh(f->header->tail_entry_realtime)))
return -ENODATA;
- if (!VALID_MONOTONIC(le64toh(f->header->tail_entry_realtime)))
+ if (!VALID_MONOTONIC(le64toh(f->header->tail_entry_monotonic)))
return -ENODATA;
} else {
/* Otherwise, the fields must be zero. */
@@ -648,7 +649,7 @@ static int journal_file_verify_header(JournalFile *f) {
return -ENODATA;
if (f->header->tail_entry_realtime != 0)
return -ENODATA;
- if (f->header->tail_entry_realtime != 0)
+ if (f->header->tail_entry_monotonic != 0)
return -ENODATA;
}
}
@@ -2530,7 +2531,7 @@ int journal_file_append_entry(
ts->realtime);
if (!VALID_MONOTONIC(ts->monotonic))
return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
- "Invalid monotomic timestamp %" PRIu64 ", refusing entry.",
+ "Invalid monotonic timestamp %" PRIu64 ", refusing entry.",
ts->monotonic);
} else {
dual_timestamp_now(&_ts);
diff --git a/src/libsystemd/sd-journal/journal-verify.c b/src/libsystemd/sd-journal/journal-verify.c
index bdaa01d66f..2e09e71574 100644
--- a/src/libsystemd/sd-journal/journal-verify.c
+++ b/src/libsystemd/sd-journal/journal-verify.c
@@ -10,6 +10,7 @@
#include "fd-util.h"
#include "fileio.h"
#include "fs-util.h"
+#include "gcrypt-util.h"
#include "journal-authenticate.h"
#include "journal-def.h"
#include "journal-file.h"
@@ -1224,7 +1225,7 @@ int journal_file_verify(
if (r < 0)
goto fail;
- if (memcmp(o->tag.tag, gcry_md_read(f->hmac, 0), TAG_LENGTH) != 0) {
+ if (memcmp(o->tag.tag, sym_gcry_md_read(f->hmac, 0), TAG_LENGTH) != 0) {
error(p, "Tag failed verification");
r = -EBADMSG;
goto fail;
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index 5d27491af3..ee64d9a81a 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -4241,6 +4241,7 @@ int manager_start_scope(
char **ret_job) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL;
int r;
assert(manager);
@@ -4330,12 +4331,12 @@ int manager_start_scope(
if (r < 0)
return r;
- r = sd_bus_call(manager->bus, m, 0, error, &reply);
+ r = sd_bus_call(manager->bus, m, 0, &e, &reply);
if (r < 0) {
/* If this failed with a property we couldn't write, this is quite likely because the server
* doesn't support PIDFDs yet, let's try without. */
if (allow_pidfd &&
- sd_bus_error_has_names(error, SD_BUS_ERROR_UNKNOWN_PROPERTY, SD_BUS_ERROR_PROPERTY_READ_ONLY))
+ sd_bus_error_has_names(&e, SD_BUS_ERROR_UNKNOWN_PROPERTY, SD_BUS_ERROR_PROPERTY_READ_ONLY))
return manager_start_scope(
manager,
scope,
@@ -4350,7 +4351,7 @@ int manager_start_scope(
error,
ret_job);
- return r;
+ return sd_bus_error_move(error, &e);
}
return strdup_job(reply, ret_job);
diff --git a/src/login/logind.c b/src/login/logind.c
index 4d3d0270ef..ac4b8602c4 100644
--- a/src/login/logind.c
+++ b/src/login/logind.c
@@ -194,8 +194,11 @@ static int manager_enumerate_devices(Manager *m) {
r = 0;
- FOREACH_DEVICE(e, d)
+ FOREACH_DEVICE(e, d) {
+ if (device_is_processed(d) <= 0)
+ continue;
RET_GATHER(r, manager_process_seat_device(m, d));
+ }
return r;
}
@@ -225,8 +228,11 @@ static int manager_enumerate_buttons(Manager *m) {
r = 0;
- FOREACH_DEVICE(e, d)
+ FOREACH_DEVICE(e, d) {
+ if (device_is_processed(d) <= 0)
+ continue;
RET_GATHER(r, manager_process_button_device(m, d));
+ }
return r;
}
diff --git a/src/network/generator/main.c b/src/network/generator/main.c
index 4a3ccd6a99..4c8e5dee37 100644
--- a/src/network/generator/main.c
+++ b/src/network/generator/main.c
@@ -48,7 +48,7 @@ static int network_save(Network *network, const char *dest_dir) {
r = conservative_rename(temp_path, p);
if (r < 0)
- return r;
+ return log_error_errno(r, "Failed to rename '%s' to '%s': %m", temp_path, p);
temp_path = mfree(temp_path);
return 0;
@@ -79,7 +79,7 @@ static int netdev_save(NetDev *netdev, const char *dest_dir) {
r = conservative_rename(temp_path, p);
if (r < 0)
- return r;
+ return log_error_errno(r, "Failed to rename '%s' to '%s': %m", temp_path, p);
temp_path = mfree(temp_path);
return 0;
@@ -113,7 +113,7 @@ static int link_save(Link *link, const char *dest_dir) {
r = conservative_rename(temp_path, p);
if (r < 0)
- return r;
+ return log_error_errno(r, "Failed to rename '%s' to '%s': %m", temp_path, p);
temp_path = mfree(temp_path);
return 0;
diff --git a/src/network/generator/network-generator.c b/src/network/generator/network-generator.c
index 106e10a575..a5458e0a5f 100644
--- a/src/network/generator/network-generator.c
+++ b/src/network/generator/network-generator.c
@@ -373,13 +373,13 @@ static int network_set_dhcp_type(Context *context, const char *ifname, const cha
t = dracut_dhcp_type_from_string(dhcp_type);
if (t < 0)
- return t;
+ return log_debug_errno(t, "Invalid DHCP type '%s'", dhcp_type);
network = network_get(context, ifname);
if (!network) {
r = network_new(context, ifname, &network);
if (r < 0)
- return r;
+ return log_debug_errno(r, "Failed to create network for '%s': %m", ifname);
}
network->dhcp_type = t;
@@ -394,13 +394,14 @@ static int network_set_hostname(Context *context, const char *ifname, const char
network = network_get(context, ifname);
if (!network)
- return -ENODEV;
+ return log_debug_errno(SYNTHETIC_ERRNO(ENODEV), "No network found for '%s'", ifname);
return free_and_strdup(&network->hostname, hostname);
}
static int network_set_mtu(Context *context, const char *ifname, const char *mtu) {
Network *network;
+ int r;
assert(context);
assert(ifname);
@@ -410,13 +411,18 @@ static int network_set_mtu(Context *context, const char *ifname, const char *mtu
network = network_get(context, ifname);
if (!network)
- return -ENODEV;
+ return log_debug_errno(SYNTHETIC_ERRNO(ENODEV), "No network found for '%s'", ifname);
- return parse_mtu(AF_UNSPEC, mtu, &network->mtu);
+ r = parse_mtu(AF_UNSPEC, mtu, &network->mtu);
+ if (r < 0)
+ return log_debug_errno(r, "Invalid MTU '%s' for '%s': %m", mtu, ifname);
+
+ return r;
}
static int network_set_mac_address(Context *context, const char *ifname, const char *mac) {
Network *network;
+ int r;
assert(context);
assert(ifname);
@@ -424,9 +430,13 @@ static int network_set_mac_address(Context *context, const char *ifname, const c
network = network_get(context, ifname);
if (!network)
- return -ENODEV;
+ return log_debug_errno(SYNTHETIC_ERRNO(ENODEV), "No network found for '%s'", ifname);
- return parse_ether_addr(mac, &network->mac);
+ r = parse_ether_addr(mac, &network->mac);
+ if (r < 0)
+ return log_debug_errno(r, "Invalid MAC address '%s' for '%s'", mac, ifname);
+
+ return r;
}
static int network_set_address(Context *context, const char *ifname, int family, unsigned char prefixlen,
@@ -443,7 +453,7 @@ static int network_set_address(Context *context, const char *ifname, int family,
network = network_get(context, ifname);
if (!network)
- return -ENODEV;
+ return log_debug_errno(SYNTHETIC_ERRNO(ENODEV), "No network found for '%s'", ifname);
return address_new(network, family, prefixlen, addr, peer, NULL);
}
@@ -465,7 +475,7 @@ static int network_set_route(Context *context, const char *ifname, int family, u
if (!network) {
r = network_new(context, ifname, &network);
if (r < 0)
- return r;
+ return log_debug_errno(r, "Failed to create network for '%s': %m", ifname);
}
return route_new(network, family, prefixlen, dest, gateway, NULL);
@@ -486,13 +496,13 @@ static int network_set_dns(Context *context, const char *ifname, int family, con
else
r = in_addr_from_string(family, dns, &a);
if (r < 0)
- return r;
+ return log_debug_errno(r, "Invalid DNS address '%s' for '%s'", dns, ifname);
network = network_get(context, ifname);
if (!network) {
r = network_new(context, ifname, &network);
if (r < 0)
- return r;
+ return log_debug_errno(r, "Failed to create network for '%s': %m", ifname);
}
return strv_extend(&network->dns, dns);
@@ -509,7 +519,7 @@ static int network_set_dhcp_use_dns(Context *context, const char *ifname, bool v
if (!network) {
r = network_new(context, ifname, &network);
if (r < 0)
- return r;
+ return log_debug_errno(r, "Failed to create network for '%s': %m", ifname);
}
network->dhcp_use_dns = value;
@@ -528,7 +538,7 @@ static int network_set_vlan(Context *context, const char *ifname, const char *va
if (!network) {
r = network_new(context, ifname, &network);
if (r < 0)
- return r;
+ return log_debug_errno(r, "Failed to create network for '%s': %m", ifname);
}
return free_and_strdup(&network->vlan, value);
@@ -545,7 +555,7 @@ static int network_set_bridge(Context *context, const char *ifname, const char *
if (!network) {
r = network_new(context, ifname, &network);
if (r < 0)
- return r;
+ return log_debug_errno(r, "Failed to create network for '%s': %m", ifname);
}
return free_and_strdup(&network->bridge, value);
@@ -562,7 +572,7 @@ static int network_set_bond(Context *context, const char *ifname, const char *va
if (!network) {
r = network_new(context, ifname, &network);
if (r < 0)
- return r;
+ return log_debug_errno(r, "Failed to create network for '%s': %m", ifname);
}
return free_and_strdup(&network->bond, value);
@@ -615,21 +625,21 @@ static int parse_ip_address_one(int family, const char **value, union in_addr_un
if (family == AF_INET6) {
if (p[0] != '[')
- return -EINVAL;
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid IPv6 address '%s'", p);
q = strchr(p + 1, ']');
if (!q)
- return -EINVAL;
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid IPv6 address '%s'", p);
if (q[1] != ':')
- return -EINVAL;
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid IPv6 address '%s'", p);
buf = strndupa_safe(p + 1, q - p - 1);
p = q + 2;
} else {
q = strchr(p, ':');
if (!q)
- return -EINVAL;
+ log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid IPv4 address '%s'", p);
buf = strndupa_safe(p, q - p);
p = q + 1;
@@ -637,7 +647,7 @@ static int parse_ip_address_one(int family, const char **value, union in_addr_un
r = in_addr_from_string(family, buf, ret);
if (r < 0)
- return r;
+ return log_debug_errno(r, "Invalid IP address '%s': %m", buf);
*value = p;
return 1;
@@ -657,7 +667,7 @@ static int parse_netmask_or_prefixlen(int family, const char **value, unsigned c
if (r > 0) {
if (family == AF_INET6)
/* TODO: Not supported yet. */
- return -EINVAL;
+ return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "IPv6 prefix length is not supported yet");
*ret = in4_addr_netmask_to_prefixlen(&netmask.in);
} else if (r == 0)
@@ -665,12 +675,12 @@ static int parse_netmask_or_prefixlen(int family, const char **value, unsigned c
else {
p = strchr(*value, ':');
if (!p)
- return -EINVAL;
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid netmask or prefix length '%s'", *value);
q = strndupa_safe(*value, p - *value);
r = safe_atou8(q, ret);
if (r < 0)
- return r;
+ return log_debug_errno(r, "Invalid netmask or prefix length '%s': %m", q);
*value = p + 1;
}
@@ -693,10 +703,8 @@ static int parse_ip_dns_address_one(Context *context, const char *ifname, const
if (p[0] == '[') {
q = strchr(p + 1, ']');
- if (!q)
- return -EINVAL;
- if (!IN_SET(q[1], ':', '\0'))
- return -EINVAL;
+ if (!q || !IN_SET(q[1], ':', '\0'))
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid IP DNS address '%s'", p);
buf = strndupa_safe(p + 1, q - p - 1);
p = q + 1;
@@ -749,12 +757,12 @@ static int parse_cmdline_ip_address(Context *context, int family, const char *va
/* hostname */
p = strchr(value, ':');
if (!p)
- return -EINVAL;
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid IP address '%s'", value);
if (p != value) {
hostname = strndupa_safe(value, p - value);
if (!hostname_is_valid(hostname, 0))
- return -EINVAL;
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid hostname '%s'", hostname);
}
value = p + 1;
@@ -762,7 +770,7 @@ static int parse_cmdline_ip_address(Context *context, int family, const char *va
/* ifname */
p = strchr(value, ':');
if (!p)
- return -EINVAL;
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid IP address '%s'", value);
ifname = strndupa_safe(value, p - value);
@@ -813,7 +821,7 @@ static int parse_cmdline_ip_address(Context *context, int family, const char *va
/* refuse unexpected trailing strings */
if (!isempty(value))
- return -EINVAL;
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid IP address '%s'", value);
return 0;
}
@@ -829,7 +837,7 @@ static int parse_cmdline_ip_interface(Context *context, const char *value) {
p = strchr(value, ':');
if (!p)
- return -EINVAL;
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid IP address '%s'", value);
ifname = strndupa_safe(value, p - value);
@@ -858,7 +866,7 @@ static int parse_cmdline_ip(Context *context, const char *key, const char *value
assert(key);
if (proc_cmdline_value_missing(key, value))
- return -EINVAL;
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Missing value for '%s'", key);
p = strchr(value, ':');
if (!p)
@@ -887,15 +895,15 @@ static int parse_cmdline_rd_route(Context *context, const char *key, const char
/* rd.route=<net>/<netmask>:<gateway>[:<interface>] */
if (proc_cmdline_value_missing(key, value))
- return -EINVAL;
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Missing value for '%s'", key);
if (value[0] == '[') {
p = strchr(value, ']');
if (!p)
- return -EINVAL;
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid IPv6 address '%s'", value);
if (p[1] != ':')
- return -EINVAL;
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid IPv6 address '%s'", value);
buf = strndupa_safe(value + 1, p - value - 1);
value = p + 2;
@@ -903,7 +911,7 @@ static int parse_cmdline_rd_route(Context *context, const char *key, const char
} else {
p = strchr(value, ':');
if (!p)
- return -EINVAL;
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid IPv4 address '%s'", value);
buf = strndupa_safe(value, p - value);
value = p + 1;
@@ -912,7 +920,7 @@ static int parse_cmdline_rd_route(Context *context, const char *key, const char
r = in_addr_prefix_from_string(buf, family, &addr, &prefixlen);
if (r < 0)
- return r;
+ return log_debug_errno(r, "Invalid IP address '%s': %m", buf);
p = strchr(value, ':');
if (!p)
@@ -930,7 +938,7 @@ static int parse_cmdline_nameserver(Context *context, const char *key, const cha
assert(key);
if (proc_cmdline_value_missing(key, value))
- return -EINVAL;
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Missing value for '%s'", key);
return network_set_dns(context, "", AF_UNSPEC, value);
}
@@ -946,7 +954,7 @@ static int parse_cmdline_rd_peerdns(Context *context, const char *key, const cha
r = parse_boolean(value);
if (r < 0)
- return r;
+ return log_debug_errno(r, "Invalid boolean value '%s'", value);
return network_set_dhcp_use_dns(context, "", r);
}
@@ -960,11 +968,11 @@ static int parse_cmdline_vlan(Context *context, const char *key, const char *val
assert(key);
if (proc_cmdline_value_missing(key, value))
- return -EINVAL;
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Missing value for '%s'", key);
p = strchr(value, ':');
if (!p)
- return -EINVAL;
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid VLAN value '%s'", value);
name = strndupa_safe(value, p - value);
@@ -972,7 +980,7 @@ static int parse_cmdline_vlan(Context *context, const char *key, const char *val
if (!netdev) {
r = netdev_new(context, "vlan", name, &netdev);
if (r < 0)
- return r;
+ return log_debug_errno(r, "Failed to create VLAN device for '%s': %m", name);
}
return network_set_vlan(context, p + 1, name);
@@ -987,11 +995,11 @@ static int parse_cmdline_bridge(Context *context, const char *key, const char *v
assert(key);
if (proc_cmdline_value_missing(key, value))
- return -EINVAL;
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Missing value for '%s'", key);
p = strchr(value, ':');
if (!p)
- return -EINVAL;
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid bridge value '%s'", value);
name = strndupa_safe(value, p - value);
@@ -999,19 +1007,21 @@ static int parse_cmdline_bridge(Context *context, const char *key, const char *v
if (!netdev) {
r = netdev_new(context, "bridge", name, &netdev);
if (r < 0)
- return r;
+ return log_debug_errno(r, "Failed to create bridge device for '%s': %m", name);
}
p++;
if (isempty(p))
- return -EINVAL;
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Missing slave interfaces for bridge '%s'", name);
for (;;) {
_cleanup_free_ char *word = NULL;
r = extract_first_word(&p, &word, ",", 0);
- if (r <= 0)
- return r;
+ if (r < 0)
+ return log_debug_errno(r, "Failed to parse slave interfaces for bridge '%s'", name);
+ if (r == 0)
+ return 0;
r = network_set_bridge(context, word, name);
if (r < 0)
@@ -1028,11 +1038,11 @@ static int parse_cmdline_bond(Context *context, const char *key, const char *val
assert(key);
if (proc_cmdline_value_missing(key, value))
- return -EINVAL;
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Missing value for '%s'", key);
p = strchr(value, ':');
if (!p)
- return -EINVAL;
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid bond value '%s'", value);
name = strndupa_safe(value, p - value);
@@ -1040,7 +1050,7 @@ static int parse_cmdline_bond(Context *context, const char *key, const char *val
if (!netdev) {
r = netdev_new(context, "bond", name, &netdev);
if (r < 0)
- return r;
+ return log_debug_errno(r, "Failed to create bond device for '%s': %m", name);
}
value = p + 1;
@@ -1051,7 +1061,7 @@ static int parse_cmdline_bond(Context *context, const char *key, const char *val
slaves = strndupa_safe(value, p - value);
if (isempty(slaves))
- return -EINVAL;
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Missing slave interfaces for bond '%s'", name);
for (const char *q = slaves; ; ) {
_cleanup_free_ char *word = NULL;
@@ -1060,7 +1070,7 @@ static int parse_cmdline_bond(Context *context, const char *key, const char *val
if (r == 0)
break;
if (r < 0)
- return r;
+ return log_debug_errno(r, "Failed to parse slave interfaces for bond '%s'", name);
r = network_set_bond(context, word, name);
if (r < 0)
@@ -1090,19 +1100,23 @@ static int parse_cmdline_ifname(Context *context, const char *key, const char *v
/* ifname=<interface>:<MAC> */
if (proc_cmdline_value_missing(key, value))
- return -EINVAL;
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Missing value for '%s'", key);
p = strchr(value, ':');
if (!p)
- return -EINVAL;
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid ifname value '%s'", value);
name = strndupa_safe(value, p - value);
r = parse_hw_addr(p + 1, &mac);
if (r < 0)
- return r;
+ return log_debug_errno(r, "Invalid MAC address '%s' for '%s'", p + 1, name);
- return link_new(context, name, &mac, NULL);
+ r = link_new(context, name, &mac, NULL);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to create link for '%s': %m", name);
+
+ return 0;
}
static int parse_cmdline_ifname_policy(Context *context, const char *key, const char *value) {
@@ -1117,7 +1131,7 @@ static int parse_cmdline_ifname_policy(Context *context, const char *key, const
/* net.ifname_policy=policy1[,policy2,...][,<MAC>] */
if (proc_cmdline_value_missing(key, value))
- return -EINVAL;
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Missing value for '%s'", key);
for (const char *q = value; ; ) {
_cleanup_free_ char *word = NULL;
@@ -1127,19 +1141,19 @@ static int parse_cmdline_ifname_policy(Context *context, const char *key, const
if (r == 0)
break;
if (r < 0)
- return r;
+ return log_debug_errno(r, "Failed to parse ifname policy '%s'", value);
p = name_policy_from_string(word);
if (p < 0) {
r = parse_hw_addr(word, &mac);
if (r < 0)
- return r;
+ return log_debug_errno(r, "Invalid MAC address '%s'", word);
if (hw_addr_is_null(&mac))
- return -EINVAL;
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "MAC address is not set");
if (!isempty(q))
- return -EINVAL;
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Unexpected trailing string '%s' in ifname policy '%s'", q, value);
break;
}
@@ -1147,20 +1161,20 @@ static int parse_cmdline_ifname_policy(Context *context, const char *key, const
if (alternative_names_policy_from_string(word) >= 0) {
r = strv_extend(&alt_policies, word);
if (r < 0)
- return r;
+ return log_oom_debug();
}
r = strv_consume(&policies, TAKE_PTR(word));
if (r < 0)
- return r;
+ return log_oom_debug();
}
if (strv_isempty(policies))
- return -EINVAL;
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "No ifname policy specified");
r = link_new(context, NULL, &mac, &link);
if (r < 0)
- return r;
+ return log_debug_errno(r, "Failed to create link: %m");
link->policies = TAKE_PTR(policies);
link->alt_policies = TAKE_PTR(alt_policies);
@@ -1220,12 +1234,12 @@ int context_merge_networks(Context *context) {
r = strv_extend_strv(&network->dns, all->dns, false);
if (r < 0)
- return r;
+ return log_oom_debug();
LIST_FOREACH(routes, route, all->routes) {
r = route_new(network, route->family, route->prefixlen, &route->dest, &route->gateway, NULL);
if (r < 0)
- return r;
+ return log_debug_errno(r, "Failed to copy route: %m");
}
}
@@ -1392,7 +1406,7 @@ int network_format(Network *network, char **ret) {
f = memstream_init(&m);
if (!f)
- return -ENOMEM;
+ return log_oom_debug();
network_dump(network, f);
@@ -1408,7 +1422,7 @@ int netdev_format(NetDev *netdev, char **ret) {
f = memstream_init(&m);
if (!f)
- return -ENOMEM;
+ return log_oom_debug();
netdev_dump(netdev, f);
@@ -1424,7 +1438,7 @@ int link_format(Link *link, char **ret) {
f = memstream_init(&m);
if (!f)
- return -ENOMEM;
+ return log_oom_debug();
link_dump(link, f);
diff --git a/src/network/meson.build b/src/network/meson.build
index 2708b3a5bf..14810ddb75 100644
--- a/src/network/meson.build
+++ b/src/network/meson.build
@@ -147,8 +147,7 @@ if get_option('link-networkd-shared')
networkd_link_with = [libshared]
else
networkd_link_with = [libsystemd_static,
- libshared_static,
- libbasic_gcrypt]
+ libshared_static]
endif
network_includes = [libsystemd_network_includes, include_directories(['.', 'netdev', 'tc'])]
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 3e8aa9e37a..192e9df979 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -1630,9 +1630,9 @@ static int link_check_initialized(Link *link) {
return 0;
}
- r = sd_device_get_is_initialized(device);
+ r = device_is_processed(device);
if (r < 0)
- return log_link_warning_errno(link, r, "Could not determine whether the device is initialized: %m");
+ return log_link_warning_errno(link, r, "Could not determine whether the device is processed by udevd: %m");
if (r == 0) {
/* not yet ready */
log_link_debug(link, "link pending udev initialization...");
@@ -1647,14 +1647,6 @@ static int link_check_initialized(Link *link) {
return 0;
}
- r = device_is_processing(device);
- if (r < 0)
- return log_link_warning_errno(link, r, "Failed to determine whether the device is being processed: %m");
- if (r > 0) {
- log_link_debug(link, "Interface is being processed by udevd, pending initialization.");
- return 0;
- }
-
return link_initialized(link, device);
}
diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c
index 61d591a2af..71e3c30727 100644
--- a/src/network/networkd-ndisc.c
+++ b/src/network/networkd-ndisc.c
@@ -1391,7 +1391,7 @@ static int ndisc_router_process_options(Link *link, sd_ndisc_router *rt) {
}
}
-static int ndisc_drop_outdated(Link *link, usec_t timestamp_usec) {
+static int ndisc_drop_outdated(Link *link, const struct in6_addr *router, usec_t timestamp_usec) {
bool updated = false;
NDiscDNSSL *dnssl;
NDiscRDNSS *rdnss;
@@ -1420,6 +1420,9 @@ static int ndisc_drop_outdated(Link *link, usec_t timestamp_usec) {
if (route->lifetime_usec > timestamp_usec)
continue; /* the route is still valid */
+ if (router && !in6_addr_equal(&route->provider.in6, router))
+ continue;
+
r = route_remove_and_cancel(route, link->manager);
if (r < 0)
RET_GATHER(ret, log_link_warning_errno(link, r, "Failed to remove outdated SLAAC route, ignoring: %m"));
@@ -1432,6 +1435,9 @@ static int ndisc_drop_outdated(Link *link, usec_t timestamp_usec) {
if (address->lifetime_valid_usec > timestamp_usec)
continue; /* the address is still valid */
+ if (router && !in6_addr_equal(&address->provider.in6, router))
+ continue;
+
r = address_remove_and_cancel(address, link);
if (r < 0)
RET_GATHER(ret, log_link_warning_errno(link, r, "Failed to remove outdated SLAAC address, ignoring: %m"));
@@ -1441,6 +1447,9 @@ static int ndisc_drop_outdated(Link *link, usec_t timestamp_usec) {
if (rdnss->lifetime_usec > timestamp_usec)
continue; /* the DNS server is still valid */
+ if (router && !in6_addr_equal(&rdnss->router, router))
+ continue;
+
free(set_remove(link->ndisc_rdnss, rdnss));
updated = true;
}
@@ -1449,6 +1458,9 @@ static int ndisc_drop_outdated(Link *link, usec_t timestamp_usec) {
if (dnssl->lifetime_usec > timestamp_usec)
continue; /* the DNS domain is still valid */
+ if (router && !in6_addr_equal(&dnssl->router, router))
+ continue;
+
free(set_remove(link->ndisc_dnssl, dnssl));
updated = true;
}
@@ -1457,6 +1469,9 @@ static int ndisc_drop_outdated(Link *link, usec_t timestamp_usec) {
if (cp->lifetime_usec > timestamp_usec)
continue; /* the captive portal is still valid */
+ if (router && !in6_addr_equal(&cp->router, router))
+ continue;
+
ndisc_captive_portal_free(set_remove(link->ndisc_captive_portals, cp));
updated = true;
}
@@ -1465,6 +1480,9 @@ static int ndisc_drop_outdated(Link *link, usec_t timestamp_usec) {
if (p64->lifetime_usec > timestamp_usec)
continue; /* the pref64 prefix is still valid */
+ if (router && !in6_addr_equal(&p64->router, router))
+ continue;
+
free(set_remove(link->ndisc_pref64, p64));
/* The pref64 prefix is not exported through the state file, hence it is not necessary to set
* the 'updated' flag. */
@@ -1486,7 +1504,7 @@ static int ndisc_expire_handler(sd_event_source *s, uint64_t usec, void *userdat
assert_se(sd_event_now(link->manager->event, CLOCK_BOOTTIME, &now_usec) >= 0);
- (void) ndisc_drop_outdated(link, now_usec);
+ (void) ndisc_drop_outdated(link, /* router = */ NULL, now_usec);
(void) ndisc_setup_expire(link);
return 0;
}
@@ -1635,7 +1653,7 @@ static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) {
if (r < 0)
return r;
- r = ndisc_drop_outdated(link, timestamp_usec);
+ r = ndisc_drop_outdated(link, /* router = */ NULL, timestamp_usec);
if (r < 0)
return r;
@@ -1679,6 +1697,131 @@ static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) {
return 0;
}
+static int ndisc_neighbor_handle_non_router_message(Link *link, sd_ndisc_neighbor *na) {
+ struct in6_addr address;
+ int r;
+
+ assert(link);
+ assert(na);
+
+ /* Received Neighbor Advertisement message without Router flag. The node might have been a router,
+ * and now it is not. Let's drop all configurations based on RAs sent from the node. */
+
+ r = sd_ndisc_neighbor_get_target_address(na, &address);
+ if (r == -ENODATA)
+ return 0;
+ if (r < 0)
+ return r;
+
+ (void) ndisc_drop_outdated(link, /* router = */ &address, /* timestamp_usec = */ USEC_INFINITY);
+ return 0;
+}
+
+static int ndisc_neighbor_handle_router_message(Link *link, sd_ndisc_neighbor *na) {
+ struct in6_addr current_address, original_address;
+ int r;
+
+ assert(link);
+ assert(link->manager);
+ assert(na);
+
+ /* Received Neighbor Advertisement message with Router flag. If the router address is changed, update
+ * the provider field of configurations. */
+
+ r = sd_ndisc_neighbor_get_sender_address(na, &current_address);
+ if (r == -ENODATA)
+ return 0;
+ if (r < 0)
+ return r;
+
+ r = sd_ndisc_neighbor_get_target_address(na, &original_address);
+ if (r == -ENODATA)
+ return 0;
+ if (r < 0)
+ return r;
+
+ if (in6_addr_equal(&current_address, &original_address))
+ return 0; /* the router address is not changed */
+
+ Route *route;
+ SET_FOREACH(route, link->manager->routes) {
+ if (route->source != NETWORK_CONFIG_SOURCE_NDISC)
+ continue;
+
+ if (route->nexthop.ifindex != link->ifindex)
+ continue;
+
+ if (!in6_addr_equal(&route->provider.in6, &original_address))
+ continue;
+
+ route->provider.in6 = current_address;
+ }
+
+ Address *address;
+ SET_FOREACH(address, link->addresses) {
+ if (address->source != NETWORK_CONFIG_SOURCE_NDISC)
+ continue;
+
+ if (!in6_addr_equal(&address->provider.in6, &original_address))
+ continue;
+
+ address->provider.in6 = current_address;
+ }
+
+ NDiscRDNSS *rdnss;
+ SET_FOREACH(rdnss, link->ndisc_rdnss) {
+ if (!in6_addr_equal(&rdnss->router, &original_address))
+ continue;
+
+ rdnss->router = current_address;
+ }
+
+ NDiscDNSSL *dnssl;
+ SET_FOREACH(dnssl, link->ndisc_dnssl) {
+ if (!in6_addr_equal(&dnssl->router, &original_address))
+ continue;
+
+ dnssl->router = current_address;
+ }
+
+ NDiscCaptivePortal *cp;
+ SET_FOREACH(cp, link->ndisc_captive_portals) {
+ if (!in6_addr_equal(&cp->router, &original_address))
+ continue;
+
+ cp->router = current_address;
+ }
+
+ NDiscPREF64 *p64;
+ SET_FOREACH(p64, link->ndisc_pref64) {
+ if (!in6_addr_equal(&p64->router, &original_address))
+ continue;
+
+ p64->router = current_address;
+ }
+
+ return 0;
+}
+
+static int ndisc_neighbor_handler(Link *link, sd_ndisc_neighbor *na) {
+ int r;
+
+ assert(link);
+ assert(na);
+
+ r = sd_ndisc_neighbor_is_router(na);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ r = ndisc_neighbor_handle_non_router_message(link, na);
+ else
+ r = ndisc_neighbor_handle_router_message(link, na);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
static void ndisc_handler(sd_ndisc *nd, sd_ndisc_event_t event, void *message, void *userdata) {
Link *link = ASSERT_PTR(userdata);
int r;
@@ -1696,6 +1839,14 @@ static void ndisc_handler(sd_ndisc *nd, sd_ndisc_event_t event, void *message, v
}
break;
+ case SD_NDISC_EVENT_NEIGHBOR:
+ r = ndisc_neighbor_handler(link, ASSERT_PTR(message));
+ if (r < 0 && r != -EBADMSG) {
+ link_enter_failed(link);
+ return;
+ }
+ break;
+
case SD_NDISC_EVENT_TIMEOUT:
log_link_debug(link, "NDisc handler get timeout event");
if (link->ndisc_messages == 0) {
@@ -1825,7 +1976,7 @@ void ndisc_flush(Link *link) {
assert(link);
/* Remove all addresses, routes, RDNSS, DNSSL, and Captive Portal entries, without exception. */
- (void) ndisc_drop_outdated(link, /* timestamp_usec = */ USEC_INFINITY);
+ (void) ndisc_drop_outdated(link, /* router = */ NULL, /* timestamp_usec = */ USEC_INFINITY);
link->ndisc_rdnss = set_free(link->ndisc_rdnss);
link->ndisc_dnssl = set_free(link->ndisc_dnssl);
diff --git a/src/network/networkd-state-file.c b/src/network/networkd-state-file.c
index 117db0af6c..86746afc41 100644
--- a/src/network/networkd-state-file.c
+++ b/src/network/networkd-state-file.c
@@ -127,7 +127,7 @@ static int link_put_dns(Link *link, OrderedSet **s) {
NDiscRDNSS *a;
SET_FOREACH(a, link->ndisc_rdnss) {
- r = ordered_set_put_in6_addrv(s, &a->router, 1);
+ r = ordered_set_put_in6_addrv(s, &a->address, 1);
if (r < 0)
return r;
}
diff --git a/src/nspawn/nspawn-network.c b/src/nspawn/nspawn-network.c
index 94e751cf65..e89f087aea 100644
--- a/src/nspawn/nspawn-network.c
+++ b/src/nspawn/nspawn-network.c
@@ -487,7 +487,7 @@ static int test_network_interface_initialized(const char *name) {
if (r < 0)
return log_error_errno(r, "Failed to get device %s: %m", name);
- r = sd_device_get_is_initialized(d);
+ r = device_is_processed(d);
if (r < 0)
return log_error_errno(r, "Failed to determine whether interface %s is initialized: %m", name);
if (r == 0)
diff --git a/src/partition/meson.build b/src/partition/meson.build
index 78cde2ff52..52e1368116 100644
--- a/src/partition/meson.build
+++ b/src/partition/meson.build
@@ -33,7 +33,6 @@ executables += [
'c_args' : '-DSTANDALONE',
'link_with' : [
libbasic,
- libbasic_gcrypt,
libshared_fdisk,
libshared_static,
libsystemd_static,
diff --git a/src/partition/repart.c b/src/partition/repart.c
index ddb7fcb046..fa556874df 100644
--- a/src/partition/repart.c
+++ b/src/partition/repart.c
@@ -300,6 +300,7 @@ typedef struct Partition {
char **exclude_files_target;
char **make_directories;
char **subvolumes;
+ char *default_subvolume;
EncryptMode encrypt;
VerityMode verity;
char *verity_match_key;
@@ -1668,6 +1669,41 @@ static int config_parse_make_dirs(
}
}
+static int config_parse_default_subvolume(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ char **subvol = ASSERT_PTR(data);
+ _cleanup_free_ char *p = NULL;
+ int r;
+
+ if (isempty(rvalue)) {
+ *subvol = mfree(*subvol);
+ return 0;
+ }
+
+ r = specifier_printf(rvalue, PATH_MAX-1, system_and_tmp_specifier_table, arg_root, NULL, &p);
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Failed to expand specifiers in DefaultSubvolume= parameter, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ r = path_simplify_and_warn(p, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
+ if (r < 0)
+ return 0;
+
+ return free_and_replace(*subvol, p);
+}
+
static DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT(config_parse_encrypt, encrypt_mode, EncryptMode, ENCRYPT_OFF, "Invalid encryption mode");
static int config_parse_gpt_flags(
@@ -1861,37 +1897,38 @@ static DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT(config_parse_minimize, minimize_mod
static int partition_read_definition(Partition *p, const char *path, const char *const *conf_file_dirs) {
ConfigTableItem table[] = {
- { "Partition", "Type", config_parse_type, 0, &p->type },
- { "Partition", "Label", config_parse_label, 0, &p->new_label },
- { "Partition", "UUID", config_parse_uuid, 0, p },
- { "Partition", "Priority", config_parse_int32, 0, &p->priority },
- { "Partition", "Weight", config_parse_weight, 0, &p->weight },
- { "Partition", "PaddingWeight", config_parse_weight, 0, &p->padding_weight },
- { "Partition", "SizeMinBytes", config_parse_size4096, -1, &p->size_min },
- { "Partition", "SizeMaxBytes", config_parse_size4096, 1, &p->size_max },
- { "Partition", "PaddingMinBytes", config_parse_size4096, -1, &p->padding_min },
- { "Partition", "PaddingMaxBytes", config_parse_size4096, 1, &p->padding_max },
- { "Partition", "FactoryReset", config_parse_bool, 0, &p->factory_reset },
- { "Partition", "CopyBlocks", config_parse_copy_blocks, 0, p },
- { "Partition", "Format", config_parse_fstype, 0, &p->format },
- { "Partition", "CopyFiles", config_parse_copy_files, 0, &p->copy_files },
- { "Partition", "ExcludeFiles", config_parse_exclude_files, 0, &p->exclude_files_source },
- { "Partition", "ExcludeFilesTarget", config_parse_exclude_files, 0, &p->exclude_files_target },
- { "Partition", "MakeDirectories", config_parse_make_dirs, 0, &p->make_directories },
- { "Partition", "Encrypt", config_parse_encrypt, 0, &p->encrypt },
- { "Partition", "Verity", config_parse_verity, 0, &p->verity },
- { "Partition", "VerityMatchKey", config_parse_string, 0, &p->verity_match_key },
- { "Partition", "Flags", config_parse_gpt_flags, 0, &p->gpt_flags },
- { "Partition", "ReadOnly", config_parse_tristate, 0, &p->read_only },
- { "Partition", "NoAuto", config_parse_tristate, 0, &p->no_auto },
- { "Partition", "GrowFileSystem", config_parse_tristate, 0, &p->growfs },
- { "Partition", "SplitName", config_parse_string, 0, &p->split_name_format },
- { "Partition", "Minimize", config_parse_minimize, 0, &p->minimize },
- { "Partition", "Subvolumes", config_parse_make_dirs, 0, &p->subvolumes },
- { "Partition", "VerityDataBlockSizeBytes", config_parse_block_size, 0, &p->verity_data_block_size },
- { "Partition", "VerityHashBlockSizeBytes", config_parse_block_size, 0, &p->verity_hash_block_size },
- { "Partition", "MountPoint", config_parse_mountpoint, 0, p },
- { "Partition", "EncryptedVolume", config_parse_encrypted_volume, 0, p },
+ { "Partition", "Type", config_parse_type, 0, &p->type },
+ { "Partition", "Label", config_parse_label, 0, &p->new_label },
+ { "Partition", "UUID", config_parse_uuid, 0, p },
+ { "Partition", "Priority", config_parse_int32, 0, &p->priority },
+ { "Partition", "Weight", config_parse_weight, 0, &p->weight },
+ { "Partition", "PaddingWeight", config_parse_weight, 0, &p->padding_weight },
+ { "Partition", "SizeMinBytes", config_parse_size4096, -1, &p->size_min },
+ { "Partition", "SizeMaxBytes", config_parse_size4096, 1, &p->size_max },
+ { "Partition", "PaddingMinBytes", config_parse_size4096, -1, &p->padding_min },
+ { "Partition", "PaddingMaxBytes", config_parse_size4096, 1, &p->padding_max },
+ { "Partition", "FactoryReset", config_parse_bool, 0, &p->factory_reset },
+ { "Partition", "CopyBlocks", config_parse_copy_blocks, 0, p },
+ { "Partition", "Format", config_parse_fstype, 0, &p->format },
+ { "Partition", "CopyFiles", config_parse_copy_files, 0, &p->copy_files },
+ { "Partition", "ExcludeFiles", config_parse_exclude_files, 0, &p->exclude_files_source },
+ { "Partition", "ExcludeFilesTarget", config_parse_exclude_files, 0, &p->exclude_files_target },
+ { "Partition", "MakeDirectories", config_parse_make_dirs, 0, &p->make_directories },
+ { "Partition", "Encrypt", config_parse_encrypt, 0, &p->encrypt },
+ { "Partition", "Verity", config_parse_verity, 0, &p->verity },
+ { "Partition", "VerityMatchKey", config_parse_string, 0, &p->verity_match_key },
+ { "Partition", "Flags", config_parse_gpt_flags, 0, &p->gpt_flags },
+ { "Partition", "ReadOnly", config_parse_tristate, 0, &p->read_only },
+ { "Partition", "NoAuto", config_parse_tristate, 0, &p->no_auto },
+ { "Partition", "GrowFileSystem", config_parse_tristate, 0, &p->growfs },
+ { "Partition", "SplitName", config_parse_string, 0, &p->split_name_format },
+ { "Partition", "Minimize", config_parse_minimize, 0, &p->minimize },
+ { "Partition", "Subvolumes", config_parse_make_dirs, 0, &p->subvolumes },
+ { "Partition", "DefaultSubvolume", config_parse_default_subvolume, 0, &p->default_subvolume },
+ { "Partition", "VerityDataBlockSizeBytes", config_parse_block_size, 0, &p->verity_data_block_size },
+ { "Partition", "VerityHashBlockSizeBytes", config_parse_block_size, 0, &p->verity_hash_block_size },
+ { "Partition", "MountPoint", config_parse_mountpoint, 0, p },
+ { "Partition", "EncryptedVolume", config_parse_encrypted_volume, 0, p },
{}
};
int r;
@@ -2018,6 +2055,14 @@ static int partition_read_definition(Partition *p, const char *path, const char
return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EOPNOTSUPP),
"Subvolumes= cannot be used with --offline=yes");
+ if (p->default_subvolume && arg_offline > 0)
+ return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "DefaultSubvolume= cannot be used with --offline=yes");
+
+ if (p->default_subvolume && !path_strv_contains(p->subvolumes, p->default_subvolume))
+ return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL),
+ "DefaultSubvolume= must be one of the paths in Subvolumes=");
+
/* Verity partitions are read only, let's imply the RO flag hence, unless explicitly configured otherwise. */
if ((IN_SET(p->type.designator,
PARTITION_ROOT_VERITY,
@@ -3736,6 +3781,11 @@ static int prepare_temporary_file(PartitionTarget *t, uint64_t size) {
return 0;
}
+static bool loop_device_error_is_fatal(const Partition *p, int r) {
+ assert(p);
+ return arg_offline == 0 || (r != -ENOENT && !ERRNO_IS_PRIVILEGE(r)) || !strv_isempty(p->subvolumes) || p->default_subvolume;
+}
+
static int partition_target_prepare(
Context *context,
Partition *p,
@@ -3775,7 +3825,7 @@ static int partition_target_prepare(
if (arg_offline <= 0) {
r = loop_device_make(whole_fd, O_RDWR, p->offset, size, context->sector_size, 0, LOCK_EX, &d);
- if (r < 0 && (arg_offline == 0 || (r != -ENOENT && !ERRNO_IS_PRIVILEGE(r)) || !strv_isempty(p->subvolumes)))
+ if (r < 0 && loop_device_error_is_fatal(p, r))
return log_error_errno(r, "Failed to make loopback device of future partition %" PRIu64 ": %m", p->partno);
if (r >= 0) {
t->loop = TAKE_PTR(d);
@@ -4878,6 +4928,27 @@ static int do_make_directories(Partition *p, const char *root) {
return 0;
}
+static int set_default_subvolume(Partition *p, const char *root) {
+ _cleanup_free_ char *path = NULL;
+ int r;
+
+ assert(p);
+ assert(root);
+
+ if (!p->default_subvolume)
+ return 0;
+
+ path = path_join(root, p->default_subvolume);
+ if (!path)
+ return log_oom();
+
+ r = btrfs_subvol_make_default(path);
+ if (r < 0)
+ return log_error_errno(r, "Failed to make '%s' the default subvolume: %m", p->default_subvolume);
+
+ return 0;
+}
+
static bool partition_needs_populate(Partition *p) {
assert(p);
return !strv_isempty(p->copy_files) || !strv_isempty(p->make_directories);
@@ -4952,6 +5023,9 @@ static int partition_populate_filesystem(Context *context, Partition *p, const c
if (do_make_directories(p, fs) < 0)
_exit(EXIT_FAILURE);
+ if (set_default_subvolume(p, fs) < 0)
+ _exit(EXIT_FAILURE);
+
r = syncfs_path(AT_FDCWD, fs);
if (r < 0) {
log_error_errno(r, "Failed to synchronize written files: %m");
@@ -6547,7 +6621,7 @@ static int context_minimize(Context *context) {
if (arg_offline <= 0) {
r = loop_device_make(fd, O_RDWR, 0, UINT64_MAX, context->sector_size, 0, LOCK_EX, &d);
- if (r < 0 && (arg_offline == 0 || (r != -ENOENT && !ERRNO_IS_PRIVILEGE(r)) || !strv_isempty(p->subvolumes)))
+ if (r < 0 && loop_device_error_is_fatal(p, r))
return log_error_errno(r, "Failed to make loopback device of %s: %m", temp);
}
diff --git a/src/resolve/meson.build b/src/resolve/meson.build
index d855ded91a..d336b2c07b 100644
--- a/src/resolve/meson.build
+++ b/src/resolve/meson.build
@@ -118,7 +118,6 @@ if conf.get('ENABLE_DNS_OVER_TLS') == 1
endif
link_with = [
- libbasic_gcrypt,
libshared,
libsystemd_resolve_core,
]
diff --git a/src/resolve/resolved-dns-dnssec.c b/src/resolve/resolved-dns-dnssec.c
index a373b610b0..233418affc 100644
--- a/src/resolve/resolved-dns-dnssec.c
+++ b/src/resolve/resolved-dns-dnssec.c
@@ -890,8 +890,11 @@ static int dnssec_rrset_verify_sig(
_cleanup_(gcry_md_closep) gcry_md_hd_t md = NULL;
void *hash;
size_t hash_size;
+ int r;
- initialize_libgcrypt(false);
+ r = initialize_libgcrypt(false);
+ if (r < 0)
+ return r;
#endif
switch (rrsig->rrsig.algorithm) {
@@ -1334,6 +1337,7 @@ static hash_md_t digest_to_hash_md(uint8_t algorithm) {
int dnssec_verify_dnskey_by_ds(DnsResourceRecord *dnskey, DnsResourceRecord *ds, bool mask_revoke) {
uint8_t wire_format[DNS_WIRE_FORMAT_HOSTNAME_MAX];
+ size_t encoded_length;
int r;
assert(dnskey);
@@ -1360,6 +1364,7 @@ int dnssec_verify_dnskey_by_ds(DnsResourceRecord *dnskey, DnsResourceRecord *ds,
r = dns_name_to_wire_format(dns_resource_key_name(dnskey->key), wire_format, sizeof wire_format, true);
if (r < 0)
return r;
+ encoded_length = r;
hash_md_t md_algorithm = digest_to_hash_md(ds->ds.digest_type);
@@ -1383,7 +1388,7 @@ int dnssec_verify_dnskey_by_ds(DnsResourceRecord *dnskey, DnsResourceRecord *ds,
if (EVP_DigestInit_ex(ctx, md_algorithm, NULL) <= 0)
return -EIO;
- if (EVP_DigestUpdate(ctx, wire_format, r) <= 0)
+ if (EVP_DigestUpdate(ctx, wire_format, encoded_length) <= 0)
return -EIO;
if (mask_revoke)
@@ -1407,7 +1412,9 @@ int dnssec_verify_dnskey_by_ds(DnsResourceRecord *dnskey, DnsResourceRecord *ds,
if (md_algorithm < 0)
return -EOPNOTSUPP;
- initialize_libgcrypt(false);
+ r = initialize_libgcrypt(false);
+ if (r < 0)
+ return r;
_cleanup_(gcry_md_closep) gcry_md_hd_t md = NULL;
@@ -1421,7 +1428,7 @@ int dnssec_verify_dnskey_by_ds(DnsResourceRecord *dnskey, DnsResourceRecord *ds,
if (gcry_err_code(err) != GPG_ERR_NO_ERROR || !md)
return -EIO;
- gcry_md_write(md, wire_format, r);
+ gcry_md_write(md, wire_format, encoded_length);
if (mask_revoke)
md_add_uint16(md, dnskey->dnskey.flags & ~DNSKEY_FLAG_REVOKE);
else
@@ -1552,8 +1559,11 @@ int dnssec_nsec3_hash(DnsResourceRecord *nsec3, const char *name, void *ret) {
if (algorithm < 0)
return algorithm;
- initialize_libgcrypt(false);
+ r = initialize_libgcrypt(false);
+ if (r < 0)
+ return r;
+ size_t encoded_length;
unsigned hash_size = gcry_md_get_algo_dlen(algorithm);
assert(hash_size > 0);
@@ -1563,13 +1573,14 @@ int dnssec_nsec3_hash(DnsResourceRecord *nsec3, const char *name, void *ret) {
r = dns_name_to_wire_format(name, wire_format, sizeof(wire_format), true);
if (r < 0)
return r;
+ encoded_length = r;
_cleanup_(gcry_md_closep) gcry_md_hd_t md = NULL;
gcry_error_t err = gcry_md_open(&md, algorithm, 0);
if (gcry_err_code(err) != GPG_ERR_NO_ERROR || !md)
return -EIO;
- gcry_md_write(md, wire_format, r);
+ gcry_md_write(md, wire_format, encoded_length);
gcry_md_write(md, nsec3->nsec3.salt, nsec3->nsec3.salt_size);
void *result = gcry_md_read(md, 0);
diff --git a/src/resolve/resolved-varlink.c b/src/resolve/resolved-varlink.c
index 6b835904be..25f85d8233 100644
--- a/src/resolve/resolved-varlink.c
+++ b/src/resolve/resolved-varlink.c
@@ -1238,7 +1238,7 @@ static int vl_method_subscribe_query_results(Varlink *link, JsonVariant *paramet
/* if the client didn't set the more flag, it is using us incorrectly */
if (!FLAGS_SET(flags, VARLINK_METHOD_MORE))
- return varlink_error_invalid_parameter(link, NULL);
+ return varlink_error(link, VARLINK_ERROR_EXPECTED_MORE, NULL);
if (json_variant_elements(parameters) > 0)
return varlink_error_invalid_parameter(link, parameters);
diff --git a/src/shared/bpf-dlopen.c b/src/shared/bpf-dlopen.c
index 70b1ffbf99..6d59001b2c 100644
--- a/src/shared/bpf-dlopen.c
+++ b/src/shared/bpf-dlopen.c
@@ -76,18 +76,23 @@ int dlopen_bpf(void) {
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"neither libbpf.so.1 nor libbpf.so.0 are installed: %s", dlerror());
+ log_debug("Loaded 'libbpf.so.0' via dlopen()");
+
/* symbols deprecated in 1.0 we use as compat */
r = dlsym_many_or_warn(
dl, LOG_DEBUG,
#if MODERN_LIBBPF
/* Don't exist anymore in new libbpf, hence cannot type check them */
DLSYM_ARG_FORCE(bpf_create_map),
- DLSYM_ARG_FORCE(bpf_probe_prog_type));
+ DLSYM_ARG_FORCE(bpf_probe_prog_type)
#else
DLSYM_ARG(bpf_create_map),
- DLSYM_ARG(bpf_probe_prog_type));
+ DLSYM_ARG(bpf_probe_prog_type)
#endif
+ );
} else {
+ log_debug("Loaded 'libbpf.so.1' via dlopen()");
+
/* symbols available from 0.7.0 */
r = dlsym_many_or_warn(
dl, LOG_DEBUG,
@@ -101,6 +106,8 @@ int dlopen_bpf(void) {
#endif
);
}
+ if (r < 0)
+ return r;
r = dlsym_many_or_warn(
dl, LOG_DEBUG,
diff --git a/src/shared/btrfs-util.c b/src/shared/btrfs-util.c
index 2ed6bf24a2..5db88221f3 100644
--- a/src/shared/btrfs-util.c
+++ b/src/shared/btrfs-util.c
@@ -1785,6 +1785,24 @@ int btrfs_subvol_auto_qgroup(const char *path, uint64_t subvol_id, bool create_i
return btrfs_subvol_auto_qgroup_fd(fd, subvol_id, create_intermediary_qgroup);
}
+int btrfs_subvol_make_default(const char *path) {
+ _cleanup_close_ int fd = -EBADF;
+ uint64_t id;
+ int r;
+
+ assert(path);
+
+ fd = open(path, O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
+ if (fd < 0)
+ return -errno;
+
+ r = btrfs_subvol_get_id_fd(fd, &id);
+ if (r < 0)
+ return r;
+
+ return RET_NERRNO(ioctl(fd, BTRFS_IOC_DEFAULT_SUBVOL, &id));
+}
+
int btrfs_subvol_get_parent(int fd, uint64_t subvol_id, uint64_t *ret) {
struct btrfs_ioctl_search_args args = {
diff --git a/src/shared/btrfs-util.h b/src/shared/btrfs-util.h
index cd80903190..6108a264c0 100644
--- a/src/shared/btrfs-util.h
+++ b/src/shared/btrfs-util.h
@@ -108,6 +108,8 @@ int btrfs_subvol_set_subtree_quota_limit_fd(int fd, uint64_t subvol_id, uint64_t
int btrfs_subvol_auto_qgroup_fd(int fd, uint64_t subvol_id, bool new_qgroup);
int btrfs_subvol_auto_qgroup(const char *path, uint64_t subvol_id, bool create_intermediary_qgroup);
+int btrfs_subvol_make_default(const char *path);
+
int btrfs_qgroupid_make(uint64_t level, uint64_t id, uint64_t *ret);
int btrfs_qgroupid_split(uint64_t qgroupid, uint64_t *level, uint64_t *id);
diff --git a/src/shared/hibernate-util.c b/src/shared/hibernate-util.c
index 3547476c85..061b341075 100644
--- a/src/shared/hibernate-util.c
+++ b/src/shared/hibernate-util.c
@@ -513,13 +513,17 @@ int write_resume_config(dev_t devno, uint64_t offset, const char *device) {
return 0;
}
-void clear_efi_hibernate_location_and_warn(void) {
+int clear_efi_hibernate_location_and_warn(void) {
int r;
if (!is_efi_boot())
- return;
+ return 0;
r = efi_set_variable(EFI_SYSTEMD_VARIABLE(HibernateLocation), NULL, 0);
+ if (r == -ENOENT)
+ return 0;
if (r < 0)
- log_warning_errno(r, "Failed to clear EFI variable HibernateLocation, ignoring: %m");
+ return log_warning_errno(r, "Failed to clear HibernateLocation EFI variable: %m");
+
+ return 1;
}
diff --git a/src/shared/hibernate-util.h b/src/shared/hibernate-util.h
index 1064d2b4dd..394d0b4176 100644
--- a/src/shared/hibernate-util.h
+++ b/src/shared/hibernate-util.h
@@ -22,7 +22,7 @@ int hibernation_is_safe(void);
int write_resume_config(dev_t devno, uint64_t offset, const char *device);
-void clear_efi_hibernate_location_and_warn(void);
+int clear_efi_hibernate_location_and_warn(void);
/* Only for test-fiemap */
int read_fiemap(int fd, struct fiemap **ret);
diff --git a/src/shared/idn-util.c b/src/shared/idn-util.c
index 70f039f825..6b26f2064a 100644
--- a/src/shared/idn-util.c
+++ b/src/shared/idn-util.c
@@ -50,7 +50,10 @@ int dlopen_idn(void) {
if (!dl)
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"libidn support is not installed: %s", dlerror());
- }
+ log_debug("Loaded 'libidn.so.11' via dlopen()");
+ } else
+ log_debug("Loaded 'libidn.so.12' via dlopen()");
+
r = dlsym_many_or_warn(
dl,
diff --git a/src/shared/meson.build b/src/shared/meson.build
index 11f2b5ade9..4c9b45434e 100644
--- a/src/shared/meson.build
+++ b/src/shared/meson.build
@@ -358,7 +358,6 @@ libshared = shared_library(
link_depends : libshared_sym_path,
link_whole : [libshared_static,
libbasic,
- libbasic_gcrypt,
libsystemd_static],
dependencies : [libshared_deps,
userspace],
diff --git a/src/shared/pkcs11-util.c b/src/shared/pkcs11-util.c
index e6feba44bd..8727fe2484 100644
--- a/src/shared/pkcs11-util.c
+++ b/src/shared/pkcs11-util.c
@@ -1711,7 +1711,7 @@ static int pkcs11_acquire_public_key_callback(
switch (attributes[i].type) {
case CKA_CLASS: {
CK_OBJECT_CLASS requested_class = *((CK_OBJECT_CLASS*) attributes[i].pValue);
- if (requested_class != CKO_PUBLIC_KEY && requested_class != CKO_CERTIFICATE)
+ if (!IN_SET(requested_class, CKO_PUBLIC_KEY, CKO_CERTIFICATE))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Selected PKCS#11 object is not a public key or certificate, refusing.");
break;
@@ -1743,7 +1743,7 @@ static int pkcs11_acquire_public_key_callback(
candidate_attributes[0].ulValueLen = sizeof(class);
candidate_attributes[1].ulValueLen = sizeof(type);
rv = m->C_GetAttributeValue(session, candidate, candidate_attributes, ELEMENTSOF(candidate_attributes));
- if (rv != CKR_OK && rv != CKR_ATTRIBUTE_TYPE_INVALID)
+ if (!IN_SET(rv, CKR_OK, CKR_ATTRIBUTE_TYPE_INVALID))
return log_error_errno(SYNTHETIC_ERRNO(EIO),
"Failed to get attributes of a selected candidate: %s", sym_p11_kit_strerror(rv));
diff --git a/src/shared/ptyfwd.c b/src/shared/ptyfwd.c
index bdbd79087c..7bd8dd6d89 100644
--- a/src/shared/ptyfwd.c
+++ b/src/shared/ptyfwd.c
@@ -478,7 +478,7 @@ static int pty_forward_ansi_process(PTYForward *f, size_t offset) {
* since we cannot lookahead to see if the Esc is followed by a \
* we cut a corner here and assume it will be \. */
- if (c == '\x07' || c == '\x1b') {
+ if (IN_SET(c, '\x07', '\x1b')) {
r = insert_window_title_fix(f, i+1);
if (r < 0)
return r;
diff --git a/src/shared/serialize.c b/src/shared/serialize.c
index 483cbc7419..d1f41ce4c8 100644
--- a/src/shared/serialize.c
+++ b/src/shared/serialize.c
@@ -180,7 +180,7 @@ int serialize_strv(FILE *f, const char *key, char **l) {
}
int serialize_pidref(FILE *f, FDSet *fds, const char *key, PidRef *pidref) {
- int copy;
+ int r;
assert(f);
assert(fds);
@@ -188,17 +188,21 @@ int serialize_pidref(FILE *f, FDSet *fds, const char *key, PidRef *pidref) {
if (!pidref_is_set(pidref))
return 0;
- /* If we have a pidfd we serialize the fd and encode the fd number prefixed by "@" in the
- * serialization. Otherwise we serialize the numeric PID as it is. */
+ /* We always serialize the pid, to keep downgrades mostly working (older versions will deserialize
+ * the pid and silently fail to deserialize the pidfd). If we also have a pidfd, we serialize it
+ * first and encode the fd number prefixed by "@" in the serialization. */
- if (pidref->fd < 0)
- return serialize_item_format(f, key, PID_FMT, pidref->pid);
+ if (pidref->fd >= 0) {
+ int copy = fdset_put_dup(fds, pidref->fd);
+ if (copy < 0)
+ return log_error_errno(copy, "Failed to add file descriptor to serialization set: %m");
- copy = fdset_put_dup(fds, pidref->fd);
- if (copy < 0)
- return log_error_errno(copy, "Failed to add file descriptor to serialization set: %m");
+ r = serialize_item_format(f, key, "@%i", copy);
+ if (r < 0)
+ return log_error_errno(r, "Failed to serialize PID file descriptor: %m");
+ }
- return serialize_item_format(f, key, "@%i", copy);
+ return serialize_item_format(f, key, PID_FMT, pidref->pid);
}
int serialize_ratelimit(FILE *f, const char *key, const RateLimit *rl) {
diff --git a/src/shared/sleep-config.c b/src/shared/sleep-config.c
index c96f8485dd..4a90ad67bd 100644
--- a/src/shared/sleep-config.c
+++ b/src/shared/sleep-config.c
@@ -54,6 +54,8 @@ SleepConfig* sleep_config_free(SleepConfig *sc) {
strv_free(sc->modes[i]);
}
+ strv_free(sc->mem_modes);
+
return mfree(sc);
}
@@ -69,8 +71,8 @@ static int config_parse_sleep_mode(
void *data,
void *userdata) {
- _cleanup_strv_free_ char **modes = NULL;
char ***sv = ASSERT_PTR(data);
+ _cleanup_strv_free_ char **modes = NULL;
int r;
assert(filename);
@@ -87,7 +89,7 @@ static int config_parse_sleep_mode(
return log_oom();
}
- return free_and_replace(*sv, modes);
+ return strv_free_and_replace(*sv, modes);
}
static void sleep_config_validate_state_and_mode(SleepConfig *sc) {
@@ -140,6 +142,8 @@ int parse_sleep_config(SleepConfig **ret) {
{ "Sleep", "HybridSleepState", config_parse_warn_compat, DISABLED_LEGACY, NULL },
{ "Sleep", "HybridSleepMode", config_parse_warn_compat, DISABLED_LEGACY, NULL },
+ { "Sleep", "SleepMemMode", config_parse_sleep_mode, 0, &sc->mem_modes },
+
{ "Sleep", "HibernateDelaySec", config_parse_sec, 0, &sc->hibernate_delay_usec },
{ "Sleep", "SuspendEstimationSec", config_parse_sec, 0, &sc->suspend_estimation_usec },
{}
@@ -183,7 +187,7 @@ int parse_sleep_config(SleepConfig **ret) {
return 0;
}
-int sleep_state_supported(char **states) {
+int sleep_state_supported(char * const *states) {
_cleanup_free_ char *supported_sysfs = NULL;
const char *found;
int r;
@@ -213,22 +217,24 @@ int sleep_state_supported(char **states) {
return false;
}
-int sleep_mode_supported(char **modes) {
+int sleep_mode_supported(const char *path, char * const *modes) {
_cleanup_free_ char *supported_sysfs = NULL;
int r;
+ assert(path);
+
/* Unlike state, kernel has its own default choice if not configured */
if (strv_isempty(modes)) {
- log_debug("No sleep mode configured, using kernel default.");
+ log_debug("No sleep mode configured, using kernel default for %s.", path);
return true;
}
- if (access("/sys/power/disk", W_OK) < 0)
- return log_debug_errno(errno, "/sys/power/disk is not writable: %m");
+ if (access(path, W_OK) < 0)
+ return log_debug_errno(errno, "%s is not writable: %m", path);
- r = read_one_line_file("/sys/power/disk", &supported_sysfs);
+ r = read_one_line_file(path, &supported_sysfs);
if (r < 0)
- return log_debug_errno(r, "Failed to read /sys/power/disk: %m");
+ return log_debug_errno(r, "Failed to read %s: %m", path);
for (const char *p = supported_sysfs;;) {
_cleanup_free_ char *word = NULL;
@@ -237,7 +243,7 @@ int sleep_mode_supported(char **modes) {
r = extract_first_word(&p, &word, NULL, 0);
if (r < 0)
- return log_debug_errno(r, "Failed to parse /sys/power/disk: %m");
+ return log_debug_errno(r, "Failed to parse %s: %m", path);
if (r == 0)
break;
@@ -250,14 +256,15 @@ int sleep_mode_supported(char **modes) {
}
if (strv_contains(modes, mode)) {
- log_debug("Disk sleep mode '%s' is supported by kernel.", mode);
+ log_debug("Sleep mode '%s' is supported by kernel (%s).", mode, path);
return true;
}
}
if (DEBUG_LOGGING) {
_cleanup_free_ char *joined = strv_join(modes, " ");
- log_debug("None of the configured hibernation power modes are supported by kernel: %s", strnull(joined));
+ log_debug("None of the configured modes are supported by kernel (%s): %s",
+ path, strnull(joined));
}
return false;
}
@@ -341,8 +348,18 @@ static int sleep_supported_internal(
return false;
}
- if (sleep_operation_is_hibernation(operation)) {
- r = sleep_mode_supported(sleep_config->modes[operation]);
+ if (SLEEP_NEEDS_MEM_SLEEP(sleep_config, operation)) {
+ r = sleep_mode_supported("/sys/power/mem_sleep", sleep_config->mem_modes);
+ if (r < 0)
+ return r;
+ if (r == 0) {
+ *ret_support = SLEEP_STATE_OR_MODE_NOT_SUPPORTED;
+ return false;
+ }
+ }
+
+ if (SLEEP_OPERATION_IS_HIBERNATION(operation)) {
+ r = sleep_mode_supported("/sys/power/disk", sleep_config->modes[operation]);
if (r < 0)
return r;
if (r == 0) {
diff --git a/src/shared/sleep-config.h b/src/shared/sleep-config.h
index bc5aeb91bd..75d9c4a622 100644
--- a/src/shared/sleep-config.h
+++ b/src/shared/sleep-config.h
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
+#include "strv.h"
#include "time-util.h"
typedef enum SleepOperation {
@@ -20,7 +21,7 @@ typedef enum SleepOperation {
const char* sleep_operation_to_string(SleepOperation s) _const_;
SleepOperation sleep_operation_from_string(const char *s) _pure_;
-static inline bool sleep_operation_is_hibernation(SleepOperation operation) {
+static inline bool SLEEP_OPERATION_IS_HIBERNATION(SleepOperation operation) {
return IN_SET(operation, SLEEP_HIBERNATE, SLEEP_HYBRID_SLEEP);
}
@@ -28,7 +29,8 @@ typedef struct SleepConfig {
bool allow[_SLEEP_OPERATION_MAX];
char **states[_SLEEP_OPERATION_CONFIG_MAX];
- char **modes[_SLEEP_OPERATION_CONFIG_MAX]; /* Power mode after writing hibernation image */
+ char **modes[_SLEEP_OPERATION_CONFIG_MAX]; /* Power mode after writing hibernation image (/sys/power/disk) */
+ char **mem_modes; /* /sys/power/mem_sleep */
usec_t hibernate_delay_usec;
usec_t suspend_estimation_usec;
@@ -39,6 +41,18 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(SleepConfig*, sleep_config_free);
int parse_sleep_config(SleepConfig **sleep_config);
+static inline bool SLEEP_NEEDS_MEM_SLEEP(const SleepConfig *sc, SleepOperation operation) {
+ assert(sc);
+ assert(operation >= 0 && operation < _SLEEP_OPERATION_CONFIG_MAX);
+
+ /* As per https://docs.kernel.org/admin-guide/pm/sleep-states.html#basic-sysfs-interfaces-for-system-suspend-and-hibernation,
+ * /sys/power/mem_sleep is honored if /sys/power/state is set to "mem" (common for suspend)
+ * or /sys/power/disk is set to "suspend" (hybrid-sleep). */
+
+ return strv_contains(sc->states[operation], "mem") ||
+ strv_contains(sc->modes[operation], "suspend");
+}
+
typedef enum SleepSupport {
SLEEP_SUPPORTED,
SLEEP_DISABLED, /* Disabled in SleepConfig.allow */
@@ -55,5 +69,5 @@ static inline int sleep_supported(SleepOperation operation) {
}
/* Only for test-sleep-config */
-int sleep_state_supported(char **states);
-int sleep_mode_supported(char **modes);
+int sleep_state_supported(char * const *states);
+int sleep_mode_supported(const char *path, char * const *modes);
diff --git a/src/shared/tpm2-util.c b/src/shared/tpm2-util.c
index 203cf5fb3a..42975cdb97 100644
--- a/src/shared/tpm2-util.c
+++ b/src/shared/tpm2-util.c
@@ -668,6 +668,8 @@ int tpm2_context_new(const char *device, Tpm2Context **ret_context) {
if (!context->tcti_dl)
return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to load %s: %s", fn, dlerror());
+ log_debug("Loaded '%s' via dlopen()", fn);
+
func = dlsym(context->tcti_dl, TSS2_TCTI_INFO_SYMBOL);
if (!func)
return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
diff --git a/src/shared/udev-util.c b/src/shared/udev-util.c
index 0014b7236f..15996ca724 100644
--- a/src/shared/udev-util.c
+++ b/src/shared/udev-util.c
@@ -139,7 +139,7 @@ static int device_wait_for_initialization_internal(
}
if (device) {
- if (sd_device_get_is_initialized(device) > 0) {
+ if (device_is_processed(device) > 0) {
if (ret)
*ret = sd_device_ref(device);
return 0;
@@ -202,7 +202,7 @@ static int device_wait_for_initialization_internal(
if (r < 0 && !ERRNO_IS_DEVICE_ABSENT(r))
return log_error_errno(r, "Failed to create sd-device object from %s: %m", devlink);
}
- if (device && sd_device_get_is_initialized(device) > 0) {
+ if (device && device_is_processed(device) > 0) {
if (ret)
*ret = sd_device_ref(device);
return 0;
@@ -237,16 +237,27 @@ int device_is_renaming(sd_device *dev) {
return r;
}
-int device_is_processing(sd_device *dev) {
+int device_is_processed(sd_device *dev) {
int r;
assert(dev);
+ /* sd_device_get_is_initialized() only checks if the udev database file exists. However, even if the
+ * database file exist, systemd-udevd may be still processing the device, e.g. when the udev rules
+ * for the device have RUN tokens. See issue #30056. Hence, to check if the device is really
+ * processed by systemd-udevd, we also need to read ID_PROCESSING property. */
+
+ r = sd_device_get_is_initialized(dev);
+ if (r <= 0)
+ return r;
+
r = device_get_property_bool(dev, "ID_PROCESSING");
if (r == -ENOENT)
- return false; /* defaults to false */
+ return true; /* If the property does not exist, then it means that the device is processed. */
+ if (r < 0)
+ return r;
- return r;
+ return !r;
}
bool device_for_action(sd_device *dev, sd_device_action_t a) {
diff --git a/src/shared/udev-util.h b/src/shared/udev-util.h
index 13710a3ec1..c21c4c158c 100644
--- a/src/shared/udev-util.h
+++ b/src/shared/udev-util.h
@@ -13,7 +13,7 @@ int udev_parse_config(void);
int device_wait_for_initialization(sd_device *device, const char *subsystem, usec_t timeout_usec, sd_device **ret);
int device_wait_for_devlink(const char *path, const char *subsystem, usec_t timeout_usec, sd_device **ret);
int device_is_renaming(sd_device *dev);
-int device_is_processing(sd_device *dev);
+int device_is_processed(sd_device *dev);
bool device_for_action(sd_device *dev, sd_device_action_t action);
diff --git a/src/shared/userdb.c b/src/shared/userdb.c
index d262c82d63..75dece3442 100644
--- a/src/shared/userdb.c
+++ b/src/shared/userdb.c
@@ -1455,6 +1455,8 @@ int userdb_block_nss_systemd(int b) {
return 0;
}
+ log_debug("Loaded '%s' via dlopen()", LIBDIR "/libnss_systemd.so.2");
+
call = dlsym(dl, "_nss_systemd_block");
if (!call)
/* If the file is installed but lacks the symbol we expect, things are weird, let's complain */
diff --git a/src/shared/watchdog.c b/src/shared/watchdog.c
index 2d79f7147a..99ccefb227 100644
--- a/src/shared/watchdog.c
+++ b/src/shared/watchdog.c
@@ -95,7 +95,7 @@ static int set_pretimeout_governor(const char *governor) {
governor,
WRITE_STRING_FILE_DISABLE_BUFFER | WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_VERIFY_IGNORE_NEWLINE);
if (r < 0)
- return log_error_errno(r, "Failed to set pretimeout_governor to '%s': %m", governor);
+ return log_error_errno(r, "Failed to set watchdog pretimeout_governor to '%s': %m", governor);
return r;
}
@@ -157,7 +157,7 @@ static int watchdog_read_pretimeout(void) {
if (ioctl(watchdog_fd, WDIOC_GETPRETIMEOUT, &sec) < 0) {
watchdog_pretimeout = 0;
- return log_full_errno(ERRNO_IS_NOT_SUPPORTED(errno) ? LOG_DEBUG : LOG_WARNING, errno, "Failed to get pretimeout value, ignoring: %m");
+ return log_full_errno(ERRNO_IS_NOT_SUPPORTED(errno) ? LOG_DEBUG : LOG_WARNING, errno, "Failed to get watchdog pretimeout value, ignoring: %m");
}
watchdog_pretimeout = sec * USEC_PER_SEC;
@@ -181,7 +181,7 @@ static int watchdog_set_pretimeout(void) {
return 0;
}
- return log_error_errno(errno, "Failed to set pretimeout to %s: %m", FORMAT_TIMESPAN(sec, USEC_PER_SEC));
+ return log_error_errno(errno, "Failed to set watchdog pretimeout to %s: %m", FORMAT_TIMESPAN(sec, USEC_PER_SEC));
}
/* The set ioctl does not return the actual value set so get it now. */
@@ -274,10 +274,10 @@ static int update_timeout(void) {
r = watchdog_set_timeout();
if (r < 0) {
if (!ERRNO_IS_NOT_SUPPORTED(r))
- return log_error_errno(r, "Failed to set timeout to %s: %m",
+ return log_error_errno(r, "Failed to set watchdog hardware timeout to %s: %m",
FORMAT_TIMESPAN(watchdog_timeout, 0));
- log_info("Modifying watchdog timeout is not supported, reusing the programmed timeout.");
+ log_info("Modifying watchdog hardware timeout is not supported, reusing the programmed timeout.");
watchdog_timeout = USEC_INFINITY;
}
}
@@ -286,8 +286,8 @@ static int update_timeout(void) {
r = watchdog_read_timeout();
if (r < 0) {
if (!ERRNO_IS_NOT_SUPPORTED(r))
- return log_error_errno(r, "Failed to query watchdog HW timeout: %m");
- log_info("Reading watchdog timeout is not supported, reusing the configured timeout.");
+ return log_error_errno(r, "Failed to query watchdog hardware timeout: %m");
+ log_info("Reading watchdog hardware timeout is not supported, reusing the configured timeout.");
watchdog_timeout = previous_timeout;
}
}
@@ -302,7 +302,7 @@ static int update_timeout(void) {
if (r < 0)
return r;
- log_info("Watchdog running with a timeout of %s.", FORMAT_TIMESPAN(watchdog_timeout, 0));
+ log_info("Watchdog running with a hardware timeout of %s.", FORMAT_TIMESPAN(watchdog_timeout, 0));
return watchdog_ping_now();
}
diff --git a/src/sleep/sleep.c b/src/sleep/sleep.c
index 0f619ce0f5..c96207428d 100644
--- a/src/sleep/sleep.c
+++ b/src/sleep/sleep.c
@@ -151,22 +151,22 @@ static int write_state(int fd, char * const *states) {
return r;
}
-static int write_mode(char * const *modes) {
- int r = 0;
+static int write_mode(const char *path, char * const *modes) {
+ int r, ret = 0;
- STRV_FOREACH(mode, modes) {
- int k;
+ assert(path);
- k = write_string_file("/sys/power/disk", *mode, WRITE_STRING_FILE_DISABLE_BUFFER);
- if (k >= 0) {
- log_debug("Using sleep disk mode '%s'.", *mode);
+ STRV_FOREACH(mode, modes) {
+ r = write_string_file(path, *mode, WRITE_STRING_FILE_DISABLE_BUFFER);
+ if (r >= 0) {
+ log_debug("Using sleep mode '%s' for %s.", *mode, path);
return 0;
}
- RET_GATHER(r, log_debug_errno(k, "Failed to write '%s' to /sys/power/disk: %m", *mode));
+ RET_GATHER(ret, log_debug_errno(r, "Failed to write '%s' to %s: %m", *mode, path));
}
- return r;
+ return ret;
}
static int lock_all_homes(void) {
@@ -237,8 +237,14 @@ static int execute(
if (state_fd < 0)
return log_error_errno(errno, "Failed to open /sys/power/state: %m");
+ if (SLEEP_NEEDS_MEM_SLEEP(sleep_config, operation)) {
+ r = write_mode("/sys/power/mem_sleep", sleep_config->mem_modes);
+ if (r < 0)
+ return log_error_errno(r, "Failed to write mode to /sys/power/mem_sleep: %m");
+ }
+
/* Configure hibernation settings if we are supposed to hibernate */
- if (sleep_operation_is_hibernation(operation)) {
+ if (SLEEP_OPERATION_IS_HIBERNATION(operation)) {
_cleanup_(hibernation_device_done) HibernationDevice hibernation_device = {};
bool resume_set;
@@ -259,7 +265,7 @@ static int execute(
goto fail;
}
- r = write_mode(sleep_config->modes[operation]);
+ r = write_mode("/sys/power/disk", sleep_config->modes[operation]);
if (r < 0) {
log_error_errno(r, "Failed to write mode to /sys/power/disk: %m");
goto fail;
@@ -301,8 +307,8 @@ static int execute(
return 0;
fail:
- if (sleep_operation_is_hibernation(operation))
- clear_efi_hibernate_location_and_warn();
+ if (SLEEP_OPERATION_IS_HIBERNATION(operation))
+ (void) clear_efi_hibernate_location_and_warn();
return r;
}
diff --git a/src/sleep/sleep.conf b/src/sleep/sleep.conf
index fad95b3897..d12f97099a 100644
--- a/src/sleep/sleep.conf
+++ b/src/sleep/sleep.conf
@@ -23,5 +23,6 @@
#AllowHybridSleep=yes
#SuspendState=mem standby freeze
#HibernateMode=platform shutdown
+#SleepMemMode=
#HibernateDelaySec=
#SuspendEstimationSec=60min
diff --git a/src/ssh-generator/ssh-generator.c b/src/ssh-generator/ssh-generator.c
index 5e03783543..3b9987b581 100644
--- a/src/ssh-generator/ssh-generator.c
+++ b/src/ssh-generator/ssh-generator.c
@@ -401,10 +401,8 @@ static int parse_credentials(void) {
int r;
r = read_credential_with_decryption("ssh.listen", (void*) &b, &sz);
- if (r < 0)
+ if (r <= 0)
return r;
- if (r == 0)
- return 0;
_cleanup_fclose_ FILE *f = NULL;
f = fmemopen_unlocked(b, sz, "r");
diff --git a/src/storagetm/storagetm.c b/src/storagetm/storagetm.c
index 62b78a350f..e060998829 100644
--- a/src/storagetm/storagetm.c
+++ b/src/storagetm/storagetm.c
@@ -1214,8 +1214,11 @@ static int run(int argc, char* argv[]) {
if (r < 0)
return log_error_errno(r, "Failed to exclude loop devices: %m");
- FOREACH_DEVICE(enumerator, device)
+ FOREACH_DEVICE(enumerator, device) {
+ if (device_is_processed(device) <= 0)
+ continue;
device_added(&context, device);
+ }
}
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
diff --git a/src/sysext/sysext.c b/src/sysext/sysext.c
index b984e9b9a0..79b016f9c3 100644
--- a/src/sysext/sysext.c
+++ b/src/sysext/sysext.c
@@ -748,8 +748,7 @@ static OverlayFSPaths *overlayfs_paths_free(OverlayFSPaths *op) {
free(op->work_dir);
strv_free(op->lower_dirs);
- free(op);
- return NULL;
+ return mfree(op);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(OverlayFSPaths *, overlayfs_paths_free);
diff --git a/src/systemctl/meson.build b/src/systemctl/meson.build
index 257c362cea..88f73bf502 100644
--- a/src/systemctl/meson.build
+++ b/src/systemctl/meson.build
@@ -44,8 +44,7 @@ if get_option('link-systemctl-shared')
systemctl_link_with = [libshared]
else
systemctl_link_with = [libsystemd_static,
- libshared_static,
- libbasic_gcrypt]
+ libshared_static]
endif
executables += [
diff --git a/src/systemd/meson.build b/src/systemd/meson.build
index a91d7064bb..389f32908c 100644
--- a/src/systemd/meson.build
+++ b/src/systemd/meson.build
@@ -38,6 +38,7 @@ _not_installed_headers = [
'sd-lldp-tx.h',
'sd-lldp.h',
'sd-ndisc.h',
+ 'sd-ndisc-neighbor.h',
'sd-ndisc-protocol.h',
'sd-ndisc-router.h',
'sd-netlink.h',
diff --git a/src/systemd/sd-bus-vtable.h b/src/systemd/sd-bus-vtable.h
index 5e80ea895d..d06c5c3015 100644
--- a/src/systemd/sd-bus-vtable.h
+++ b/src/systemd/sd-bus-vtable.h
@@ -208,6 +208,7 @@ struct sd_bus_vtable {
_41, _42, _43, _44, _45, _46, _47, _48, _49, _50, \
NAME, ...) NAME
+#define _SD_VARARGS_FOREACH_EVEN_00(FN)
#define _SD_VARARGS_FOREACH_EVEN_01(FN, X) FN(X)
#define _SD_VARARGS_FOREACH_EVEN_02(FN, X, Y) FN(X)
#define _SD_VARARGS_FOREACH_EVEN_04(FN, X, Y, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_02(FN, __VA_ARGS__)
@@ -261,9 +262,11 @@ struct sd_bus_vtable {
_SD_VARARGS_FOREACH_EVEN_08, _SD_VARARGS_FOREACH_EVEN_07, \
_SD_VARARGS_FOREACH_EVEN_06, _SD_VARARGS_FOREACH_EVEN_05, \
_SD_VARARGS_FOREACH_EVEN_04, _SD_VARARGS_FOREACH_EVEN_03, \
- _SD_VARARGS_FOREACH_EVEN_02, _SD_VARARGS_FOREACH_EVEN_01) \
+ _SD_VARARGS_FOREACH_EVEN_02, _SD_VARARGS_FOREACH_EVEN_01, \
+ _SD_VARARGS_FOREACH_EVEN_00) \
(FN, __VA_ARGS__)
+#define _SD_VARARGS_FOREACH_ODD_00(FN)
#define _SD_VARARGS_FOREACH_ODD_01(FN, X)
#define _SD_VARARGS_FOREACH_ODD_02(FN, X, Y) FN(Y)
#define _SD_VARARGS_FOREACH_ODD_04(FN, X, Y, ...) FN(Y) _SD_VARARGS_FOREACH_ODD_02(FN, __VA_ARGS__)
@@ -317,7 +320,8 @@ struct sd_bus_vtable {
_SD_VARARGS_FOREACH_ODD_08, _SD_VARARGS_FOREACH_ODD_07, \
_SD_VARARGS_FOREACH_ODD_06, _SD_VARARGS_FOREACH_ODD_05, \
_SD_VARARGS_FOREACH_ODD_04, _SD_VARARGS_FOREACH_ODD_03, \
- _SD_VARARGS_FOREACH_ODD_02, _SD_VARARGS_FOREACH_ODD_01) \
+ _SD_VARARGS_FOREACH_ODD_02, _SD_VARARGS_FOREACH_ODD_01, \
+ _SD_VARARGS_FOREACH_ODD_00) \
(FN, __VA_ARGS__)
#define SD_BUS_ARGS(...) __VA_ARGS__
diff --git a/src/systemd/sd-ndisc-neighbor.h b/src/systemd/sd-ndisc-neighbor.h
new file mode 100644
index 0000000000..2ea033741f
--- /dev/null
+++ b/src/systemd/sd-ndisc-neighbor.h
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#ifndef foosdndiscneighborfoo
+#define foosdndiscneighborfoo
+
+/***
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <https://www.gnu.org/licenses/>.
+***/
+
+#include <inttypes.h>
+#include <net/ethernet.h>
+#include <netinet/in.h>
+#include <sys/types.h>
+#include <time.h>
+
+#include "_sd-common.h"
+
+_SD_BEGIN_DECLARATIONS;
+
+typedef struct sd_ndisc_neighbor sd_ndisc_neighbor;
+
+sd_ndisc_neighbor *sd_ndisc_neighbor_ref(sd_ndisc_neighbor *na);
+sd_ndisc_neighbor *sd_ndisc_neighbor_unref(sd_ndisc_neighbor *na);
+_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_ndisc_neighbor, sd_ndisc_neighbor_unref);
+
+int sd_ndisc_neighbor_get_sender_address(sd_ndisc_neighbor *na, struct in6_addr *ret);
+/* RFC 4861 section 4.4:
+ * For solicited advertisements, the Target Address field in the Neighbor Solicitation message that prompted
+ * this advertisement. For an unsolicited advertisement, the address whose link-layer address has changed.
+ * The Target Address MUST NOT be a multicast address. */
+int sd_ndisc_neighbor_get_target_address(sd_ndisc_neighbor *na, struct in6_addr *ret);
+int sd_ndisc_neighbor_get_target_mac(sd_ndisc_neighbor *na, struct ether_addr *ret);
+int sd_ndisc_neighbor_get_flags(sd_ndisc_neighbor *na, uint32_t *ret);
+int sd_ndisc_neighbor_is_router(sd_ndisc_neighbor *na);
+int sd_ndisc_neighbor_is_solicited(sd_ndisc_neighbor *na);
+int sd_ndisc_neighbor_is_override(sd_ndisc_neighbor *na);
+
+_SD_END_DECLARATIONS;
+
+#endif
diff --git a/src/systemd/sd-ndisc.h b/src/systemd/sd-ndisc.h
index 5f4f6caf8d..185e0c6fd8 100644
--- a/src/systemd/sd-ndisc.h
+++ b/src/systemd/sd-ndisc.h
@@ -26,6 +26,7 @@
#include <sys/types.h>
#include "sd-event.h"
+#include "sd-ndisc-neighbor.h"
#include "sd-ndisc-protocol.h"
#include "sd-ndisc-router.h"
@@ -38,6 +39,7 @@ typedef struct sd_ndisc sd_ndisc;
__extension__ typedef enum sd_ndisc_event_t {
SD_NDISC_EVENT_TIMEOUT,
SD_NDISC_EVENT_ROUTER,
+ SD_NDISC_EVENT_NEIGHBOR,
_SD_NDISC_EVENT_MAX,
_SD_NDISC_EVENT_INVALID = -EINVAL,
_SD_ENUM_FORCE_S64(NDISC_EVENT)
diff --git a/src/sysupdate/sysupdate-transfer.c b/src/sysupdate/sysupdate-transfer.c
index b350f83065..435c38020e 100644
--- a/src/sysupdate/sysupdate-transfer.c
+++ b/src/sysupdate/sysupdate-transfer.c
@@ -532,6 +532,7 @@ int transfer_read_definition(Transfer *t, const char *path) {
"Target path is not a normalized, absolute path: %s", t->target.path);
if (strv_isempty(t->target.patterns)) {
+ log_syntax(NULL, LOG_INFO, path, 1, 0, "Target specification lacks MatchPattern= expression. Assuming same value as in source specification.");
strv_free(t->target.patterns);
t->target.patterns = strv_copy(t->source.patterns);
if (!t->target.patterns)
diff --git a/src/sysusers/meson.build b/src/sysusers/meson.build
index fcb291d02c..0f9c067d50 100644
--- a/src/sysusers/meson.build
+++ b/src/sysusers/meson.build
@@ -15,7 +15,6 @@ executables += [
'c_args' : '-DSTANDALONE',
'link_with' : [
libbasic,
- libbasic_gcrypt,
libshared_static,
libsystemd_static,
],
diff --git a/src/test/test-dirent-util.c b/src/test/test-dirent-util.c
index be0496904f..8192a53e6f 100644
--- a/src/test/test-dirent-util.c
+++ b/src/test/test-dirent-util.c
@@ -68,7 +68,7 @@ TEST (test_dirent_is_file) {
}
dir = opendir(t);
- if (dir == NULL) {
+ if (!dir) {
log_error_errno(errno, "Failed to open directory '%s': %m", t);
exit(EXIT_FAILURE);
}
@@ -144,7 +144,7 @@ TEST (test_dirent_is_file_with_suffix) {
}
dir = opendir(t);
- if (dir == NULL) {
+ if (!dir) {
log_error_errno(errno, "Failed to open directory '%s': %m", t);
exit(EXIT_FAILURE);
}
diff --git a/src/test/test-dlopen-so.c b/src/test/test-dlopen-so.c
index 3232506d5a..00134c305e 100644
--- a/src/test/test-dlopen-so.c
+++ b/src/test/test-dlopen-so.c
@@ -7,6 +7,7 @@
#include "compress.h"
#include "cryptsetup-util.h"
#include "elf-util.h"
+#include "gcrypt-util.h"
#include "idn-util.h"
#include "libarchive-util.h"
#include "libfido2-util.h"
@@ -88,6 +89,10 @@ static int run(int argc, char **argv) {
assert_se(dlopen_lzma() >= 0);
#endif
+#if HAVE_GCRYPT
+ assert_se(initialize_libgcrypt(/* secmem= */ false) >= 0);
+#endif
+
return 0;
}
diff --git a/src/test/test-sleep-config.c b/src/test/test-sleep-config.c
index 112fec6346..dc1a8fb71c 100644
--- a/src/test/test-sleep-config.c
+++ b/src/test/test-sleep-config.c
@@ -52,10 +52,10 @@ TEST(sleep_supported) {
log_info("Standby configured: %s", yes_no(sleep_state_supported(standby) > 0));
log_info("Suspend configured: %s", yes_no(sleep_state_supported(mem) > 0));
log_info("Hibernate configured: %s", yes_no(sleep_state_supported(disk) > 0));
- log_info("Hibernate+Suspend (Hybrid-Sleep) configured: %s", yes_no(sleep_mode_supported(suspend) > 0));
- log_info("Hibernate+Reboot configured: %s", yes_no(sleep_mode_supported(reboot) > 0));
- log_info("Hibernate+Platform configured: %s", yes_no(sleep_mode_supported(platform) > 0));
- log_info("Hibernate+Shutdown configured: %s", yes_no(sleep_mode_supported(shutdown) > 0));
+ log_info("Hibernate+Suspend (Hybrid-Sleep) configured: %s", yes_no(sleep_mode_supported("/sys/power/disk", suspend) > 0));
+ log_info("Hibernate+Reboot configured: %s", yes_no(sleep_mode_supported("/sys/power/disk", reboot) > 0));
+ log_info("Hibernate+Platform configured: %s", yes_no(sleep_mode_supported("/sys/power/disk", platform) > 0));
+ log_info("Hibernate+Shutdown configured: %s", yes_no(sleep_mode_supported("/sys/power/disk", shutdown) > 0));
log_info("Freeze configured: %s", yes_no(sleep_state_supported(freeze) > 0));
log_info("/= high-level sleep verbs =/");
diff --git a/src/test/test-string-util.c b/src/test/test-string-util.c
index 3b003e885f..67f332db8e 100644
--- a/src/test/test-string-util.c
+++ b/src/test/test-string-util.c
@@ -375,31 +375,31 @@ TEST(strjoin) {
actual = strjoin("", "foo", "bar");
assert_se(streq(actual, "foobar"));
- mfree(actual);
+ free(actual);
actual = strjoin("foo", "bar", "baz");
assert_se(streq(actual, "foobarbaz"));
- mfree(actual);
+ free(actual);
actual = strjoin("foo", "", "bar", "baz");
assert_se(streq(actual, "foobarbaz"));
- mfree(actual);
+ free(actual);
actual = strjoin("foo", NULL);
assert_se(streq(actual, "foo"));
- mfree(actual);
+ free(actual);
actual = strjoin(NULL, NULL);
assert_se(streq(actual, ""));
- mfree(actual);
+ free(actual);
actual = strjoin(NULL, "foo");
assert_se(streq(actual, ""));
- mfree(actual);
+ free(actual);
actual = strjoin("foo", NULL, "bar");
assert_se(streq(actual, "foo"));
- mfree(actual);
+ free(actual);
}
TEST(strcmp_ptr) {
diff --git a/src/timesync/meson.build b/src/timesync/meson.build
index 684448097c..d843ed78bf 100644
--- a/src/timesync/meson.build
+++ b/src/timesync/meson.build
@@ -21,8 +21,7 @@ if get_option('link-timesyncd-shared')
timesyncd_link_with = [libshared]
else
timesyncd_link_with = [libsystemd_static,
- libshared_static,
- libbasic_gcrypt]
+ libshared_static]
endif
libtimesyncd_core = static_library(
diff --git a/src/tmpfiles/meson.build b/src/tmpfiles/meson.build
index 8a24a21a27..2e918509a7 100644
--- a/src/tmpfiles/meson.build
+++ b/src/tmpfiles/meson.build
@@ -21,7 +21,6 @@ executables += [
'c_args' : '-DSTANDALONE',
'link_with' : [
libbasic,
- libbasic_gcrypt,
libshared_static,
libsystemd_static,
],
diff --git a/src/udev/meson.build b/src/udev/meson.build
index 824ec47803..e5b52ab642 100644
--- a/src/udev/meson.build
+++ b/src/udev/meson.build
@@ -205,6 +205,7 @@ executables += [
},
udev_test_template + {
'sources' : files('net/test-link-config-tables.c'),
+ 'include_directories' : includes + include_directories('.'),
'suite' : 'udev',
},
udev_test_template + {
@@ -240,6 +241,7 @@ executables += [
},
udev_fuzz_template + {
'sources' : files('net/fuzz-link-parser.c'),
+ 'include_directories' : includes + include_directories('.'),
},
udev_fuzz_template + {
'sources' : files('fuzz-udev-rule-parse-value.c'),
diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c
index 7f16b17467..647cdeeb9d 100644
--- a/src/udev/net/link-config.c
+++ b/src/udev/net/link-config.c
@@ -483,7 +483,7 @@ int link_get_config(LinkConfigContext *ctx, Link *link) {
return -ENOENT;
}
-static int link_apply_ethtool_settings(Link *link, int *ethtool_fd) {
+static int link_apply_ethtool_settings(Link *link, int *ethtool_fd, EventMode mode) {
LinkConfig *config;
const char *name;
int r;
@@ -492,6 +492,11 @@ static int link_apply_ethtool_settings(Link *link, int *ethtool_fd) {
assert(link->config);
assert(ethtool_fd);
+ if (mode != EVENT_UDEV_WORKER) {
+ log_link_debug(link, "Running in test mode, skipping application of ethtool settings.");
+ return 0;
+ }
+
config = link->config;
name = link->ifname;
@@ -684,7 +689,7 @@ finalize:
return 0;
}
-static int link_apply_rtnl_settings(Link *link, sd_netlink **rtnl) {
+static int link_apply_rtnl_settings(Link *link, sd_netlink **rtnl, EventMode mode) {
struct hw_addr_data hw_addr = {};
LinkConfig *config;
int r;
@@ -693,6 +698,11 @@ static int link_apply_rtnl_settings(Link *link, sd_netlink **rtnl) {
assert(link->config);
assert(rtnl);
+ if (mode != EVENT_UDEV_WORKER) {
+ log_link_debug(link, "Running in test mode, skipping application of rtnl settings.");
+ return 0;
+ }
+
config = link->config;
(void) link_generate_new_hw_addr(link, &hw_addr);
@@ -896,7 +906,7 @@ static int sr_iov_configure(Link *link, sd_netlink **rtnl, SRIOV *sr_iov) {
return 0;
}
-static int link_apply_sr_iov_config(Link *link, sd_netlink **rtnl) {
+static int link_apply_sr_iov_config(Link *link, sd_netlink **rtnl, EventMode mode) {
SRIOV *sr_iov;
uint32_t n;
int r;
@@ -905,6 +915,11 @@ static int link_apply_sr_iov_config(Link *link, sd_netlink **rtnl) {
assert(link->config);
assert(link->device);
+ if (mode != EVENT_UDEV_WORKER) {
+ log_link_debug(link, "Running in test mode, skipping application of SR-IOV settings.");
+ return 0;
+ }
+
r = sr_iov_set_num_vfs(link->device, link->config->sr_iov_num_vfs, link->config->sr_iov_by_section);
if (r < 0)
log_link_warning_errno(link, r, "Failed to set the number of SR-IOV virtual functions, ignoring: %m");
@@ -938,7 +953,7 @@ static int link_apply_sr_iov_config(Link *link, sd_netlink **rtnl) {
return 0;
}
-static int link_apply_rps_cpu_mask(Link *link) {
+static int link_apply_rps_cpu_mask(Link *link, EventMode mode) {
_cleanup_free_ char *mask_str = NULL;
LinkConfig *config;
int r;
@@ -946,6 +961,11 @@ static int link_apply_rps_cpu_mask(Link *link) {
assert(link);
config = ASSERT_PTR(link->config);
+ if (mode != EVENT_UDEV_WORKER) {
+ log_link_debug(link, "Running in test mode, skipping application of RPS setting.");
+ return 0;
+ }
+
/* Skip if the config is not specified. */
if (!config->rps_cpu_mask)
return 0;
@@ -981,7 +1001,7 @@ static int link_apply_rps_cpu_mask(Link *link) {
return 0;
}
-static int link_apply_udev_properties(Link *link, bool test) {
+static int link_apply_udev_properties(Link *link, EventMode mode) {
LinkConfig *config;
sd_device *device;
@@ -992,7 +1012,7 @@ static int link_apply_udev_properties(Link *link, bool test) {
/* 1. apply ImportProperty=. */
STRV_FOREACH(p, config->import_properties)
- (void) udev_builtin_import_property(device, link->device_db_clone, test, *p);
+ (void) udev_builtin_import_property(device, link->device_db_clone, mode, *p);
/* 2. apply Property=. */
STRV_FOREACH(p, config->properties) {
@@ -1007,15 +1027,15 @@ static int link_apply_udev_properties(Link *link, bool test) {
if (!key)
return log_oom();
- (void) udev_builtin_add_property(device, test, key, eq + 1);
+ (void) udev_builtin_add_property(device, mode, key, eq + 1);
}
/* 3. apply UnsetProperty=. */
STRV_FOREACH(p, config->unset_properties)
- (void) udev_builtin_add_property(device, test, *p, NULL);
+ (void) udev_builtin_add_property(device, mode, *p, NULL);
/* 4. set the default properties. */
- (void) udev_builtin_add_property(device, test, "ID_NET_LINK_FILE", config->filename);
+ (void) udev_builtin_add_property(device, mode, "ID_NET_LINK_FILE", config->filename);
_cleanup_free_ char *joined = NULL;
STRV_FOREACH(d, config->dropins) {
@@ -1029,26 +1049,26 @@ static int link_apply_udev_properties(Link *link, bool test) {
return log_oom();
}
- (void) udev_builtin_add_property(device, test, "ID_NET_LINK_FILE_DROPINS", joined);
+ (void) udev_builtin_add_property(device, mode, "ID_NET_LINK_FILE_DROPINS", joined);
if (link->new_name)
- (void) udev_builtin_add_property(device, test, "ID_NET_NAME", link->new_name);
+ (void) udev_builtin_add_property(device, mode, "ID_NET_NAME", link->new_name);
return 0;
}
-int link_apply_config(LinkConfigContext *ctx, sd_netlink **rtnl, Link *link, bool test) {
+int link_apply_config(LinkConfigContext *ctx, sd_netlink **rtnl, Link *link, EventMode mode) {
int r;
assert(ctx);
assert(rtnl);
assert(link);
- r = link_apply_ethtool_settings(link, &ctx->ethtool_fd);
+ r = link_apply_ethtool_settings(link, &ctx->ethtool_fd, mode);
if (r < 0)
return r;
- r = link_apply_rtnl_settings(link, rtnl);
+ r = link_apply_rtnl_settings(link, rtnl, mode);
if (r < 0)
return r;
@@ -1060,19 +1080,15 @@ int link_apply_config(LinkConfigContext *ctx, sd_netlink **rtnl, Link *link, boo
if (r < 0)
return r;
- r = link_apply_sr_iov_config(link, rtnl);
+ r = link_apply_sr_iov_config(link, rtnl, mode);
if (r < 0)
return r;
- r = link_apply_udev_properties(link, test);
+ r = link_apply_rps_cpu_mask(link, mode);
if (r < 0)
return r;
- r = link_apply_rps_cpu_mask(link);
- if (r < 0)
- return r;
-
- return 0;
+ return link_apply_udev_properties(link, mode);
}
int config_parse_udev_property(
diff --git a/src/udev/net/link-config.h b/src/udev/net/link-config.h
index f6abff89e8..103343f5a5 100644
--- a/src/udev/net/link-config.h
+++ b/src/udev/net/link-config.h
@@ -12,6 +12,7 @@
#include "list.h"
#include "net-condition.h"
#include "netif-naming-scheme.h"
+#include "udev-event.h"
typedef struct LinkConfigContext LinkConfigContext;
typedef struct LinkConfig LinkConfig;
@@ -106,7 +107,7 @@ Link *link_free(Link *link);
DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_free);
int link_get_config(LinkConfigContext *ctx, Link *link);
-int link_apply_config(LinkConfigContext *ctx, sd_netlink **rtnl, Link *link, bool test);
+int link_apply_config(LinkConfigContext *ctx, sd_netlink **rtnl, Link *link, EventMode mode);
const char *mac_address_policy_to_string(MACAddressPolicy p) _const_;
MACAddressPolicy mac_address_policy_from_string(const char *p) _pure_;
diff --git a/src/udev/test-udev-rule-runner.c b/src/udev/test-udev-rule-runner.c
index f5aa38ac3e..10da645d0d 100644
--- a/src/udev/test-udev-rule-runner.c
+++ b/src/udev/test-udev-rule-runner.c
@@ -142,7 +142,7 @@ static int run(int argc, char *argv[]) {
if (r < 0)
return log_debug_errno(r, "Failed to open device '%s'", devpath);
- assert_se(event = udev_event_new(dev, NULL));
+ assert_se(event = udev_event_new(dev, NULL, EVENT_TEST_RULE_RUNNER));
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, SIGHUP, SIGCHLD) >= 0);
diff --git a/src/udev/test-udev-spawn.c b/src/udev/test-udev-spawn.c
index 0102d8d707..7cbccf32a6 100644
--- a/src/udev/test-udev-spawn.c
+++ b/src/udev/test-udev-spawn.c
@@ -17,7 +17,7 @@ static void test_event_spawn_core(bool with_pidfd, const char *cmd, char *result
assert_se(setenv("SYSTEMD_PIDFD", yes_no(with_pidfd), 1) >= 0);
assert_se(sd_device_new_from_syspath(&dev, "/sys/class/net/lo") >= 0);
- assert_se(event = udev_event_new(dev, NULL));
+ assert_se(event = udev_event_new(dev, NULL, EVENT_TEST_SPAWN));
assert_se(udev_event_spawn(event, false, cmd, result_buf, buf_size, NULL) == 0);
assert_se(unsetenv("SYSTEMD_PIDFD") >= 0);
diff --git a/src/udev/udev-builtin-blkid.c b/src/udev/udev-builtin-blkid.c
index 11419a3e61..aec3650781 100644
--- a/src/udev/udev-builtin-blkid.c
+++ b/src/udev/udev-builtin-blkid.c
@@ -34,95 +34,95 @@
#include "strxcpyx.h"
#include "udev-builtin.h"
-static void print_property(sd_device *dev, bool test, const char *name, const char *value) {
+static void print_property(sd_device *dev, EventMode mode, const char *name, const char *value) {
char s[256];
s[0] = '\0';
if (streq(name, "TYPE")) {
- udev_builtin_add_property(dev, test, "ID_FS_TYPE", value);
+ udev_builtin_add_property(dev, mode, "ID_FS_TYPE", value);
} else if (streq(name, "USAGE")) {
- udev_builtin_add_property(dev, test, "ID_FS_USAGE", value);
+ udev_builtin_add_property(dev, mode, "ID_FS_USAGE", value);
} else if (streq(name, "VERSION")) {
- udev_builtin_add_property(dev, test, "ID_FS_VERSION", value);
+ udev_builtin_add_property(dev, mode, "ID_FS_VERSION", value);
} else if (streq(name, "UUID")) {
blkid_safe_string(value, s, sizeof(s));
- udev_builtin_add_property(dev, test, "ID_FS_UUID", s);
+ udev_builtin_add_property(dev, mode, "ID_FS_UUID", s);
blkid_encode_string(value, s, sizeof(s));
- udev_builtin_add_property(dev, test, "ID_FS_UUID_ENC", s);
+ udev_builtin_add_property(dev, mode, "ID_FS_UUID_ENC", s);
} else if (streq(name, "UUID_SUB")) {
blkid_safe_string(value, s, sizeof(s));
- udev_builtin_add_property(dev, test, "ID_FS_UUID_SUB", s);
+ udev_builtin_add_property(dev, mode, "ID_FS_UUID_SUB", s);
blkid_encode_string(value, s, sizeof(s));
- udev_builtin_add_property(dev, test, "ID_FS_UUID_SUB_ENC", s);
+ udev_builtin_add_property(dev, mode, "ID_FS_UUID_SUB_ENC", s);
} else if (streq(name, "LABEL")) {
blkid_safe_string(value, s, sizeof(s));
- udev_builtin_add_property(dev, test, "ID_FS_LABEL", s);
+ udev_builtin_add_property(dev, mode, "ID_FS_LABEL", s);
blkid_encode_string(value, s, sizeof(s));
- udev_builtin_add_property(dev, test, "ID_FS_LABEL_ENC", s);
+ udev_builtin_add_property(dev, mode, "ID_FS_LABEL_ENC", s);
} else if (STR_IN_SET(name, "FSSIZE", "FSLASTBLOCK", "FSBLOCKSIZE")) {
strscpyl(s, sizeof(s), "ID_FS_", name + 2, NULL);
- udev_builtin_add_property(dev, test, s, value);
+ udev_builtin_add_property(dev, mode, s, value);
} else if (streq(name, "PTTYPE")) {
- udev_builtin_add_property(dev, test, "ID_PART_TABLE_TYPE", value);
+ udev_builtin_add_property(dev, mode, "ID_PART_TABLE_TYPE", value);
} else if (streq(name, "PTUUID")) {
- udev_builtin_add_property(dev, test, "ID_PART_TABLE_UUID", value);
+ udev_builtin_add_property(dev, mode, "ID_PART_TABLE_UUID", value);
} else if (streq(name, "PART_ENTRY_NAME")) {
blkid_encode_string(value, s, sizeof(s));
- udev_builtin_add_property(dev, test, "ID_PART_ENTRY_NAME", s);
+ udev_builtin_add_property(dev, mode, "ID_PART_ENTRY_NAME", s);
} else if (streq(name, "PART_ENTRY_TYPE")) {
blkid_encode_string(value, s, sizeof(s));
- udev_builtin_add_property(dev, test, "ID_PART_ENTRY_TYPE", s);
+ udev_builtin_add_property(dev, mode, "ID_PART_ENTRY_TYPE", s);
} else if (startswith(name, "PART_ENTRY_")) {
strscpyl(s, sizeof(s), "ID_", name, NULL);
- udev_builtin_add_property(dev, test, s, value);
+ udev_builtin_add_property(dev, mode, s, value);
} else if (streq(name, "SYSTEM_ID")) {
blkid_encode_string(value, s, sizeof(s));
- udev_builtin_add_property(dev, test, "ID_FS_SYSTEM_ID", s);
+ udev_builtin_add_property(dev, mode, "ID_FS_SYSTEM_ID", s);
} else if (streq(name, "PUBLISHER_ID")) {
blkid_encode_string(value, s, sizeof(s));
- udev_builtin_add_property(dev, test, "ID_FS_PUBLISHER_ID", s);
+ udev_builtin_add_property(dev, mode, "ID_FS_PUBLISHER_ID", s);
} else if (streq(name, "APPLICATION_ID")) {
blkid_encode_string(value, s, sizeof(s));
- udev_builtin_add_property(dev, test, "ID_FS_APPLICATION_ID", s);
+ udev_builtin_add_property(dev, mode, "ID_FS_APPLICATION_ID", s);
} else if (streq(name, "BOOT_SYSTEM_ID")) {
blkid_encode_string(value, s, sizeof(s));
- udev_builtin_add_property(dev, test, "ID_FS_BOOT_SYSTEM_ID", s);
+ udev_builtin_add_property(dev, mode, "ID_FS_BOOT_SYSTEM_ID", s);
} else if (streq(name, "VOLUME_ID")) {
blkid_encode_string(value, s, sizeof(s));
- udev_builtin_add_property(dev, test, "ID_FS_VOLUME_ID", s);
+ udev_builtin_add_property(dev, mode, "ID_FS_VOLUME_ID", s);
} else if (streq(name, "LOGICAL_VOLUME_ID")) {
blkid_encode_string(value, s, sizeof(s));
- udev_builtin_add_property(dev, test, "ID_FS_LOGICAL_VOLUME_ID", s);
+ udev_builtin_add_property(dev, mode, "ID_FS_LOGICAL_VOLUME_ID", s);
} else if (streq(name, "VOLUME_SET_ID")) {
blkid_encode_string(value, s, sizeof(s));
- udev_builtin_add_property(dev, test, "ID_FS_VOLUME_SET_ID", s);
+ udev_builtin_add_property(dev, mode, "ID_FS_VOLUME_SET_ID", s);
} else if (streq(name, "DATA_PREPARER_ID")) {
blkid_encode_string(value, s, sizeof(s));
- udev_builtin_add_property(dev, test, "ID_FS_DATA_PREPARER_ID", s);
+ udev_builtin_add_property(dev, mode, "ID_FS_DATA_PREPARER_ID", s);
}
}
-static int find_gpt_root(sd_device *dev, blkid_probe pr, bool test) {
+static int find_gpt_root(sd_device *dev, blkid_probe pr, EventMode mode) {
#if defined(SD_GPT_ROOT_NATIVE) && ENABLE_EFI
@@ -201,7 +201,7 @@ static int find_gpt_root(sd_device *dev, blkid_probe pr, bool test) {
/* We found the ESP/XBOOTLDR on this disk, and also found a root partition, nice! Let's export its
* UUID */
if (found_esp_or_xbootldr && !sd_id128_is_null(root_id))
- udev_builtin_add_property(dev, test, "ID_PART_GPT_AUTO_ROOT_UUID", SD_ID128_TO_UUID_STRING(root_id));
+ udev_builtin_add_property(dev, mode, "ID_PART_GPT_AUTO_ROOT_UUID", SD_ID128_TO_UUID_STRING(root_id));
#endif
return 0;
@@ -315,7 +315,7 @@ notloop:
return 0;
}
-static int builtin_blkid(UdevEvent *event, int argc, char *argv[], bool test) {
+static int builtin_blkid(UdevEvent *event, int argc, char *argv[]) {
sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
const char *devnode, *root_partition = NULL, *data, *name;
_cleanup_(blkid_free_probep) blkid_probe pr = NULL;
@@ -422,7 +422,7 @@ static int builtin_blkid(UdevEvent *event, int argc, char *argv[], bool test) {
if (blkid_probe_get_value(pr, i, &name, &data, NULL) < 0)
continue;
- print_property(dev, test, name, data);
+ print_property(dev, event->event_mode, name, data);
/* Is this a disk with GPT partition table? */
if (streq(name, "PTTYPE") && streq(data, "gpt"))
@@ -431,11 +431,11 @@ static int builtin_blkid(UdevEvent *event, int argc, char *argv[], bool test) {
/* Is this a partition that matches the root partition
* property inherited from the parent? */
if (root_partition && streq(name, "PART_ENTRY_UUID") && streq(data, root_partition))
- udev_builtin_add_property(dev, test, "ID_PART_GPT_AUTO_ROOT", "1");
+ udev_builtin_add_property(dev, event->event_mode, "ID_PART_GPT_AUTO_ROOT", "1");
}
if (is_gpt)
- find_gpt_root(dev, pr, test);
+ find_gpt_root(dev, pr, event->event_mode);
r = read_loopback_backing_inode(
dev,
@@ -446,8 +446,8 @@ static int builtin_blkid(UdevEvent *event, int argc, char *argv[], bool test) {
if (r < 0)
log_device_debug_errno(dev, r, "Failed to read loopback backing inode, ignoring: %m");
else if (r > 0) {
- udev_builtin_add_propertyf(dev, test, "ID_LOOP_BACKING_DEVICE", DEVNUM_FORMAT_STR, DEVNUM_FORMAT_VAL(backing_devno));
- udev_builtin_add_propertyf(dev, test, "ID_LOOP_BACKING_INODE", "%" PRIu64, (uint64_t) backing_inode);
+ udev_builtin_add_propertyf(dev, event->event_mode, "ID_LOOP_BACKING_DEVICE", DEVNUM_FORMAT_STR, DEVNUM_FORMAT_VAL(backing_devno));
+ udev_builtin_add_propertyf(dev, event->event_mode, "ID_LOOP_BACKING_INODE", "%" PRIu64, (uint64_t) backing_inode);
if (backing_fname) {
/* In the worst case blkid_encode_string() will blow up to 4x the string
@@ -458,8 +458,8 @@ static int builtin_blkid(UdevEvent *event, int argc, char *argv[], bool test) {
assert(strlen(backing_fname) < ELEMENTSOF(encoded) / 4);
blkid_encode_string(backing_fname, encoded, ELEMENTSOF(encoded));
- udev_builtin_add_property(dev, test, "ID_LOOP_BACKING_FILENAME", backing_fname);
- udev_builtin_add_property(dev, test, "ID_LOOP_BACKING_FILENAME_ENC", encoded);
+ udev_builtin_add_property(dev, event->event_mode, "ID_LOOP_BACKING_FILENAME", backing_fname);
+ udev_builtin_add_property(dev, event->event_mode, "ID_LOOP_BACKING_FILENAME_ENC", encoded);
}
}
diff --git a/src/udev/udev-builtin-btrfs.c b/src/udev/udev-builtin-btrfs.c
index 9b12aebb3a..fe030d05b9 100644
--- a/src/udev/udev-builtin-btrfs.c
+++ b/src/udev/udev-builtin-btrfs.c
@@ -12,7 +12,7 @@
#include "strxcpyx.h"
#include "udev-builtin.h"
-static int builtin_btrfs(UdevEvent *event, int argc, char *argv[], bool test) {
+static int builtin_btrfs(UdevEvent *event, int argc, char *argv[]) {
sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
struct btrfs_ioctl_vol_args args = {};
_cleanup_close_ int fd = -EBADF;
@@ -27,7 +27,7 @@ static int builtin_btrfs(UdevEvent *event, int argc, char *argv[], bool test) {
/* Driver not installed? Then we aren't ready. This is useful in initrds that lack
* btrfs.ko. After the host transition (where btrfs.ko will hopefully become
* available) the device can be retriggered and will then be considered ready. */
- udev_builtin_add_property(dev, test, "ID_BTRFS_READY", "0");
+ udev_builtin_add_property(dev, event->event_mode, "ID_BTRFS_READY", "0");
return 0;
}
@@ -39,7 +39,7 @@ static int builtin_btrfs(UdevEvent *event, int argc, char *argv[], bool test) {
if (r < 0)
return log_device_debug_errno(dev, errno, "Failed to call BTRFS_IOC_DEVICES_READY: %m");
- udev_builtin_add_property(dev, test, "ID_BTRFS_READY", one_zero(r == 0));
+ udev_builtin_add_property(dev, event->event_mode, "ID_BTRFS_READY", one_zero(r == 0));
return 0;
}
diff --git a/src/udev/udev-builtin-hwdb.c b/src/udev/udev-builtin-hwdb.c
index 4540c33d98..e33a7febd6 100644
--- a/src/udev/udev-builtin-hwdb.c
+++ b/src/udev/udev-builtin-hwdb.c
@@ -17,9 +17,13 @@
static sd_hwdb *hwdb;
-int udev_builtin_hwdb_lookup(sd_device *dev,
- const char *prefix, const char *modalias,
- const char *filter, bool test) {
+int udev_builtin_hwdb_lookup(
+ sd_device *dev,
+ const char *prefix,
+ const char *modalias,
+ const char *filter,
+ EventMode mode) {
+
_cleanup_free_ char *lookup = NULL;
const char *key, *value;
int n = 0, r;
@@ -38,7 +42,7 @@ int udev_builtin_hwdb_lookup(sd_device *dev,
if (filter && fnmatch(filter, key, FNM_NOESCAPE) != 0)
continue;
- r = udev_builtin_add_property(dev, test, key, value);
+ r = udev_builtin_add_property(dev, mode, key, value);
if (r < 0)
return r;
n++;
@@ -64,9 +68,14 @@ static const char *modalias_usb(sd_device *dev, char *s, size_t size) {
return s;
}
-static int udev_builtin_hwdb_search(sd_device *dev, sd_device *srcdev,
- const char *subsystem, const char *prefix,
- const char *filter, bool test) {
+static int udev_builtin_hwdb_search(
+ sd_device *dev,
+ sd_device *srcdev,
+ const char *subsystem,
+ const char *prefix,
+ const char *filter,
+ EventMode mode) {
+
char s[LINE_MAX];
bool last = false;
int r = 0;
@@ -99,7 +108,7 @@ static int udev_builtin_hwdb_search(sd_device *dev, sd_device *srcdev,
log_device_debug(dev, "hwdb modalias key: \"%s\"", modalias);
- r = udev_builtin_hwdb_lookup(dev, prefix, modalias, filter, test);
+ r = udev_builtin_hwdb_lookup(dev, prefix, modalias, filter, mode);
if (r > 0)
break;
@@ -113,7 +122,7 @@ next:
return r;
}
-static int builtin_hwdb(UdevEvent *event, int argc, char *argv[], bool test) {
+static int builtin_hwdb(UdevEvent *event, int argc, char *argv[]) {
static const struct option options[] = {
{ "filter", required_argument, NULL, 'f' },
{ "device", required_argument, NULL, 'd' },
@@ -160,7 +169,7 @@ static int builtin_hwdb(UdevEvent *event, int argc, char *argv[], bool test) {
/* query a specific key given as argument */
if (argv[optind]) {
- r = udev_builtin_hwdb_lookup(dev, prefix, argv[optind], filter, test);
+ r = udev_builtin_hwdb_lookup(dev, prefix, argv[optind], filter, event->event_mode);
if (r < 0)
return log_device_debug_errno(dev, r, "Failed to look up hwdb: %m");
if (r == 0)
@@ -175,7 +184,7 @@ static int builtin_hwdb(UdevEvent *event, int argc, char *argv[], bool test) {
return log_device_debug_errno(dev, r, "Failed to create sd_device object '%s': %m", device);
}
- r = udev_builtin_hwdb_search(dev, srcdev, subsystem, prefix, filter, test);
+ r = udev_builtin_hwdb_search(dev, srcdev, subsystem, prefix, filter, event->event_mode);
if (r < 0)
return log_device_debug_errno(dev, r, "Failed to look up hwdb: %m");
if (r == 0)
diff --git a/src/udev/udev-builtin-input_id.c b/src/udev/udev-builtin-input_id.c
index 295e8d2159..6f75d9df22 100644
--- a/src/udev/udev-builtin-input_id.c
+++ b/src/udev/udev-builtin-input_id.c
@@ -44,7 +44,7 @@ static int abs_size_mm(const struct input_absinfo *absinfo) {
return (absinfo->maximum - absinfo->minimum) / absinfo->resolution;
}
-static void extract_info(sd_device *dev, bool test) {
+static void extract_info(sd_device *dev, EventMode mode) {
char width[DECIMAL_STR_MAX(int)], height[DECIMAL_STR_MAX(int)];
struct input_absinfo xabsinfo = {}, yabsinfo = {};
_cleanup_close_ int fd = -EBADF;
@@ -63,8 +63,8 @@ static void extract_info(sd_device *dev, bool test) {
xsprintf(width, "%d", abs_size_mm(&xabsinfo));
xsprintf(height, "%d", abs_size_mm(&yabsinfo));
- udev_builtin_add_property(dev, test, "ID_INPUT_WIDTH_MM", width);
- udev_builtin_add_property(dev, test, "ID_INPUT_HEIGHT_MM", height);
+ udev_builtin_add_property(dev, mode, "ID_INPUT_WIDTH_MM", width);
+ udev_builtin_add_property(dev, mode, "ID_INPUT_HEIGHT_MM", height);
}
/*
@@ -73,9 +73,13 @@ static void extract_info(sd_device *dev, bool test) {
* @param attr sysfs attribute name (e. g. "capabilities/key")
* @param bitmask: Output array which has a sizeof of bitmask_size
*/
-static void get_cap_mask(sd_device *pdev, const char* attr,
- unsigned long *bitmask, size_t bitmask_size,
- bool test) {
+static void get_cap_mask(
+ sd_device *pdev,
+ const char* attr,
+ unsigned long *bitmask,
+ size_t bitmask_size,
+ EventMode mode) {
+
const char *v;
char text[4096];
unsigned i;
@@ -110,7 +114,7 @@ static void get_cap_mask(sd_device *pdev, const char* attr,
else
log_device_debug(pdev, "Ignoring %s block %lX which is larger than maximum size", attr, val);
- if (test && DEBUG_LOGGING) {
+ if (mode == EVENT_UDEVADM_TEST_BUILTIN && DEBUG_LOGGING) {
log_device_debug(pdev, "%s decoded bit map:", attr);
val = bitmask_size / sizeof (unsigned long);
@@ -144,14 +148,16 @@ static struct input_id get_input_id(sd_device *dev) {
}
/* pointer devices */
-static bool test_pointers(sd_device *dev,
- const struct input_id *id,
- const unsigned long* bitmask_ev,
- const unsigned long* bitmask_abs,
- const unsigned long* bitmask_key,
- const unsigned long* bitmask_rel,
- const unsigned long* bitmask_props,
- bool test) {
+static bool test_pointers(
+ sd_device *dev,
+ const struct input_id *id,
+ const unsigned long* bitmask_ev,
+ const unsigned long* bitmask_abs,
+ const unsigned long* bitmask_key,
+ const unsigned long* bitmask_rel,
+ const unsigned long* bitmask_props,
+ EventMode mode) {
+
bool has_abs_coordinates = false;
bool has_rel_coordinates = false;
bool has_mt_coordinates = false;
@@ -186,7 +192,7 @@ static bool test_pointers(sd_device *dev,
is_accelerometer = true;
if (is_accelerometer) {
- udev_builtin_add_property(dev, test, "ID_INPUT_ACCELEROMETER", "1");
+ udev_builtin_add_property(dev, mode, "ID_INPUT_ACCELEROMETER", "1");
return true;
}
@@ -309,28 +315,29 @@ static bool test_pointers(sd_device *dev,
}
if (is_pointing_stick)
- udev_builtin_add_property(dev, test, "ID_INPUT_POINTINGSTICK", "1");
+ udev_builtin_add_property(dev, mode, "ID_INPUT_POINTINGSTICK", "1");
if (is_mouse || is_abs_mouse)
- udev_builtin_add_property(dev, test, "ID_INPUT_MOUSE", "1");
+ udev_builtin_add_property(dev, mode, "ID_INPUT_MOUSE", "1");
if (is_touchpad)
- udev_builtin_add_property(dev, test, "ID_INPUT_TOUCHPAD", "1");
+ udev_builtin_add_property(dev, mode, "ID_INPUT_TOUCHPAD", "1");
if (is_touchscreen)
- udev_builtin_add_property(dev, test, "ID_INPUT_TOUCHSCREEN", "1");
+ udev_builtin_add_property(dev, mode, "ID_INPUT_TOUCHSCREEN", "1");
if (is_joystick)
- udev_builtin_add_property(dev, test, "ID_INPUT_JOYSTICK", "1");
+ udev_builtin_add_property(dev, mode, "ID_INPUT_JOYSTICK", "1");
if (is_tablet)
- udev_builtin_add_property(dev, test, "ID_INPUT_TABLET", "1");
+ udev_builtin_add_property(dev, mode, "ID_INPUT_TABLET", "1");
if (is_tablet_pad)
- udev_builtin_add_property(dev, test, "ID_INPUT_TABLET_PAD", "1");
+ udev_builtin_add_property(dev, mode, "ID_INPUT_TABLET_PAD", "1");
return is_tablet || is_mouse || is_abs_mouse || is_touchpad || is_touchscreen || is_joystick || is_pointing_stick;
}
/* key like devices */
-static bool test_key(sd_device *dev,
- const unsigned long* bitmask_ev,
- const unsigned long* bitmask_key,
- bool test) {
+static bool test_key(
+ sd_device *dev,
+ const unsigned long* bitmask_ev,
+ const unsigned long* bitmask_key,
+ EventMode mode) {
bool found = false;
@@ -357,19 +364,19 @@ static bool test_key(sd_device *dev,
}
if (found)
- udev_builtin_add_property(dev, test, "ID_INPUT_KEY", "1");
+ udev_builtin_add_property(dev, mode, "ID_INPUT_KEY", "1");
/* the first 32 bits are ESC, numbers, and Q to D; if we have all of
* those, consider it a full keyboard; do not test KEY_RESERVED, though */
if (FLAGS_SET(bitmask_key[0], 0xFFFFFFFE)) {
- udev_builtin_add_property(dev, test, "ID_INPUT_KEYBOARD", "1");
+ udev_builtin_add_property(dev, mode, "ID_INPUT_KEYBOARD", "1");
return true;
}
return found;
}
-static int builtin_input_id(UdevEvent *event, int argc, char *argv[], bool test) {
+static int builtin_input_id(UdevEvent *event, int argc, char *argv[]) {
sd_device *pdev, *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
unsigned long bitmask_ev[NBITS(EV_MAX)];
unsigned long bitmask_abs[NBITS(ABS_MAX)];
@@ -400,28 +407,28 @@ static int builtin_input_id(UdevEvent *event, int argc, char *argv[], bool test)
/* Use this as a flag that input devices were detected, so that this
* program doesn't need to be called more than once per device */
- udev_builtin_add_property(dev, test, "ID_INPUT", "1");
- get_cap_mask(pdev, "capabilities/ev", bitmask_ev, sizeof(bitmask_ev), test);
- get_cap_mask(pdev, "capabilities/abs", bitmask_abs, sizeof(bitmask_abs), test);
- get_cap_mask(pdev, "capabilities/rel", bitmask_rel, sizeof(bitmask_rel), test);
- get_cap_mask(pdev, "capabilities/key", bitmask_key, sizeof(bitmask_key), test);
- get_cap_mask(pdev, "properties", bitmask_props, sizeof(bitmask_props), test);
+ udev_builtin_add_property(dev, event->event_mode, "ID_INPUT", "1");
+ get_cap_mask(pdev, "capabilities/ev", bitmask_ev, sizeof(bitmask_ev), event->event_mode);
+ get_cap_mask(pdev, "capabilities/abs", bitmask_abs, sizeof(bitmask_abs), event->event_mode);
+ get_cap_mask(pdev, "capabilities/rel", bitmask_rel, sizeof(bitmask_rel), event->event_mode);
+ get_cap_mask(pdev, "capabilities/key", bitmask_key, sizeof(bitmask_key), event->event_mode);
+ get_cap_mask(pdev, "properties", bitmask_props, sizeof(bitmask_props), event->event_mode);
is_pointer = test_pointers(dev, &id, bitmask_ev, bitmask_abs,
bitmask_key, bitmask_rel,
- bitmask_props, test);
- is_key = test_key(dev, bitmask_ev, bitmask_key, test);
+ bitmask_props, event->event_mode);
+ is_key = test_key(dev, bitmask_ev, bitmask_key, event->event_mode);
/* Some evdev nodes have only a scrollwheel */
if (!is_pointer && !is_key && test_bit(EV_REL, bitmask_ev) &&
(test_bit(REL_WHEEL, bitmask_rel) || test_bit(REL_HWHEEL, bitmask_rel)))
- udev_builtin_add_property(dev, test, "ID_INPUT_KEY", "1");
+ udev_builtin_add_property(dev, event->event_mode, "ID_INPUT_KEY", "1");
if (test_bit(EV_SW, bitmask_ev))
- udev_builtin_add_property(dev, test, "ID_INPUT_SWITCH", "1");
+ udev_builtin_add_property(dev, event->event_mode, "ID_INPUT_SWITCH", "1");
}
if (sd_device_get_sysname(dev, &sysname) >= 0 &&
startswith(sysname, "event"))
- extract_info(dev, test);
+ extract_info(dev, event->event_mode);
return 0;
}
diff --git a/src/udev/udev-builtin-keyboard.c b/src/udev/udev-builtin-keyboard.c
index 3903bc463f..e1e6de0426 100644
--- a/src/udev/udev-builtin-keyboard.c
+++ b/src/udev/udev-builtin-keyboard.c
@@ -159,7 +159,7 @@ static int set_trackpoint_sensitivity(sd_device *dev, const char *value) {
return 0;
}
-static int builtin_keyboard(UdevEvent *event, int argc, char *argv[], bool test) {
+static int builtin_keyboard(UdevEvent *event, int argc, char *argv[]) {
sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
unsigned release[1024];
unsigned release_count = 0;
@@ -167,6 +167,11 @@ static int builtin_keyboard(UdevEvent *event, int argc, char *argv[], bool test)
const char *node;
int has_abs = -1, r;
+ if (event->event_mode != EVENT_UDEV_WORKER) {
+ log_device_debug(dev, "Running in test mode, skipping execution of 'keyboard' builtin command.");
+ return 0;
+ }
+
r = sd_device_get_devname(dev, &node);
if (r < 0)
return log_device_error_errno(dev, r, "Failed to get device name: %m");
diff --git a/src/udev/udev-builtin-kmod.c b/src/udev/udev-builtin-kmod.c
index 3ab5c485f8..6d37af88a3 100644
--- a/src/udev/udev-builtin-kmod.c
+++ b/src/udev/udev-builtin-kmod.c
@@ -22,10 +22,15 @@ _printf_(6,0) static void udev_kmod_log(void *data, int priority, const char *fi
log_internalv(priority, 0, file, line, fn, format, args);
}
-static int builtin_kmod(UdevEvent *event, int argc, char *argv[], bool test) {
+static int builtin_kmod(UdevEvent *event, int argc, char *argv[]) {
sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
int r;
+ if (event->event_mode != EVENT_UDEV_WORKER) {
+ log_device_debug(dev, "Running in test mode, skipping execution of 'kmod' builtin command.");
+ return 0;
+ }
+
if (!ctx)
return 0;
diff --git a/src/udev/udev-builtin-net_driver.c b/src/udev/udev-builtin-net_driver.c
index f1642a491d..90a9e8d22f 100644
--- a/src/udev/udev-builtin-net_driver.c
+++ b/src/udev/udev-builtin-net_driver.c
@@ -9,7 +9,7 @@
#include "string-util.h"
#include "udev-builtin.h"
-static int builtin_net_driver_set_driver(UdevEvent *event, int argc, char **argv, bool test) {
+static int builtin_net_driver_set_driver(UdevEvent *event, int argc, char **argv) {
sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
_cleanup_close_ int ethtool_fd = -EBADF;
_cleanup_free_ char *driver = NULL;
@@ -32,7 +32,7 @@ static int builtin_net_driver_set_driver(UdevEvent *event, int argc, char **argv
if (r < 0)
return log_device_warning_errno(dev, r, "Failed to get driver for '%s': %m", sysname);
- return udev_builtin_add_property(event->dev, test, "ID_NET_DRIVER", driver);
+ return udev_builtin_add_property(event->dev, event->event_mode, "ID_NET_DRIVER", driver);
}
const UdevBuiltin udev_builtin_net_driver = {
diff --git a/src/udev/udev-builtin-net_id.c b/src/udev/udev-builtin-net_id.c
index 8ef3abada9..0d87a35288 100644
--- a/src/udev/udev-builtin-net_id.c
+++ b/src/udev/udev-builtin-net_id.c
@@ -298,7 +298,7 @@ static int pci_get_onboard_index(sd_device *dev, unsigned *ret) {
return 0;
}
-static int names_pci_onboard(sd_device *dev, sd_device *pci_dev, const char *prefix, const char *suffix, bool test) {
+static int names_pci_onboard(sd_device *dev, sd_device *pci_dev, const char *prefix, const char *suffix, EventMode mode) {
_cleanup_free_ char *port = NULL;
unsigned idx = 0; /* avoid false maybe-uninitialized warning */
int r;
@@ -318,7 +318,7 @@ static int names_pci_onboard(sd_device *dev, sd_device *pci_dev, const char *pre
char str[ALTIFNAMSIZ];
if (snprintf_ok(str, sizeof str, "%so%u%s%s", prefix, idx, strempty(port), strempty(suffix)))
- udev_builtin_add_property(dev, test, "ID_NET_NAME_ONBOARD", str);
+ udev_builtin_add_property(dev, mode, "ID_NET_NAME_ONBOARD", str);
log_device_debug(dev, "Onboard index identifier: index=%u port=%s %s %s",
idx, strna(port),
@@ -327,7 +327,7 @@ static int names_pci_onboard(sd_device *dev, sd_device *pci_dev, const char *pre
return 0;
}
-static int names_pci_onboard_label(sd_device *dev, sd_device *pci_dev, const char *prefix, bool test) {
+static int names_pci_onboard_label(sd_device *dev, sd_device *pci_dev, const char *prefix, EventMode mode) {
const char *label;
int r;
@@ -343,7 +343,7 @@ static int names_pci_onboard_label(sd_device *dev, sd_device *pci_dev, const cha
if (snprintf_ok(str, sizeof str, "%s%s",
naming_scheme_has(NAMING_LABEL_NOPREFIX) ? "" : prefix,
label))
- udev_builtin_add_property(dev, test, "ID_NET_LABEL_ONBOARD", str);
+ udev_builtin_add_property(dev, mode, "ID_NET_LABEL_ONBOARD", str);
log_device_debug(dev, "Onboard label from PCI device: %s", label);
return 0;
@@ -613,7 +613,7 @@ static int get_pci_slot_specifiers(
return 0;
}
-static int names_pci_slot(sd_device *dev, sd_device *pci_dev, const char *prefix, const char *suffix, bool test) {
+static int names_pci_slot(sd_device *dev, sd_device *pci_dev, const char *prefix, const char *suffix, EventMode mode) {
_cleanup_free_ char *domain = NULL, *bus_and_slot = NULL, *func = NULL, *port = NULL;
uint32_t hotplug_slot = 0; /* avoid false maybe-uninitialized warning */
char str[ALTIFNAMSIZ];
@@ -634,7 +634,7 @@ static int names_pci_slot(sd_device *dev, sd_device *pci_dev, const char *prefix
/* compose a name based on the raw kernel's PCI bus, slot numbers */
if (snprintf_ok(str, sizeof str, "%s%s%s%s%s%s",
prefix, strempty(domain), bus_and_slot, strempty(func), strempty(port), strempty(suffix)))
- udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str);
+ udev_builtin_add_property(dev, mode, "ID_NET_NAME_PATH", str);
log_device_debug(dev, "PCI path identifier: domain=%s bus_and_slot=%s func=%s port=%s %s %s",
strna(domain), bus_and_slot, strna(func), strna(port),
@@ -650,7 +650,7 @@ static int names_pci_slot(sd_device *dev, sd_device *pci_dev, const char *prefix
if (snprintf_ok(str, sizeof str, "%s%ss%"PRIu32"%s%s%s",
prefix, strempty(domain), hotplug_slot, strempty(func), strempty(port), strempty(suffix)))
- udev_builtin_add_property(dev, test, "ID_NET_NAME_SLOT", str);
+ udev_builtin_add_property(dev, mode, "ID_NET_NAME_SLOT", str);
log_device_debug(dev, "Slot identifier: domain=%s slot=%"PRIu32" func=%s port=%s %s %s",
strna(domain), hotplug_slot, strna(func), strna(port),
@@ -659,7 +659,7 @@ static int names_pci_slot(sd_device *dev, sd_device *pci_dev, const char *prefix
return 0;
}
-static int names_vio(sd_device *dev, const char *prefix, bool test) {
+static int names_vio(sd_device *dev, const char *prefix, EventMode mode) {
_cleanup_free_ char *s = NULL;
unsigned slotid;
int r;
@@ -698,13 +698,13 @@ static int names_vio(sd_device *dev, const char *prefix, bool test) {
char str[ALTIFNAMSIZ];
if (snprintf_ok(str, sizeof str, "%sv%u", prefix, slotid))
- udev_builtin_add_property(dev, test, "ID_NET_NAME_SLOT", str);
+ udev_builtin_add_property(dev, mode, "ID_NET_NAME_SLOT", str);
log_device_debug(dev, "Vio slot identifier: slotid=%u %s %s",
slotid, special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), str + strlen(prefix));
return 0;
}
-static int names_platform(sd_device *dev, const char *prefix, bool test) {
+static int names_platform(sd_device *dev, const char *prefix, EventMode mode) {
_cleanup_free_ char *p = NULL;
const char *validchars;
char *vendor, *model_str, *instance_str;
@@ -760,13 +760,13 @@ static int names_platform(sd_device *dev, const char *prefix, bool test) {
char str[ALTIFNAMSIZ];
if (snprintf_ok(str, sizeof str, "%sa%s%xi%u", prefix, vendor, model, instance))
- udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str);
+ udev_builtin_add_property(dev, mode, "ID_NET_NAME_PATH", str);
log_device_debug(dev, "Platform identifier: vendor=%s model=%x instance=%u %s %s",
vendor, model, instance, special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), str + strlen(prefix));
return 0;
}
-static int names_devicetree(sd_device *dev, const char *prefix, bool test) {
+static int names_devicetree(sd_device *dev, const char *prefix, EventMode mode) {
_cleanup_(sd_device_unrefp) sd_device *aliases_dev = NULL, *ofnode_dev = NULL, *devicetree_dev = NULL;
const char *ofnode_path, *ofnode_syspath, *devicetree_syspath;
sd_device *parent;
@@ -858,7 +858,7 @@ static int names_devicetree(sd_device *dev, const char *prefix, bool test) {
char str[ALTIFNAMSIZ];
if (snprintf_ok(str, sizeof str, "%sd%u", prefix, i))
- udev_builtin_add_property(dev, test, "ID_NET_NAME_ONBOARD", str);
+ udev_builtin_add_property(dev, mode, "ID_NET_NAME_ONBOARD", str);
log_device_debug(dev, "devicetree identifier: alias_index=%u %s \"%s\"",
i, special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), str + strlen(prefix));
return 0;
@@ -867,7 +867,7 @@ static int names_devicetree(sd_device *dev, const char *prefix, bool test) {
return -ENOENT;
}
-static int names_pci(sd_device *dev, const char *prefix, bool test) {
+static int names_pci(sd_device *dev, const char *prefix, EventMode mode) {
_cleanup_(sd_device_unrefp) sd_device *physfn_pcidev = NULL;
_cleanup_free_ char *virtfn_suffix = NULL;
sd_device *parent;
@@ -884,10 +884,10 @@ static int names_pci(sd_device *dev, const char *prefix, bool test) {
get_virtfn_info(parent, &physfn_pcidev, &virtfn_suffix) >= 0)
parent = physfn_pcidev;
else
- (void) names_pci_onboard_label(dev, parent, prefix, test);
+ (void) names_pci_onboard_label(dev, parent, prefix, mode);
- (void) names_pci_onboard(dev, parent, prefix, virtfn_suffix, test);
- (void) names_pci_slot(dev, parent, prefix, virtfn_suffix, test);
+ (void) names_pci_onboard(dev, parent, prefix, virtfn_suffix, mode);
+ (void) names_pci_slot(dev, parent, prefix, virtfn_suffix, mode);
return 0;
}
@@ -950,7 +950,7 @@ static int get_usb_specifier(sd_device *dev, char **ret) {
return 0;
}
-static int names_usb(sd_device *dev, const char *prefix, bool test) {
+static int names_usb(sd_device *dev, const char *prefix, EventMode mode) {
_cleanup_free_ char *suffix = NULL;
sd_device *usbdev, *pcidev;
int r;
@@ -971,7 +971,7 @@ static int names_usb(sd_device *dev, const char *prefix, bool test) {
/* If the USB bus is on PCI bus, then suffix the USB specifier to the name based on the PCI bus. */
r = sd_device_get_parent_with_subsystem_devtype(usbdev, "pci", NULL, &pcidev);
if (r >= 0)
- return names_pci_slot(dev, pcidev, prefix, suffix, test);
+ return names_pci_slot(dev, pcidev, prefix, suffix, mode);
if (r != -ENOENT || !naming_scheme_has(NAMING_USB_HOST))
return log_device_debug_errno(usbdev, r, "Failed to get parent PCI bus: %m");
@@ -979,7 +979,7 @@ static int names_usb(sd_device *dev, const char *prefix, bool test) {
/* Otherwise, e.g. on-chip asics that have USB ports, use the USB specifier as is. */
char str[ALTIFNAMSIZ];
if (snprintf_ok(str, sizeof str, "%s%s", prefix, suffix))
- udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str);
+ udev_builtin_add_property(dev, mode, "ID_NET_NAME_PATH", str);
return 0;
}
@@ -1014,7 +1014,7 @@ static int get_bcma_specifier(sd_device *dev, char **ret) {
return 0;
}
-static int names_bcma(sd_device *dev, const char *prefix, bool test) {
+static int names_bcma(sd_device *dev, const char *prefix, EventMode mode) {
_cleanup_free_ char *suffix = NULL;
sd_device *bcmadev, *pcidev;
int r;
@@ -1034,10 +1034,10 @@ static int names_bcma(sd_device *dev, const char *prefix, bool test) {
if (r < 0)
return r;
- return names_pci_slot(dev, pcidev, prefix, suffix, test);
+ return names_pci_slot(dev, pcidev, prefix, suffix, mode);
}
-static int names_ccw(sd_device *dev, const char *prefix, bool test) {
+static int names_ccw(sd_device *dev, const char *prefix, EventMode mode) {
sd_device *cdev;
const char *bus_id;
size_t bus_id_start, bus_id_len;
@@ -1079,14 +1079,14 @@ static int names_ccw(sd_device *dev, const char *prefix, bool test) {
/* Use the CCW bus-ID as network device name */
char str[ALTIFNAMSIZ];
if (snprintf_ok(str, sizeof str, "%sc%s", prefix, bus_id))
- udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str);
+ udev_builtin_add_property(dev, mode, "ID_NET_NAME_PATH", str);
log_device_debug(dev, "CCW identifier: ccw_busid=%s %s \"%s\"",
bus_id, special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), str + strlen(prefix));
return 0;
}
/* IEEE Organizationally Unique Identifier vendor string */
-static int ieee_oui(sd_device *dev, const struct hw_addr_data *hw_addr, bool test) {
+static int ieee_oui(sd_device *dev, const struct hw_addr_data *hw_addr, EventMode mode) {
char str[32];
assert(dev);
@@ -1109,10 +1109,10 @@ static int ieee_oui(sd_device *dev, const struct hw_addr_data *hw_addr, bool tes
hw_addr->bytes[4],
hw_addr->bytes[5]);
- return udev_builtin_hwdb_lookup(dev, NULL, str, NULL, test);
+ return udev_builtin_hwdb_lookup(dev, NULL, str, NULL, mode);
}
-static int names_mac(sd_device *dev, const char *prefix, bool test) {
+static int names_mac(sd_device *dev, const char *prefix, EventMode mode) {
unsigned iftype, assign_type;
struct hw_addr_data hw_addr;
const char *s;
@@ -1156,16 +1156,16 @@ static int names_mac(sd_device *dev, const char *prefix, bool test) {
char str[ALTIFNAMSIZ];
xsprintf(str, "%sx%s", prefix, HW_ADDR_TO_STR_FULL(&hw_addr, HW_ADDR_TO_STRING_NO_COLON));
- udev_builtin_add_property(dev, test, "ID_NET_NAME_MAC", str);
+ udev_builtin_add_property(dev, mode, "ID_NET_NAME_MAC", str);
log_device_debug(dev, "MAC address identifier: hw_addr=%s %s %s",
HW_ADDR_TO_STR(&hw_addr),
special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), str + strlen(prefix));
- (void) ieee_oui(dev, &hw_addr, test);
+ (void) ieee_oui(dev, &hw_addr, mode);
return 0;
}
-static int names_netdevsim(sd_device *dev, const char *prefix, bool test) {
+static int names_netdevsim(sd_device *dev, const char *prefix, EventMode mode) {
sd_device *netdevsimdev;
const char *sysnum, *phys_port_name;
unsigned addr;
@@ -1200,13 +1200,13 @@ static int names_netdevsim(sd_device *dev, const char *prefix, bool test) {
char str[ALTIFNAMSIZ];
if (snprintf_ok(str, sizeof str, "%si%un%s", prefix, addr, phys_port_name))
- udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str);
+ udev_builtin_add_property(dev, mode, "ID_NET_NAME_PATH", str);
log_device_debug(dev, "Netdevsim identifier: address=%u, port_name=%s %s %s",
addr, phys_port_name, special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), str + strlen(prefix));
return 0;
}
-static int names_xen(sd_device *dev, const char *prefix, bool test) {
+static int names_xen(sd_device *dev, const char *prefix, EventMode mode) {
_cleanup_free_ char *vif = NULL;
const char *p;
unsigned id;
@@ -1240,7 +1240,7 @@ static int names_xen(sd_device *dev, const char *prefix, bool test) {
char str[ALTIFNAMSIZ];
if (snprintf_ok(str, sizeof str, "%sX%u", prefix, id))
- udev_builtin_add_property(dev, test, "ID_NET_NAME_SLOT", str);
+ udev_builtin_add_property(dev, mode, "ID_NET_NAME_SLOT", str);
log_device_debug(dev, "Xen identifier: id=%u %s %s",
id, special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), str + strlen(prefix));
return 0;
@@ -1300,7 +1300,7 @@ static int device_is_stacked(sd_device *dev) {
return ifindex != iflink;
}
-static int builtin_net_id(UdevEvent *event, int argc, char *argv[], bool test) {
+static int builtin_net_id(UdevEvent *event, int argc, char *argv[]) {
sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
const char *prefix;
int r;
@@ -1318,18 +1318,18 @@ static int builtin_net_id(UdevEvent *event, int argc, char *argv[], bool test) {
return 0;
}
- udev_builtin_add_property(dev, test, "ID_NET_NAMING_SCHEME", naming_scheme()->name);
-
- (void) names_mac(dev, prefix, test);
- (void) names_devicetree(dev, prefix, test);
- (void) names_ccw(dev, prefix, test);
- (void) names_vio(dev, prefix, test);
- (void) names_platform(dev, prefix, test);
- (void) names_netdevsim(dev, prefix, test);
- (void) names_xen(dev, prefix, test);
- (void) names_pci(dev, prefix, test);
- (void) names_usb(dev, prefix, test);
- (void) names_bcma(dev, prefix, test);
+ udev_builtin_add_property(dev, event->event_mode, "ID_NET_NAMING_SCHEME", naming_scheme()->name);
+
+ (void) names_mac(dev, prefix, event->event_mode);
+ (void) names_devicetree(dev, prefix, event->event_mode);
+ (void) names_ccw(dev, prefix, event->event_mode);
+ (void) names_vio(dev, prefix, event->event_mode);
+ (void) names_platform(dev, prefix, event->event_mode);
+ (void) names_netdevsim(dev, prefix, event->event_mode);
+ (void) names_xen(dev, prefix, event->event_mode);
+ (void) names_pci(dev, prefix, event->event_mode);
+ (void) names_usb(dev, prefix, event->event_mode);
+ (void) names_bcma(dev, prefix, event->event_mode);
return 0;
}
diff --git a/src/udev/udev-builtin-net_setup_link.c b/src/udev/udev-builtin-net_setup_link.c
index df89679de3..8cfcaa932f 100644
--- a/src/udev/udev-builtin-net_setup_link.c
+++ b/src/udev/udev-builtin-net_setup_link.c
@@ -12,7 +12,7 @@
static LinkConfigContext *ctx = NULL;
-static int builtin_net_setup_link(UdevEvent *event, int argc, char **argv, bool test) {
+static int builtin_net_setup_link(UdevEvent *event, int argc, char **argv) {
sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
_cleanup_(link_freep) Link *link = NULL;
int r;
@@ -30,13 +30,13 @@ static int builtin_net_setup_link(UdevEvent *event, int argc, char **argv, bool
device_action_to_string(action));
/* Import previously assigned .link file name. */
- (void) udev_builtin_import_property(dev, event->dev_db_clone, test, "ID_NET_LINK_FILE");
- (void) udev_builtin_import_property(dev, event->dev_db_clone, test, "ID_NET_LINK_FILE_DROPINS");
+ (void) udev_builtin_import_property(dev, event->dev_db_clone, event->event_mode, "ID_NET_LINK_FILE");
+ (void) udev_builtin_import_property(dev, event->dev_db_clone, event->event_mode, "ID_NET_LINK_FILE_DROPINS");
/* Set ID_NET_NAME= with the current interface name. */
const char *value;
if (sd_device_get_sysname(dev, &value) >= 0)
- (void) udev_builtin_add_property(dev, test, "ID_NET_NAME", value);
+ (void) udev_builtin_add_property(dev, event->event_mode, "ID_NET_NAME", value);
return 0;
}
@@ -59,7 +59,7 @@ static int builtin_net_setup_link(UdevEvent *event, int argc, char **argv, bool
return log_device_error_errno(dev, r, "Failed to get link config: %m");
}
- r = link_apply_config(ctx, &event->rtnl, link, test);
+ r = link_apply_config(ctx, &event->rtnl, link, event->event_mode);
if (r == -ENODEV)
log_device_debug_errno(dev, r, "Link vanished while applying configuration, ignoring.");
else if (r < 0)
diff --git a/src/udev/udev-builtin-path_id.c b/src/udev/udev-builtin-path_id.c
index dc0630596b..a23b32db3e 100644
--- a/src/udev/udev-builtin-path_id.c
+++ b/src/udev/udev-builtin-path_id.c
@@ -642,7 +642,7 @@ static int find_real_nvme_parent(sd_device *dev, sd_device **ret) {
return 0;
}
-static void add_id_with_usb_revision(sd_device *dev, bool test, char *path) {
+static void add_id_with_usb_revision(sd_device *dev, EventMode mode, char *path) {
char *p;
assert(dev);
@@ -659,13 +659,13 @@ static void add_id_with_usb_revision(sd_device *dev, bool test, char *path) {
if (p[1] != '-')
return;
- (void) udev_builtin_add_property(dev, test, "ID_PATH_WITH_USB_REVISION", path);
+ (void) udev_builtin_add_property(dev, mode, "ID_PATH_WITH_USB_REVISION", path);
/* Drop the USB revision specifier for backward compatibility. */
memmove(p - 1, p + 1, strlen(p + 1) + 1);
}
-static void add_id_tag(sd_device *dev, bool test, const char *path) {
+static void add_id_tag(sd_device *dev, EventMode mode, const char *path) {
char tag[UDEV_NAME_SIZE];
size_t i = 0;
@@ -693,10 +693,10 @@ static void add_id_tag(sd_device *dev, bool test, const char *path) {
i--;
tag[i] = '\0';
- (void) udev_builtin_add_property(dev, test, "ID_PATH_TAG", tag);
+ (void) udev_builtin_add_property(dev, mode, "ID_PATH_TAG", tag);
}
-static int builtin_path_id(UdevEvent *event, int argc, char *argv[], bool test) {
+static int builtin_path_id(UdevEvent *event, int argc, char *argv[]) {
sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
_cleanup_(sd_device_unrefp) sd_device *dev_other_branch = NULL;
_cleanup_free_ char *path = NULL, *compat_path = NULL;
@@ -851,11 +851,11 @@ static int builtin_path_id(UdevEvent *event, int argc, char *argv[], bool test)
if (device_in_subsystem(dev, "block") && !supported_transport)
return -ENOENT;
- add_id_with_usb_revision(dev, test, path);
+ add_id_with_usb_revision(dev, event->event_mode, path);
- (void) udev_builtin_add_property(dev, test, "ID_PATH", path);
+ (void) udev_builtin_add_property(dev, event->event_mode, "ID_PATH", path);
- add_id_tag(dev, test, path);
+ add_id_tag(dev, event->event_mode, path);
/*
* Compatible link generation for ATA devices
@@ -863,7 +863,7 @@ static int builtin_path_id(UdevEvent *event, int argc, char *argv[], bool test)
* ID_PATH_ATA_COMPAT
*/
if (compat_path)
- (void) udev_builtin_add_property(dev, test, "ID_PATH_ATA_COMPAT", compat_path);
+ (void) udev_builtin_add_property(dev, event->event_mode, "ID_PATH_ATA_COMPAT", compat_path);
return 0;
}
diff --git a/src/udev/udev-builtin-uaccess.c b/src/udev/udev-builtin-uaccess.c
index da42ef59b0..805d048e81 100644
--- a/src/udev/udev-builtin-uaccess.c
+++ b/src/udev/udev-builtin-uaccess.c
@@ -17,13 +17,18 @@
#include "log.h"
#include "udev-builtin.h"
-static int builtin_uaccess(UdevEvent *event, int argc, char *argv[], bool test) {
+static int builtin_uaccess(UdevEvent *event, int argc, char *argv[]) {
sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
const char *path = NULL, *seat;
bool changed_acl = false;
uid_t uid;
int r;
+ if (event->event_mode != EVENT_UDEV_WORKER) {
+ log_device_debug(dev, "Running in test mode, skipping execution of 'uaccess' builtin command.");
+ return 0;
+ }
+
umask(0022);
/* don't muck around with ACLs when the system is not running systemd */
diff --git a/src/udev/udev-builtin-usb_id.c b/src/udev/udev-builtin-usb_id.c
index f5b8fe9e9a..2413f9ce9e 100644
--- a/src/udev/udev-builtin-usb_id.c
+++ b/src/udev/udev-builtin-usb_id.c
@@ -224,7 +224,7 @@ static int dev_if_packed_info(sd_device *dev, char *ifs_str, size_t len) {
* 6.) If the device supplies a serial number, this number
* is concatenated with the identification with an underscore '_'.
*/
-static int builtin_usb_id(UdevEvent *event, int argc, char *argv[], bool test) {
+static int builtin_usb_id(UdevEvent *event, int argc, char *argv[]) {
sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
char vendor_str[64] = "";
char vendor_str_enc[256];
@@ -429,55 +429,55 @@ fallback:
if (sd_device_get_property_value(dev, "ID_BUS", NULL) >= 0)
log_device_debug(dev, "ID_BUS property is already set, setting only properties prefixed with \"ID_USB_\".");
else {
- udev_builtin_add_property(dev, test, "ID_BUS", "usb");
+ udev_builtin_add_property(dev, event->event_mode, "ID_BUS", "usb");
- udev_builtin_add_property(dev, test, "ID_MODEL", model_str);
- udev_builtin_add_property(dev, test, "ID_MODEL_ENC", model_str_enc);
- udev_builtin_add_property(dev, test, "ID_MODEL_ID", product_id);
+ udev_builtin_add_property(dev, event->event_mode, "ID_MODEL", model_str);
+ udev_builtin_add_property(dev, event->event_mode, "ID_MODEL_ENC", model_str_enc);
+ udev_builtin_add_property(dev, event->event_mode, "ID_MODEL_ID", product_id);
- udev_builtin_add_property(dev, test, "ID_SERIAL", serial);
+ udev_builtin_add_property(dev, event->event_mode, "ID_SERIAL", serial);
if (!isempty(serial_str))
- udev_builtin_add_property(dev, test, "ID_SERIAL_SHORT", serial_str);
+ udev_builtin_add_property(dev, event->event_mode, "ID_SERIAL_SHORT", serial_str);
- udev_builtin_add_property(dev, test, "ID_VENDOR", vendor_str);
- udev_builtin_add_property(dev, test, "ID_VENDOR_ENC", vendor_str_enc);
- udev_builtin_add_property(dev, test, "ID_VENDOR_ID", vendor_id);
+ udev_builtin_add_property(dev, event->event_mode, "ID_VENDOR", vendor_str);
+ udev_builtin_add_property(dev, event->event_mode, "ID_VENDOR_ENC", vendor_str_enc);
+ udev_builtin_add_property(dev, event->event_mode, "ID_VENDOR_ID", vendor_id);
- udev_builtin_add_property(dev, test, "ID_REVISION", revision_str);
+ udev_builtin_add_property(dev, event->event_mode, "ID_REVISION", revision_str);
if (!isempty(type_str))
- udev_builtin_add_property(dev, test, "ID_TYPE", type_str);
+ udev_builtin_add_property(dev, event->event_mode, "ID_TYPE", type_str);
if (!isempty(instance_str))
- udev_builtin_add_property(dev, test, "ID_INSTANCE", instance_str);
+ udev_builtin_add_property(dev, event->event_mode, "ID_INSTANCE", instance_str);
}
/* Also export the same values in the above by prefixing ID_USB_. */
- udev_builtin_add_property(dev, test, "ID_USB_MODEL", model_str);
- udev_builtin_add_property(dev, test, "ID_USB_MODEL_ENC", model_str_enc);
- udev_builtin_add_property(dev, test, "ID_USB_MODEL_ID", product_id);
- udev_builtin_add_property(dev, test, "ID_USB_SERIAL", serial);
+ udev_builtin_add_property(dev, event->event_mode, "ID_USB_MODEL", model_str);
+ udev_builtin_add_property(dev, event->event_mode, "ID_USB_MODEL_ENC", model_str_enc);
+ udev_builtin_add_property(dev, event->event_mode, "ID_USB_MODEL_ID", product_id);
+ udev_builtin_add_property(dev, event->event_mode, "ID_USB_SERIAL", serial);
if (!isempty(serial_str))
- udev_builtin_add_property(dev, test, "ID_USB_SERIAL_SHORT", serial_str);
+ udev_builtin_add_property(dev, event->event_mode, "ID_USB_SERIAL_SHORT", serial_str);
- udev_builtin_add_property(dev, test, "ID_USB_VENDOR", vendor_str);
- udev_builtin_add_property(dev, test, "ID_USB_VENDOR_ENC", vendor_str_enc);
- udev_builtin_add_property(dev, test, "ID_USB_VENDOR_ID", vendor_id);
+ udev_builtin_add_property(dev, event->event_mode, "ID_USB_VENDOR", vendor_str);
+ udev_builtin_add_property(dev, event->event_mode, "ID_USB_VENDOR_ENC", vendor_str_enc);
+ udev_builtin_add_property(dev, event->event_mode, "ID_USB_VENDOR_ID", vendor_id);
- udev_builtin_add_property(dev, test, "ID_USB_REVISION", revision_str);
+ udev_builtin_add_property(dev, event->event_mode, "ID_USB_REVISION", revision_str);
if (!isempty(type_str))
- udev_builtin_add_property(dev, test, "ID_USB_TYPE", type_str);
+ udev_builtin_add_property(dev, event->event_mode, "ID_USB_TYPE", type_str);
if (!isempty(instance_str))
- udev_builtin_add_property(dev, test, "ID_USB_INSTANCE", instance_str);
+ udev_builtin_add_property(dev, event->event_mode, "ID_USB_INSTANCE", instance_str);
if (!isempty(packed_if_str))
- udev_builtin_add_property(dev, test, "ID_USB_INTERFACES", packed_if_str);
+ udev_builtin_add_property(dev, event->event_mode, "ID_USB_INTERFACES", packed_if_str);
if (ifnum)
- udev_builtin_add_property(dev, test, "ID_USB_INTERFACE_NUM", ifnum);
+ udev_builtin_add_property(dev, event->event_mode, "ID_USB_INTERFACE_NUM", ifnum);
if (driver)
- udev_builtin_add_property(dev, test, "ID_USB_DRIVER", driver);
+ udev_builtin_add_property(dev, event->event_mode, "ID_USB_DRIVER", driver);
return 0;
}
diff --git a/src/udev/udev-builtin.c b/src/udev/udev-builtin.c
index 6caea8ecce..1a1cb3734d 100644
--- a/src/udev/udev-builtin.c
+++ b/src/udev/udev-builtin.c
@@ -99,7 +99,7 @@ UdevBuiltinCommand udev_builtin_lookup(const char *command) {
return _UDEV_BUILTIN_INVALID;
}
-int udev_builtin_run(UdevEvent *event, UdevBuiltinCommand cmd, const char *command, bool test) {
+int udev_builtin_run(UdevEvent *event, UdevBuiltinCommand cmd, const char *command) {
_cleanup_strv_free_ char **argv = NULL;
int r;
@@ -117,10 +117,10 @@ int udev_builtin_run(UdevEvent *event, UdevBuiltinCommand cmd, const char *comma
/* we need '0' here to reset the internal state */
optind = 0;
- return builtins[cmd]->cmd(event, strv_length(argv), argv, test);
+ return builtins[cmd]->cmd(event, strv_length(argv), argv);
}
-int udev_builtin_add_property(sd_device *dev, bool test, const char *key, const char *val) {
+int udev_builtin_add_property(sd_device *dev, EventMode mode, const char *key, const char *val) {
int r;
assert(dev);
@@ -131,13 +131,13 @@ int udev_builtin_add_property(sd_device *dev, bool test, const char *key, const
return log_device_debug_errno(dev, r, "Failed to add property '%s%s%s'",
key, val ? "=" : "", strempty(val));
- if (test)
+ if (mode == EVENT_UDEVADM_TEST_BUILTIN)
printf("%s=%s\n", key, strempty(val));
return 0;
}
-int udev_builtin_add_propertyf(sd_device *dev, bool test, const char *key, const char *valf, ...) {
+int udev_builtin_add_propertyf(sd_device *dev, EventMode mode, const char *key, const char *valf, ...) {
_cleanup_free_ char *val = NULL;
va_list ap;
int r;
@@ -152,10 +152,10 @@ int udev_builtin_add_propertyf(sd_device *dev, bool test, const char *key, const
if (r < 0)
return log_oom_debug();
- return udev_builtin_add_property(dev, test, key, val);
+ return udev_builtin_add_property(dev, mode, key, val);
}
-int udev_builtin_import_property(sd_device *dev, sd_device *src, bool test, const char *key) {
+int udev_builtin_import_property(sd_device *dev, sd_device *src, EventMode mode, const char *key) {
const char *val;
int r;
@@ -171,7 +171,7 @@ int udev_builtin_import_property(sd_device *dev, sd_device *src, bool test, cons
if (r < 0)
return log_device_debug_errno(src, r, "Failed to get property \"%s\", ignoring: %m", key);
- r = udev_builtin_add_property(dev, test, key, val);
+ r = udev_builtin_add_property(dev, mode, key, val);
if (r < 0)
return r;
diff --git a/src/udev/udev-builtin.h b/src/udev/udev-builtin.h
index c7a48b0201..0d82bebf23 100644
--- a/src/udev/udev-builtin.h
+++ b/src/udev/udev-builtin.h
@@ -34,7 +34,7 @@ typedef enum UdevBuiltinCommand {
typedef struct UdevBuiltin {
const char *name;
- int (*cmd)(UdevEvent *event, int argc, char *argv[], bool test);
+ int (*cmd)(UdevEvent *event, int argc, char *argv[]);
const char *help;
int (*init)(void);
void (*exit)(void);
@@ -79,11 +79,11 @@ void udev_builtin_exit(void);
UdevBuiltinCommand udev_builtin_lookup(const char *command);
const char *udev_builtin_name(UdevBuiltinCommand cmd);
bool udev_builtin_run_once(UdevBuiltinCommand cmd);
-int udev_builtin_run(UdevEvent *event, UdevBuiltinCommand cmd, const char *command, bool test);
+int udev_builtin_run(UdevEvent *event, UdevBuiltinCommand cmd, const char *command);
void udev_builtin_list(void);
bool udev_builtin_should_reload(void);
-int udev_builtin_add_property(sd_device *dev, bool test, const char *key, const char *val);
-int udev_builtin_add_propertyf(sd_device *dev, bool test, const char *key, const char *valf, ...) _printf_(4, 5);
-int udev_builtin_import_property(sd_device *dev, sd_device *src, bool test, const char *key);
+int udev_builtin_add_property(sd_device *dev, EventMode mode, const char *key, const char *val);
+int udev_builtin_add_propertyf(sd_device *dev, EventMode mode, const char *key, const char *valf, ...) _printf_(4, 5);
+int udev_builtin_import_property(sd_device *dev, sd_device *src, EventMode mode, const char *key);
int udev_builtin_hwdb_lookup(sd_device *dev, const char *prefix, const char *modalias,
- const char *filter, bool test);
+ const char *filter, EventMode mode);
diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c
index 4541b0e0fb..607071a8cf 100644
--- a/src/udev/udev-event.c
+++ b/src/udev/udev-event.c
@@ -16,7 +16,7 @@
#include "udev-util.h"
#include "user-util.h"
-UdevEvent *udev_event_new(sd_device *dev, UdevWorker *worker) {
+UdevEvent *udev_event_new(sd_device *dev, UdevWorker *worker, EventMode mode) {
int log_level = worker ? worker->log_level : log_get_max_level();
UdevEvent *event;
@@ -36,6 +36,7 @@ UdevEvent *udev_event_new(sd_device *dev, UdevWorker *worker) {
.mode = MODE_INVALID,
.log_level_was_debug = log_level == LOG_DEBUG,
.default_log_level = log_level,
+ .event_mode = mode,
};
return event;
@@ -110,6 +111,9 @@ static int rename_netif(UdevEvent *event) {
assert(event);
+ if (!EVENT_MODE_DESTRUCTIVE(event))
+ return 0;
+
if (!event->name)
return 0; /* No new name is requested. */
@@ -222,6 +226,9 @@ static int assign_altnames(UdevEvent *event) {
int ifindex, r;
const char *s;
+ if (!EVENT_MODE_DESTRUCTIVE(event))
+ return 0;
+
if (strv_isempty(event->altnames))
return 0;
@@ -250,6 +257,9 @@ static int update_devnode(UdevEvent *event) {
sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
int r;
+ if (!EVENT_MODE_DESTRUCTIVE(event))
+ return 0;
+
r = sd_device_get_devnum(dev, NULL);
if (r == -ENOENT)
return 0;
@@ -291,18 +301,22 @@ static int event_execute_rules_on_remove(UdevEvent *event, UdevRules *rules) {
if (r < 0)
log_device_debug_errno(dev, r, "Failed to read database under /run/udev/data/: %m");
- r = device_tag_index(dev, NULL, false);
- if (r < 0)
- log_device_debug_errno(dev, r, "Failed to remove corresponding tag files under /run/udev/tag/, ignoring: %m");
+ if (EVENT_MODE_DESTRUCTIVE(event)) {
+ r = device_tag_index(dev, NULL, false);
+ if (r < 0)
+ log_device_debug_errno(dev, r, "Failed to remove corresponding tag files under /run/udev/tag/, ignoring: %m");
- r = device_delete_db(dev);
- if (r < 0)
- log_device_debug_errno(dev, r, "Failed to delete database under /run/udev/data/, ignoring: %m");
+ r = device_delete_db(dev);
+ if (r < 0)
+ log_device_debug_errno(dev, r, "Failed to delete database under /run/udev/data/, ignoring: %m");
+ }
r = udev_rules_apply_to_event(rules, event);
- if (sd_device_get_devnum(dev, NULL) >= 0)
- (void) udev_node_remove(dev);
+ if (EVENT_MODE_DESTRUCTIVE(event)) {
+ if (sd_device_get_devnum(dev, NULL) >= 0)
+ (void) udev_node_remove(dev);
+ }
return r;
}
@@ -324,12 +338,45 @@ static int copy_all_tags(sd_device *d, sd_device *s) {
return 0;
}
+static int update_clone(UdevEvent *event) {
+ sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev_db_clone);
+ int r;
+
+ if (!EVENT_MODE_DESTRUCTIVE(event))
+ return 0;
+
+ /* Drop previously added property for safety to make IMPORT{db}="ID_RENAMING" not work. This is
+ * mostly for 'move' uevent, but let's do unconditionally. Why? If a network interface is renamed in
+ * initrd, then udevd may lose the 'move' uevent during switching root. Usually, we do not set the
+ * persistent flag for network interfaces, but user may set it. Just for safety. */
+
+ r = device_add_property(dev, "ID_RENAMING", NULL);
+ if (r < 0)
+ return log_device_debug_errno(dev, r, "Failed to remove 'ID_RENAMING' property: %m");
+
+ /* If the database file already exists, append ID_PROCESSING property to the existing database,
+ * to indicate that the device is being processed by udevd. */
+ if (device_has_db(dev) > 0) {
+ r = device_add_property(dev, "ID_PROCESSING", "1");
+ if (r < 0)
+ return log_device_warning_errno(dev, r, "Failed to add 'ID_PROCESSING' property: %m");
+
+ r = device_update_db(dev);
+ if (r < 0)
+ return log_device_warning_errno(dev, r, "Failed to update database under /run/udev/data/: %m");
+ }
+
+ return 0;
+}
+
int udev_event_execute_rules(UdevEvent *event, UdevRules *rules) {
sd_device_action_t action;
sd_device *dev;
int r;
- dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
+ assert(event);
+ assert(IN_SET(event->event_mode, EVENT_UDEV_WORKER, EVENT_UDEVADM_TEST, EVENT_TEST_RULE_RUNNER));
+ dev = ASSERT_PTR(event->dev);
assert(rules);
r = sd_device_get_action(dev, &action);
@@ -347,25 +394,9 @@ int udev_event_execute_rules(UdevEvent *event, UdevRules *rules) {
if (r < 0)
log_device_warning_errno(dev, r, "Failed to copy all tags from old database entry, ignoring: %m");
- /* Drop previously added property for safety to make IMPORT{db}="ID_RENAMING" not work. This is
- * mostly for 'move' uevent, but let's do unconditionally. Why? If a network interface is renamed in
- * initrd, then udevd may lose the 'move' uevent during switching root. Usually, we do not set the
- * persistent flag for network interfaces, but user may set it. Just for safety. */
- r = device_add_property(event->dev_db_clone, "ID_RENAMING", NULL);
+ r = update_clone(event);
if (r < 0)
- return log_device_debug_errno(dev, r, "Failed to remove 'ID_RENAMING' property: %m");
-
- /* If the database file already exists, append ID_PROCESSING property to the existing database,
- * to indicate that the device is being processed by udevd. */
- if (device_has_db(event->dev_db_clone) > 0) {
- r = device_add_property(event->dev_db_clone, "ID_PROCESSING", "1");
- if (r < 0)
- return log_device_warning_errno(event->dev_db_clone, r, "Failed to add 'ID_PROCESSING' property: %m");
-
- r = device_update_db(event->dev_db_clone);
- if (r < 0)
- return log_device_warning_errno(event->dev_db_clone, r, "Failed to update database under /run/udev/data/: %m");
- }
+ return r;
DEVICE_TRACE_POINT(rules_start, dev);
@@ -392,10 +423,12 @@ int udev_event_execute_rules(UdevEvent *event, UdevRules *rules) {
if (r < 0)
return log_device_debug_errno(dev, r, "Failed to set initialization timestamp: %m");
- /* (re)write database file */
- r = device_tag_index(dev, event->dev_db_clone, true);
- if (r < 0)
- return log_device_debug_errno(dev, r, "Failed to update tags under /run/udev/tag/: %m");
+ if (EVENT_MODE_DESTRUCTIVE(event)) {
+ /* (re)write database file */
+ r = device_tag_index(dev, event->dev_db_clone, true);
+ if (r < 0)
+ return log_device_debug_errno(dev, r, "Failed to update tags under /run/udev/tag/: %m");
+ }
/* If the database file for the device will be created below, add ID_PROCESSING=1 to indicate that
* the device is still being processed by udevd, as commands specified in RUN are invoked after
@@ -406,9 +439,11 @@ int udev_event_execute_rules(UdevEvent *event, UdevRules *rules) {
return log_device_warning_errno(dev, r, "Failed to add 'ID_PROCESSING' property: %m");
}
- r = device_update_db(dev);
- if (r < 0)
- return log_device_debug_errno(dev, r, "Failed to update database under /run/udev/data/: %m");
+ if (EVENT_MODE_DESTRUCTIVE(event)) {
+ r = device_update_db(dev);
+ if (r < 0)
+ return log_device_debug_errno(dev, r, "Failed to update database under /run/udev/data/: %m");
+ }
device_set_is_initialized(dev);
diff --git a/src/udev/udev-event.h b/src/udev/udev-event.h
index 5ff7bd7ec1..3dc89365bb 100644
--- a/src/udev/udev-event.h
+++ b/src/udev/udev-event.h
@@ -18,6 +18,14 @@
#include "udev-worker.h"
#include "user-util.h"
+typedef enum EventMode {
+ EVENT_UDEV_WORKER,
+ EVENT_UDEVADM_TEST,
+ EVENT_UDEVADM_TEST_BUILTIN,
+ EVENT_TEST_RULE_RUNNER,
+ EVENT_TEST_SPAWN,
+} EventMode;
+
typedef struct UdevEvent {
UdevWorker *worker;
sd_netlink *rtnl;
@@ -47,10 +55,16 @@ typedef struct UdevEvent {
bool run_final;
bool log_level_was_debug;
int default_log_level;
+ EventMode event_mode;
} UdevEvent;
-UdevEvent *udev_event_new(sd_device *dev, UdevWorker *worker);
+UdevEvent *udev_event_new(sd_device *dev, UdevWorker *worker, EventMode mode);
UdevEvent *udev_event_free(UdevEvent *event);
DEFINE_TRIVIAL_CLEANUP_FUNC(UdevEvent*, udev_event_free);
int udev_event_execute_rules(UdevEvent *event, UdevRules *rules);
+
+static inline bool EVENT_MODE_DESTRUCTIVE(UdevEvent *event) {
+ assert(event);
+ return IN_SET(event->event_mode, EVENT_UDEV_WORKER, EVENT_TEST_RULE_RUNNER);
+}
diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c
index 3ec675746b..51732080e8 100644
--- a/src/udev/udev-rules.c
+++ b/src/udev/udev-rules.c
@@ -2100,7 +2100,7 @@ static int udev_rule_apply_token_to_event(
return false;
}
- log_event_debug(dev, token, "Running PROGRAM '%s'", buf);
+ log_event_debug(dev, token, "Running PROGRAM=\"%s\"", buf);
r = udev_event_spawn(event, /* accept_failure = */ true, buf, result, sizeof(result), NULL);
if (r != 0) {
@@ -2264,7 +2264,7 @@ static int udev_rule_apply_token_to_event(
log_event_debug(dev, token, "Importing properties from results of builtin command '%s'", buf);
- r = udev_builtin_run(event, cmd, buf, false);
+ r = udev_builtin_run(event, cmd, buf);
if (r < 0) {
/* remember failure */
log_event_debug_errno(dev, token, r, "Failed to run builtin '%s': %m", buf);
@@ -2702,14 +2702,18 @@ static int udev_rule_apply_token_to_event(
break;
}
- log_event_debug(dev, token, "ATTR '%s' writing '%s'", buf, value);
- r = write_string_file(buf, value,
- WRITE_STRING_FILE_VERIFY_ON_FAILURE |
- WRITE_STRING_FILE_DISABLE_BUFFER |
- WRITE_STRING_FILE_AVOID_NEWLINE |
- WRITE_STRING_FILE_VERIFY_IGNORE_NEWLINE);
- if (r < 0)
- log_event_error_errno(dev, token, r, "Failed to write ATTR{%s}, ignoring: %m", buf);
+ if (EVENT_MODE_DESTRUCTIVE(event)) {
+ log_event_debug(dev, token, "Writing ATTR{'%s'}=\"%s\".", buf, value);
+ r = write_string_file(buf, value,
+ WRITE_STRING_FILE_VERIFY_ON_FAILURE |
+ WRITE_STRING_FILE_DISABLE_BUFFER |
+ WRITE_STRING_FILE_AVOID_NEWLINE |
+ WRITE_STRING_FILE_VERIFY_IGNORE_NEWLINE);
+ if (r < 0)
+ log_event_error_errno(dev, token, r, "Failed to write ATTR{%s}=\"%s\", ignoring: %m", buf, value);
+ } else
+ log_event_debug(dev, token, "Running in test mode, skipping writing ATTR{%s}=\"%s\".", buf, value);
+
break;
}
case TK_A_SYSCTL: {
@@ -2731,10 +2735,15 @@ static int udev_rule_apply_token_to_event(
}
sysctl_normalize(buf);
- log_event_debug(dev, token, "SYSCTL '%s' writing '%s'", buf, value);
- r = sysctl_write(buf, value);
- if (r < 0)
- log_event_error_errno(dev, token, r, "Failed to write SYSCTL{%s}='%s', ignoring: %m", buf, value);
+
+ if (EVENT_MODE_DESTRUCTIVE(event)) {
+ log_event_debug(dev, token, "Writing SYSCTL{%s}=\"%s\".", buf, value);
+ r = sysctl_write(buf, value);
+ if (r < 0)
+ log_event_error_errno(dev, token, r, "Failed to write SYSCTL{%s}=\"%s\", ignoring: %m", buf, value);
+ } else
+ log_event_debug(dev, token, "Running in test mode, skipping writing SYSCTL{%s}=\"%s\".", buf, value);
+
break;
}
case TK_A_RUN_BUILTIN:
diff --git a/src/udev/udev-spawn.c b/src/udev/udev-spawn.c
index 8f7c9fec42..01a6dcdaa8 100644
--- a/src/udev/udev-spawn.c
+++ b/src/udev/udev-spawn.c
@@ -225,9 +225,19 @@ int udev_event_spawn(
int r;
assert(event);
+ assert(IN_SET(event->event_mode, EVENT_UDEV_WORKER, EVENT_UDEVADM_TEST, EVENT_TEST_RULE_RUNNER, EVENT_TEST_SPAWN));
assert(event->dev);
+ assert(cmd);
assert(result || result_size == 0);
+ if (event->event_mode == EVENT_UDEVADM_TEST &&
+ !STARTSWITH_SET(cmd, "ata_id", "cdrom_id", "dmi_memory_id", "fido_id", "mtd_probe", "scsi_id")) {
+ log_device_debug(event->dev, "Running in test mode, skipping execution of '%s'.", cmd);
+ result[0] = '\0';
+ ret_truncated = false;
+ return 0;
+ }
+
int timeout_signal = event->worker ? event->worker->timeout_signal : SIGKILL;
usec_t timeout_usec = event->worker ? event->worker->timeout_usec : DEFAULT_WORKER_TIMEOUT_USEC;
usec_t now_usec = now(CLOCK_MONOTONIC);
@@ -333,7 +343,7 @@ void udev_event_execute_run(UdevEvent *event) {
if (builtin_cmd != _UDEV_BUILTIN_INVALID) {
log_device_debug(event->dev, "Running built-in command \"%s\"", command);
- r = udev_builtin_run(event, builtin_cmd, command, false);
+ r = udev_builtin_run(event, builtin_cmd, command);
if (r < 0)
log_device_debug_errno(event->dev, r, "Failed to run built-in command \"%s\", ignoring: %m", command);
} else {
diff --git a/src/udev/udev-worker.c b/src/udev/udev-worker.c
index b038b68099..97c5679b74 100644
--- a/src/udev/udev-worker.c
+++ b/src/udev/udev-worker.c
@@ -172,7 +172,7 @@ static int worker_process_device(UdevWorker *worker, sd_device *dev) {
log_device_uevent(dev, "Processing device");
- udev_event = udev_event_new(dev, worker);
+ udev_event = udev_event_new(dev, worker, EVENT_UDEV_WORKER);
if (!udev_event)
return -ENOMEM;
diff --git a/src/udev/udevadm-test-builtin.c b/src/udev/udevadm-test-builtin.c
index fdbdb6f59a..8831949717 100644
--- a/src/udev/udevadm-test-builtin.c
+++ b/src/udev/udevadm-test-builtin.c
@@ -100,7 +100,7 @@ int builtin_main(int argc, char *argv[], void *userdata) {
goto finish;
}
- event = udev_event_new(dev, NULL);
+ event = udev_event_new(dev, NULL, EVENT_UDEVADM_TEST_BUILTIN);
if (!event) {
r = log_oom();
goto finish;
@@ -115,7 +115,7 @@ int builtin_main(int argc, char *argv[], void *userdata) {
}
}
- r = udev_builtin_run(event, cmd, arg_command, true);
+ r = udev_builtin_run(event, cmd, arg_command);
if (r < 0) {
log_debug_errno(r, "Builtin command '%s' fails: %m", arg_command);
goto finish;
diff --git a/src/udev/udevadm-test.c b/src/udev/udevadm-test.c
index 6c4a01a30e..b0d2f9b20c 100644
--- a/src/udev/udevadm-test.c
+++ b/src/udev/udevadm-test.c
@@ -16,14 +16,18 @@
#include "device-private.h"
#include "device-util.h"
+#include "format-util.h"
#include "path-util.h"
#include "string-util.h"
+#include "strv.h"
#include "strxcpyx.h"
+#include "terminal-util.h"
#include "udev-builtin.h"
#include "udev-event.h"
#include "udev-format.h"
#include "udevadm-util.h"
#include "udevadm.h"
+#include "user-util.h"
static sd_device_action_t arg_action = SD_DEVICE_ADD;
static ResolveNameTiming arg_resolve_name_timing = RESOLVE_NAME_EARLY;
@@ -89,9 +93,7 @@ int test_main(int argc, char *argv[], void *userdata) {
_cleanup_(udev_rules_freep) UdevRules *rules = NULL;
_cleanup_(udev_event_freep) UdevEvent *event = NULL;
_cleanup_(sd_device_unrefp) sd_device *dev = NULL;
- const char *cmd;
sigset_t mask, sigmask_orig;
- void *val;
int r;
log_set_max_level(LOG_DEBUG);
@@ -125,24 +127,89 @@ int test_main(int argc, char *argv[], void *userdata) {
/* don't read info from the db */
device_seal(dev);
- event = udev_event_new(dev, NULL);
+ event = udev_event_new(dev, NULL, EVENT_UDEVADM_TEST);
assert_se(sigfillset(&mask) >= 0);
assert_se(sigprocmask(SIG_SETMASK, &mask, &sigmask_orig) >= 0);
udev_event_execute_rules(event, rules);
+ printf("%sProperties:%s\n", ansi_highlight(), ansi_normal());
FOREACH_DEVICE_PROPERTY(dev, key, value)
- printf("%s=%s\n", key, value);
+ printf(" %s=%s\n", key, value);
- ORDERED_HASHMAP_FOREACH_KEY(val, cmd, event->run_list) {
- char program[UDEV_PATH_SIZE];
- bool truncated;
+ if (sd_device_get_tag_first(dev)) {
+ printf("%sTags:%s\n", ansi_highlight(), ansi_normal());
+ FOREACH_DEVICE_TAG(dev, tag)
+ printf(" %s\n", tag);
+ }
+
+ if (sd_device_get_devnum(dev, NULL) >= 0) {
+
+ if (sd_device_get_devlink_first(dev)) {
+ int prio;
+ device_get_devlink_priority(dev, &prio);
+ printf("%sDevice node symlinks:%s (priority=%i)\n", ansi_highlight(), ansi_normal(), prio);
+ FOREACH_DEVICE_DEVLINK(dev, devlink)
+ printf(" %s\n", devlink);
+ }
+
+ printf("%sInotify watch:%s\n %s\n", ansi_highlight(), ansi_normal(), enabled_disabled(event->inotify_watch));
+
+ uid_t uid = event->uid;
+ if (!uid_is_valid(uid))
+ (void) device_get_devnode_uid(dev, &uid);
+ if (uid_is_valid(uid)) {
+ _cleanup_free_ char *user = uid_to_name(uid);
+ printf("%sDevice node owner:%s\n %s (uid="UID_FMT")\n", ansi_highlight(), ansi_normal(), strna(user), uid);
+ }
+
+ gid_t gid = event->gid;
+ if (!gid_is_valid(uid))
+ (void) device_get_devnode_gid(dev, &gid);
+ if (gid_is_valid(gid)) {
+ _cleanup_free_ char *group = gid_to_name(gid);
+ printf("%sDevice node group:%s\n %s (gid="GID_FMT")\n", ansi_highlight(), ansi_normal(), strna(group), gid);
+ }
- (void) udev_event_apply_format(event, cmd, program, sizeof(program), false, &truncated);
- if (truncated)
- log_warning("The command '%s' is truncated while substituting into '%s'.", program, cmd);
- printf("run: '%s'\n", program);
+ mode_t mode = event->mode;
+ if (mode == MODE_INVALID)
+ (void) device_get_devnode_mode(dev, &mode);
+ if (mode != MODE_INVALID)
+ printf("%sDevice node permission:%s\n %04o\n", ansi_highlight(), ansi_normal(), mode);
+
+ if (!ordered_hashmap_isempty(event->seclabel_list)) {
+ const char *name, *label;
+ printf("%sDevice node security label:%s\n", ansi_highlight(), ansi_normal());
+ ORDERED_HASHMAP_FOREACH_KEY(label, name, event->seclabel_list)
+ printf(" %s : %s\n", name, label);
+ }
+ }
+
+ if (sd_device_get_ifindex(dev, NULL) >= 0) {
+ if (!isempty(event->name))
+ printf("%sNetwork interface name:%s\n %s\n", ansi_highlight(), ansi_normal(), event->name);
+
+ if (!strv_isempty(event->altnames)) {
+ bool space = true;
+ printf("%sAlternative interface names:%s", ansi_highlight(), ansi_normal());
+ fputstrv(stdout, event->altnames, "\n ", &space);
+ puts("");
+ }
+ }
+
+ if (!ordered_hashmap_isempty(event->run_list)) {
+ void *val;
+ const char *command;
+ printf("%sQueued commands:%s\n", ansi_highlight(), ansi_normal());
+ ORDERED_HASHMAP_FOREACH_KEY(val, command, event->run_list) {
+ UdevBuiltinCommand builtin_cmd = PTR_TO_UDEV_BUILTIN_CMD(val);
+
+ if (builtin_cmd != _UDEV_BUILTIN_INVALID)
+ printf(" RUN{builtin} : %s\n", command);
+ else
+ printf(" RUN{program} : %s\n", command);
+ }
}
r = 0;
diff --git a/src/udev/udevadm-wait.c b/src/udev/udevadm-wait.c
index e6620c25dd..6ffc86bbf1 100644
--- a/src/udev/udevadm-wait.c
+++ b/src/udev/udevadm-wait.c
@@ -67,7 +67,7 @@ static int check_device(const char *path) {
return r;
if (arg_wait_until == WAIT_UNTIL_INITIALIZED)
- return sd_device_get_is_initialized(dev);
+ return device_is_processed(dev);
return true;
}
diff --git a/src/vmspawn/vmspawn.c b/src/vmspawn/vmspawn.c
index 8d2348d748..1828deae2a 100644
--- a/src/vmspawn/vmspawn.c
+++ b/src/vmspawn/vmspawn.c
@@ -505,7 +505,7 @@ static int parse_argv(int argc, char *argv[]) {
}
if (!isempty(optarg) && !path_is_absolute(optarg) && !startswith(optarg, "./"))
- return log_error_errno(SYNTHETIC_ERRNO(errno), "Absolute path or path starting with './' required.");
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Absolute path or path starting with './' required.");
r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_firmware);
if (r < 0)
diff --git a/test/TEST-54-CREDS/test.sh b/test/TEST-54-CREDS/test.sh
index c0a9d7a53d..afcb348166 100755
--- a/test/TEST-54-CREDS/test.sh
+++ b/test/TEST-54-CREDS/test.sh
@@ -9,6 +9,19 @@ NSPAWN_CREDS=(
)
NSPAWN_ARGUMENTS="${NSPAWN_ARGUMENTS:-} ${NSPAWN_CREDS[*]}"
+UNIT_CRED=$(base64 -w 0 <<EOF
+[Service]
+Type=oneshot
+ExecStart=touch /tmp/unit-cred
+EOF
+)
+DROPIN_CRED=$(base64 -w 0 <<EOF
+[Service]
+ExecStart=
+ExecStart=touch /tmp/unit-dropin
+EOF
+)
+
QEMU_CREDS=(
"-fw_cfg name=opt/io.systemd.credentials/myqemucredential,string=othervalue"
"-smbios type=11,value=io.systemd.credential:smbioscredential=magicdata"
@@ -17,6 +30,8 @@ QEMU_CREDS=(
"-smbios type=11,value=io.systemd.credential.binary:tmpfiles.extra=ZiAvdG1wL3NvdXJjZWRmcm9tY3JlZGVudGlhbCAtIC0gLSAtIHRtcGZpbGVzc2VjcmV0Cg=="
"-smbios type=11,value=io.systemd.credential.binary:fstab.extra=aW5qZWN0ZWQgL2luamVjdGVkIHRtcGZzIFgtbW91bnQubWtkaXIgMCAwCg=="
"-smbios type=11,value=io.systemd.credential:getty.ttys.container=idontexist"
+ "-smbios type=11,value=io.systemd.credential.binary:systemd.extra-unit.my-service.service=$UNIT_CRED"
+ "-smbios type=11,value=io.systemd.credential.binary:systemd.unit-dropin.my-service.service=$DROPIN_CRED"
)
QEMU_OPTIONS="${QEMU_OPTIONS:-} ${QEMU_CREDS[*]}"
diff --git a/test/test-functions b/test/test-functions
index 0c0ffa1545..5d63a41d80 100644
--- a/test/test-functions
+++ b/test/test-functions
@@ -1494,7 +1494,7 @@ install_systemd() {
# units using DynamicUser=yes. Do this only for services with test- prefix and a couple of
# known-to-use DynamicUser=yes services, as setting this system-wide has many undesirable
# side-effects, as it creates its own namespace.
- for service in test- systemd-journal-{gatewayd,upload}; do
+ for service in capsule@ test- systemd-journal-{gatewayd,upload}; do
mkdir -p "$initdir/etc/systemd/system/$service.service.d/"
echo -ne "[Service]\nReadWritePaths=${BUILD_DIR:?}\n" >"$initdir/etc/systemd/system/$service.service.d/99-gcov-rwpaths-override.conf"
done
@@ -1555,7 +1555,7 @@ install_missing_libraries() {
local lib path
# A number of dependencies is now optional via dlopen, so the install
# script will not pick them up, since it looks at linkage.
- for lib in libcryptsetup libidn libidn2 pwquality libqrencode tss2-esys tss2-rc tss2-mu tss2-tcti-device libfido2 libbpf libelf libdw xkbcommon p11-kit-1 libarchive; do
+ for lib in libcryptsetup libidn libidn2 pwquality libqrencode tss2-esys tss2-rc tss2-mu tss2-tcti-device libfido2 libbpf libelf libdw xkbcommon p11-kit-1 libarchive libgcrypt; do
ddebug "Searching for $lib via pkg-config"
if pkg-config --exists "$lib"; then
path="$(pkg-config --variable=libdir "$lib")"
diff --git a/test/test-network-generator-conversion.sh b/test/test-network-generator-conversion.sh
index 0a5fa4d22e..12254acdab 100755
--- a/test/test-network-generator-conversion.sh
+++ b/test/test-network-generator-conversion.sh
@@ -49,7 +49,7 @@ run_network_generator() {
rm -rf "${WORK_DIR:?}"/*
stderr="$WORK_DIR/stderr"
- if ! "$GENERATOR_BIN" --root "$WORK_DIR" 2>"$stderr"; then
+ if ! SYSTEMD_LOG_LEVEL="info" "$GENERATOR_BIN" --root "$WORK_DIR" 2>"$stderr"; then
echo >&2 "Generator failed when parsing $SYSTEMD_PROC_CMDLINE"
cat >&2 "$stderr"
return 1
diff --git a/test/test-network/conf/25-dhcp-server-veth-peer.network b/test/test-network/conf/25-dhcp-server-veth-peer.network
index d5cc6d3334..abe3fa2596 100644
--- a/test/test-network/conf/25-dhcp-server-veth-peer.network
+++ b/test/test-network/conf/25-dhcp-server-veth-peer.network
@@ -6,3 +6,5 @@ Name=veth-peer
IPv6AcceptRA=no
Address=2600::1/0
Address=192.168.5.1/24
+# To make the kernel send NA with IsRouter flag.
+IPv6Forwarding=yes
diff --git a/test/units/end.sh b/test/units/end.sh
index 4c6c0afa0e..5e2943758a 100755
--- a/test/units/end.sh
+++ b/test/units/end.sh
@@ -9,5 +9,9 @@ set -o pipefail
# Here, the redundant '[ ]' in the pattern is required in order not to match the logged command itself.
(! journalctl -q -o short-monotonic --grep 'Warning: cannot close sd-bus connection[ ].*after fork' >>/failed)
+# Check if sd-executor doesn't complain about not being able to (de)serialize stuff
+(! journalctl -q -o short-monotonic --grep "[F]ailed to parse serialized line" >>/failed)
+(! journalctl -q -o short-monotonic --grep "[F]ailed to (de)?serialize \w+" >>/failed)
+
systemctl poweroff --no-block
exit 0
diff --git a/test/units/testsuite-08.sh b/test/units/testsuite-08.sh
index 5c6b4cee79..58d9bea195 100755
--- a/test/units/testsuite-08.sh
+++ b/test/units/testsuite-08.sh
@@ -13,7 +13,7 @@ fi
if [[ "$(systemctl show -P InitRDTimestampMonotonic)" -eq 0 ]]; then
echo "systemd didn't run in the initrd, skipping the test"
touch /skipped
- exit 0
+ exit 77
fi
# We should've created a mount under /run in initrd (see the other half of the test)
diff --git a/test/units/testsuite-17.link-property.sh b/test/units/testsuite-17.link-property.sh
index a43ad22b43..517cc3f7d2 100755
--- a/test/units/testsuite-17.link-property.sh
+++ b/test/units/testsuite-17.link-property.sh
@@ -122,12 +122,12 @@ assert_in "ID_NET_LINK_FILE=/run/systemd/network/10-test.link" "$output"
assert_in "ID_NET_LINK_FILE_DROPINS=/run/systemd/network/10-test.link.d/10-override.conf:/run/systemd/network/10-test.link.d/11-override.conf" "$output"
assert_in "ID_NET_NAME=test1" "$output"
-# check that test command _does_ update udev database.
+# check that test command does not update udev database.
output=$(udevadm info --query property /sys/class/net/test1)
assert_not_in "HOGE=" "$output"
-assert_in "HOGE2=foo2" "$output"
+assert_not_in "HOGE2=" "$output"
assert_not_in "BAR=" "$output"
-assert_in "BAR2=baz2" "$output"
+assert_not_in "BAR2=" "$output"
assert_not_in "SHOULD_BE_UNSET=" "$output"
assert_in "ID_NET_LINK_FILE=/run/systemd/network/10-test.link" "$output"
assert_in "ID_NET_LINK_FILE_DROPINS=/run/systemd/network/10-test.link.d/10-override.conf:/run/systemd/network/10-test.link.d/11-override.conf" "$output"
@@ -165,6 +165,7 @@ udevadm control --reload
output=$(udevadm test --action add /sys/class/net/test1)
assert_in "LINK_VERSION=$(uname -r)" "$output"
+udevadm trigger --settle --action add /sys/class/net/test1
output=$(udevadm info --query property /sys/class/net/test1)
assert_in "LINK_VERSION=$(uname -r)" "$output"
@@ -185,6 +186,7 @@ assert_in "IFINDEX=" "$output"
assert_not_in "IFINDEX=bar" "$output"
assert_in "DEVPATH=" "$output"
+udevadm trigger --settle --action add /sys/class/net/test1
output=$(udevadm info --query property /sys/class/net/test1)
assert_not_in "ACTION=foo" "$output"
assert_in "IFINDEX=" "$output"
diff --git a/test/units/testsuite-43.sh b/test/units/testsuite-43.sh
index 4f31a33c34..c120468593 100755
--- a/test/units/testsuite-43.sh
+++ b/test/units/testsuite-43.sh
@@ -8,7 +8,7 @@ set -o pipefail
if [[ "$(sysctl -ne kernel.apparmor_restrict_unprivileged_userns)" -eq 1 ]]; then
echo "Cannot create unprivileged user namespaces" >/skipped
- exit 0
+ exit 77
fi
systemd-analyze log-level debug
diff --git a/test/units/testsuite-46.sh b/test/units/testsuite-46.sh
index 7a2bee8179..d9ba83aa82 100755
--- a/test/units/testsuite-46.sh
+++ b/test/units/testsuite-46.sh
@@ -6,7 +6,7 @@ set -o pipefail
# Check if homectl is installed, and if it isn't bail out early instead of failing
if ! test -x /usr/bin/homectl ; then
echo "no homed" >/skipped
- exit 0
+ exit 77
fi
inspect() {
diff --git a/test/units/testsuite-50.sh b/test/units/testsuite-50.sh
index 7c4a9db96d..cd2d6aa7f7 100755
--- a/test/units/testsuite-50.sh
+++ b/test/units/testsuite-50.sh
@@ -152,16 +152,16 @@ elif [ "${machine}" = "arm" ]; then
verity_guid=7386cdf2-203c-47a9-a498-f2ecce45a2d6
signature_guid=42b0455f-eb11-491d-98d3-56145ba9d037
architecture="arm"
-elif [ "${machine}" = "loongarch64" ]; then
- root_guid=77055800-792c-4f94-b39a-98c91b762bb6
- verity_guid=f3393b22-e9af-4613-a948-9d3bfbd0c535
- signature_guid=5afb67eb-ecc8-4f85-ae8e-ac1e7c50e7d0
- architecture="loongarch64"
elif [ "${machine}" = "ia64" ]; then
root_guid=993d8d3d-f80e-4225-855a-9daf8ed7ea97
verity_guid=86ed10d5-b607-45bb-8957-d350f23d0571
signature_guid=e98b36ee-32ba-4882-9b12-0ce14655f46a
architecture="ia64"
+elif [ "${machine}" = "loongarch64" ]; then
+ root_guid=77055800-792c-4f94-b39a-98c91b762bb6
+ verity_guid=f3393b22-e9af-4613-a948-9d3bfbd0c535
+ signature_guid=5afb67eb-ecc8-4f85-ae8e-ac1e7c50e7d0
+ architecture="loongarch64"
elif [ "${machine}" = "s390x" ]; then
root_guid=5eead9a9-fe09-4a1e-a1d7-520d00531306
verity_guid=b325bfbe-c7be-4ab8-8357-139e652d2f6b
@@ -172,6 +172,16 @@ elif [ "${machine}" = "ppc64le" ]; then
verity_guid=906bd944-4589-4aae-a4e4-dd983917446a
signature_guid=d4a236e7-e873-4c07-bf1d-bf6cf7f1c3c6
architecture="ppc64-le"
+elif [ "${machine}" = "riscv64" ]; then
+ root_guid=72ec70a6-cf74-40e6-bd49-4bda08e8f224
+ verity_guid=b6ed5582-440b-4209-b8da-5ff7c419ea3d
+ signature_guid=efe0f087-ea8d-4469-821a-4c2a96a8386a
+ architecture="riscv64"
+elif [ "${machine}" = "riscv32" ]; then
+ root_guid=60d5a7fe-8e7d-435c-b714-3dd8162144e1
+ verity_guid=ae0253be-1167-4007-ac68-43926c14c5de
+ signature_guid=3a112a75-8729-4380-b4cf-764d79934448
+ architecture="riscv32"
else
echo "Unexpected uname -m: ${machine} in testsuite-50.sh, please fix me"
exit 1
diff --git a/test/units/testsuite-54.sh b/test/units/testsuite-54.sh
index 7618e92c9f..a8d5a0c3fa 100755
--- a/test/units/testsuite-54.sh
+++ b/test/units/testsuite-54.sh
@@ -8,13 +8,20 @@ set -eux
systemd-analyze log-level debug
-run_with_cred_compare() {
+run_with_cred_compare() (
local cred="${1:?}"
local exp="${2?}"
+ local log_file
shift 2
- diff <(systemd-run -p SetCredential="$cred" --wait --pipe -- systemd-creds "$@") <(echo -ne "$exp")
-}
+ log_file="$(mktemp)"
+ # shellcheck disable=SC2064
+ trap "rm -f '$log_file'" RETURN
+
+ set -o pipefail
+ systemd-run -p SetCredential="$cred" --wait --pipe -- systemd-creds "$@" | tee "$log_file"
+ diff "$log_file" <(echo -ne "$exp")
+)
# Sanity checks
#
@@ -200,6 +207,10 @@ elif [ -d /sys/firmware/qemu_fw_cfg/by_name ]; then
[ "$(cat /tmp/sourcedfromcredential)" = "tmpfilessecret" ]
[ "$(cat /etc/motd.d/50-provision.conf)" = "hello" ]
[ "$(cat /etc/issue.d/50-provision.conf)" = "welcome" ]
+
+ # Verify that adding a unit and drop-in via credentials worked
+ systemctl start my-service
+ test -f /tmp/unit-dropin
else
echo "qemu_fw_cfg support missing in kernel. Sniff!"
expected_credential=""
diff --git a/test/units/testsuite-55.sh b/test/units/testsuite-55.sh
index 3e549dd7db..e5d930175f 100755
--- a/test/units/testsuite-55.sh
+++ b/test/units/testsuite-55.sh
@@ -16,7 +16,7 @@ test "$(cat /sys/fs/cgroup/init.scope/memory.high)" != "max"
[[ "$(get_cgroup_hierarchy)" == "unified" ]] || echo "no cgroupsv2" >>/skipped
[[ -x /usr/lib/systemd/systemd-oomd ]] || echo "no oomd" >>/skipped
if [[ -s /skipped ]]; then
- exit 0
+ exit 77
fi
rm -rf /run/systemd/system/testsuite-55-testbloat.service.d
diff --git a/test/units/testsuite-58.sh b/test/units/testsuite-58.sh
index c64b2039f3..bebe7b727b 100755
--- a/test/units/testsuite-58.sh
+++ b/test/units/testsuite-58.sh
@@ -9,7 +9,7 @@ set -o pipefail
if ! command -v systemd-repart >/dev/null; then
echo "no systemd-repart" >/skipped
- exit 0
+ exit 77
fi
# shellcheck source=test/units/test-control.sh
diff --git a/test/units/testsuite-59.sh b/test/units/testsuite-59.sh
index 61564dc166..0e044037b8 100755
--- a/test/units/testsuite-59.sh
+++ b/test/units/testsuite-59.sh
@@ -104,6 +104,14 @@ sleep 10
systemctl daemon-reload
+# Same test for reexec, but we wait here
+timeout 15 bash -c 'while systemctl daemon-reexec; do true; done'
+
+# Rate limit should reset after 9s
+sleep 10
+
+systemctl daemon-reexec
+
# Let's now test the notify-reload logic
cat >/run/notify-reload-test.sh <<EOF
diff --git a/test/units/testsuite-62.sh b/test/units/testsuite-62.sh
index 0dbedc4c86..84c92247b8 100755
--- a/test/units/testsuite-62.sh
+++ b/test/units/testsuite-62.sh
@@ -44,12 +44,12 @@ MINOR_REQUIRED=7
if [[ "$KERNEL_MAJOR" -lt $MAJOR_REQUIRED || ("$KERNEL_MAJOR" -eq $MAJOR_REQUIRED && "$KERNEL_MINOR" -lt $MINOR_REQUIRED) ]]; then
echo "kernel is not 5.7+" >>/skipped
- exit 0
+ exit 77
fi
if systemctl --version | grep -q -F -- "-BPF_FRAMEWORK"; then
echo "bpf-framework is disabled" >>/skipped
- exit 0
+ exit 77
fi
trap teardown EXIT
diff --git a/test/units/testsuite-72.sh b/test/units/testsuite-72.sh
index 587eb69540..5e658e0485 100755
--- a/test/units/testsuite-72.sh
+++ b/test/units/testsuite-72.sh
@@ -16,7 +16,7 @@ export SYSTEMD_LOG_LEVEL=debug
if [[ ! -x "$SYSUPDATE" ]]; then
echo "no systemd-sysupdate" >/skipped
- exit 0
+ exit 77
fi
# Loopback devices may not be supported. They are used because sfdisk cannot
diff --git a/test/units/testsuite-74.coredump.sh b/test/units/testsuite-74.coredump.sh
index 6552643ee9..f48607c0db 100755
--- a/test/units/testsuite-74.coredump.sh
+++ b/test/units/testsuite-74.coredump.sh
@@ -77,24 +77,26 @@ rm -fv /run/systemd/coredump.conf.d/99-external.conf
# Wait a bit for the coredumps to get processed
timeout 30 bash -c "while [[ \$(coredumpctl list -q --no-legend $CORE_TEST_BIN | wc -l) -lt 4 ]]; do sleep 1; done"
-# Make sure we can forward crashes back to containers
-CONTAINER="testsuite-74-container"
-
-mkdir -p "/var/lib/machines/$CONTAINER"
-mkdir -p "/run/systemd/system/systemd-nspawn@$CONTAINER.service.d"
-# Bind-mounting /etc into the container kinda defeats the purpose of --volatile=,
-# but we need the ASan-related overrides scattered across /etc
-cat > "/run/systemd/system/systemd-nspawn@$CONTAINER.service.d/override.conf" << EOF
+if cgroupfs_supports_user_xattrs; then
+ # Make sure we can forward crashes back to containers
+ CONTAINER="testsuite-74-container"
+
+ mkdir -p "/var/lib/machines/$CONTAINER"
+ mkdir -p "/run/systemd/system/systemd-nspawn@$CONTAINER.service.d"
+ # Bind-mounting /etc into the container kinda defeats the purpose of --volatile=,
+ # but we need the ASan-related overrides scattered across /etc
+ cat > "/run/systemd/system/systemd-nspawn@$CONTAINER.service.d/override.conf" <<EOF
[Service]
ExecStart=
ExecStart=systemd-nspawn --quiet --link-journal=try-guest --keep-unit --machine=%i --boot \
--volatile=yes --directory=/ --bind-ro=/etc --inaccessible=/etc/machine-id
EOF
-systemctl daemon-reload
+ systemctl daemon-reload
+
+ [[ "$(systemd-detect-virt)" == "qemu" ]] && TIMEOUT=120 || TIMEOUT=60
-if cgroupfs_supports_user_xattrs; then
machinectl start "$CONTAINER"
- timeout 60 bash -xec "until systemd-run -M '$CONTAINER' -q --wait --pipe true; do sleep .5; done"
+ timeout "$TIMEOUT" bash -xec "until systemd-run -M '$CONTAINER' -q --wait --pipe true; do sleep .5; done"
[[ "$(systemd-run -M "$CONTAINER" -q --wait --pipe coredumpctl list -q --no-legend /usr/bin/sleep | wc -l)" -eq 0 ]]
machinectl copy-to "$CONTAINER" "$MAKE_DUMP_SCRIPT"
@@ -102,6 +104,8 @@ if cgroupfs_supports_user_xattrs; then
systemd-run -M "$CONTAINER" -q --wait --pipe "$MAKE_DUMP_SCRIPT" "/usr/bin/sleep" "SIGTRAP"
# Wait a bit for the coredumps to get processed
timeout 30 bash -c "while [[ \$(systemd-run -M $CONTAINER -q --wait --pipe coredumpctl list -q --no-legend /usr/bin/sleep | wc -l) -lt 2 ]]; do sleep 1; done"
+
+ rm -rf "/var/lib/machines/$CONTAINER"
fi
coredumpctl
diff --git a/tmpfiles.d/20-systemd-ssh-generator.conf.in b/tmpfiles.d/20-systemd-ssh-generator.conf.in
index 033379ec7a..6d1a6a3e31 100644
--- a/tmpfiles.d/20-systemd-ssh-generator.conf.in
+++ b/tmpfiles.d/20-systemd-ssh-generator.conf.in
@@ -8,3 +8,6 @@
# See tmpfiles.d(5) for details
L {{SSHCONFDIR}}/20-systemd-ssh-proxy.conf - - - - {{LIBEXECDIR}}/ssh_config.d/20-systemd-ssh-proxy.conf
+{% if CREATE_SSHDPRIVSEPDIR %}
+d {{SSHDPRIVSEPDIR}} 0755
+{% endif %}
diff --git a/tools/git-contrib.sh b/tools/git-contrib.sh
index 6371d49331..2cbcf6ca44 100755
--- a/tools/git-contrib.sh
+++ b/tools/git-contrib.sh
@@ -3,13 +3,7 @@
set -eu
tag="$(git describe --abbrev=0 --match 'v[0-9][0-9][0-9]')"
-(
- # authors
- git log --pretty=tformat:%aN -s "${tag}.."
- # Co-authors (drop empty line and mail addresses)
- git log --pretty='tformat:%(trailers:key=Co-authored-by,valueonly)' -s "${tag}.." | sed -e '/^[[:space:]]*$/ d' | sed -e 's/ <.*@.*>$//'
-) |
- grep -v noreply@weblate.org |
- sed 's/ / /g; s/--/-/g; s/.*/\0,/' |
- sort -u | tr '\n' ' ' | sed -e "s/^/Contributions from: /g" -e "s/,\s*$/\n/g" | fold -w 72 -s |
+git shortlog -s --group=author --group=trailer:Co-authored-by "${tag}.." |
+ sed -e 's/^[[:space:]]*[0-9]*[[:space:]]*//; /Weblate/ d; /dependabot\[bot\]/ d; s/ / /g; s/--/-/g; s/.*/\0,/' |
+ tr '\n' ' ' | sed -e "s/^/Contributions from: /g" -e "s/,\s*$/\n/g" | fold -w 72 -s |
sed -e "s/^/ /g" -e "s/\s*$//g"
diff --git a/units/meson.build b/units/meson.build
index 6fecbea0a1..16a5564086 100644
--- a/units/meson.build
+++ b/units/meson.build
@@ -313,6 +313,11 @@ units = [
{ 'file' : 'systemd-growfs@.service.in' },
{ 'file' : 'systemd-halt.service' },
{
+ 'file' : 'systemd-hibernate-clear.service.in',
+ 'conditions' : ['ENABLE_HIBERNATE', 'ENABLE_EFI'],
+ 'symlinks' : ['sysinit.target.wants/'],
+ },
+ {
'file' : 'systemd-hibernate-resume.service.in',
'conditions' : ['ENABLE_HIBERNATE'],
},
diff --git a/units/systemd-hibernate-clear.service.in b/units/systemd-hibernate-clear.service.in
new file mode 100644
index 0000000000..2e8587e692
--- /dev/null
+++ b/units/systemd-hibernate-clear.service.in
@@ -0,0 +1,24 @@
+# SPDX-License-Identifier: LGPL-2.1-or-later
+#
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+
+[Unit]
+Description=Clear Stale Hibernate Storage Info
+Documentation=man:systemd-hibernate-clear.service(8)
+
+ConditionPathExists=/sys/firmware/efi/efivars/HibernateLocation-8cf2644b-4b0b-428f-9387-6d876050dc67
+ConditionPathExists=!/etc/initrd-release
+
+DefaultDependencies=no
+Before=sysinit.target shutdown.target
+Conflicts=shutdown.target
+
+[Service]
+Type=oneshot
+RemainAfterExit=yes
+ExecStart={{LIBEXECDIR}}/systemd-hibernate-resume --clear
diff --git a/units/systemd-networkd-persistent-storage.service b/units/systemd-networkd-persistent-storage.service
index c151d36285..5db2936547 100644
--- a/units/systemd-networkd-persistent-storage.service
+++ b/units/systemd-networkd-persistent-storage.service
@@ -15,7 +15,6 @@ DefaultDependencies=no
After=systemd-remount-fs.service systemd-networkd.service
BindsTo=systemd-networkd.service
Conflicts=shutdown.target
-RequiresMountsFor=/var/lib/systemd/network
ConditionPathExists=!/etc/initrd-release
[Service]