summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/analyze/analyze-security.c23
-rw-r--r--src/analyze/analyze.c3
-rw-r--r--src/basic/alloc-util.h49
-rw-r--r--src/basic/btrfs-util.c2
-rw-r--r--src/basic/btrfs-util.h16
-rw-r--r--src/basic/build.h2
-rw-r--r--src/basic/capability-util.c1
-rw-r--r--src/basic/cgroup-util.c12
-rw-r--r--src/basic/cgroup-util.h12
-rw-r--r--src/basic/copy.c28
-rw-r--r--src/basic/copy.h9
-rw-r--r--src/basic/env-file.c32
-rw-r--r--src/basic/env-util.c2
-rw-r--r--src/basic/env-util.h6
-rw-r--r--src/basic/extract-word.h12
-rw-r--r--src/basic/fd-util.c39
-rw-r--r--src/basic/fd-util.h2
-rw-r--r--src/basic/hashmap.c10
-rw-r--r--src/basic/hashmap.h1
-rw-r--r--src/basic/in-addr-util.c37
-rw-r--r--src/basic/in-addr-util.h22
-rw-r--r--src/basic/io-util.c10
-rw-r--r--src/basic/io-util.h2
-rw-r--r--src/basic/meson.build3
-rw-r--r--src/basic/missing_if_link.h3
-rw-r--r--src/basic/missing_syscall.h1
-rw-r--r--src/basic/path-util.h2
-rw-r--r--src/basic/prioq.c7
-rw-r--r--src/basic/prioq.h8
-rw-r--r--src/basic/process-util.c91
-rw-r--r--src/basic/process-util.h4
-rw-r--r--src/basic/procfs-util.c9
-rw-r--r--src/basic/procfs-util.h5
-rw-r--r--src/basic/siphash24.c8
-rw-r--r--src/basic/siphash24.h6
-rw-r--r--src/basic/stat-util.c16
-rw-r--r--src/basic/stat-util.h5
-rw-r--r--src/basic/string-util.c2
-rw-r--r--src/basic/string-util.h3
-rw-r--r--src/basic/strv.h15
-rw-r--r--src/basic/time-util.c1
-rw-r--r--src/basic/tmpfile-util.c1
-rw-r--r--src/basic/unit-name.h10
-rw-r--r--src/basic/user-util.c7
-rw-r--r--src/basic/util.c2
-rw-r--r--src/basic/util.h9
-rw-r--r--src/boot/efi/boot.c10
-rw-r--r--src/boot/efi/disk.c2
-rw-r--r--src/boot/efi/disk.h2
-rw-r--r--src/boot/efi/linux.c4
-rw-r--r--src/boot/efi/meson.build8
-rw-r--r--src/boot/efi/stub.c4
-rw-r--r--src/busctl/busctl.c2
-rw-r--r--src/cgtop/cgtop.c4
-rw-r--r--src/core/automount.c7
-rw-r--r--src/core/bpf-devices.c1
-rw-r--r--src/core/cgroup.c55
-rw-r--r--src/core/dbus-manager.c2
-rw-r--r--src/core/dbus-service.c38
-rw-r--r--src/core/dbus-socket.c4
-rw-r--r--src/core/dbus-unit.c4
-rw-r--r--src/core/dbus.c9
-rw-r--r--src/core/device.c2
-rw-r--r--src/core/dynamic-user.c2
-rw-r--r--src/core/execute.c55
-rw-r--r--src/core/job.c11
-rw-r--r--src/core/load-fragment.c8
-rw-r--r--src/core/locale-setup.c4
-rw-r--r--src/core/macros.systemd.in22
-rw-r--r--src/core/main.c77
-rw-r--r--src/core/manager.c2
-rw-r--r--src/core/meson.build21
-rw-r--r--src/core/mount.c77
-rw-r--r--src/core/namespace.c2
-rw-r--r--src/core/namespace.h2
-rw-r--r--src/core/service.c2
-rw-r--r--src/core/socket.c69
-rw-r--r--src/core/systemd.pc.in4
-rw-r--r--src/core/transaction.c26
-rw-r--r--src/core/unit-printf.c1
-rw-r--r--src/core/unit.h4
-rw-r--r--src/coredump/coredump.c44
-rw-r--r--src/cryptsetup/cryptsetup.c88
-rw-r--r--src/fsck/fsck.c2
-rw-r--r--src/import/curl-util.c5
-rw-r--r--src/import/pull-job.c2
-rw-r--r--src/initctl/initctl.c8
-rw-r--r--src/journal-remote/journal-gatewayd.c53
-rw-r--r--src/journal-remote/journal-remote-main.c39
-rw-r--r--src/journal-remote/journal-remote.c3
-rw-r--r--src/journal-remote/journal-upload-journal.c2
-rw-r--r--src/journal-remote/journal-upload.c3
-rw-r--r--src/journal-remote/microhttpd-util.c13
-rw-r--r--src/journal-remote/microhttpd-util.h1
-rw-r--r--src/journal/audit-type.h3
-rw-r--r--src/journal/cat.c50
-rw-r--r--src/journal/catalog.c48
-rw-r--r--src/journal/journal-def.h118
-rw-r--r--src/journal/journal-send.c4
-rw-r--r--src/journal/journald-audit.c2
-rw-r--r--src/journal/journald-context.c72
-rw-r--r--src/journal/journald-native.c74
-rw-r--r--src/journal/journald-server.c29
-rw-r--r--src/journal/journald-server.h2
-rw-r--r--src/journal/journald-wall.h1
-rw-r--r--src/journal/mmap-cache.c2
-rw-r--r--src/journal/sd-journal.c1
-rw-r--r--src/kernel-install/90-loaderentry.install25
-rw-r--r--src/kernel-install/kernel-install7
-rw-r--r--src/libsystemd-network/dhcp-identifier.c7
-rw-r--r--src/libsystemd-network/lldp-neighbor.c4
-rw-r--r--src/libsystemd-network/network-internal.c2
-rw-r--r--src/libsystemd-network/radv-internal.h35
-rw-r--r--src/libsystemd-network/sd-dhcp-client.c35
-rw-r--r--src/libsystemd-network/sd-ndisc.c1
-rw-r--r--src/libsystemd-network/test-lldp.c4
-rw-r--r--src/libsystemd/libsystemd.pc.in4
-rw-r--r--src/libsystemd/libsystemd.sym5
-rw-r--r--src/libsystemd/meson.build7
-rw-r--r--src/libsystemd/sd-bus/bus-dump.h4
-rw-r--r--src/libsystemd/sd-bus/bus-match.c4
-rw-r--r--src/libsystemd/sd-bus/bus-objects.c12
-rw-r--r--src/libsystemd/sd-bus/bus-protocol.h12
-rw-r--r--src/libsystemd/sd-bus/bus-socket.c11
-rw-r--r--src/libsystemd/sd-bus/sd-bus.c13
-rw-r--r--src/libsystemd/sd-daemon/sd-daemon.c8
-rw-r--r--src/libsystemd/sd-device/device-monitor.c12
-rw-r--r--src/libsystemd/sd-device/device-private.c24
-rw-r--r--src/libsystemd/sd-device/device-private.h1
-rw-r--r--src/libsystemd/sd-device/sd-device.c76
-rw-r--r--src/libsystemd/sd-device/test-sd-device-monitor.c127
-rw-r--r--src/libsystemd/sd-event/sd-event.c23
-rw-r--r--src/libsystemd/sd-hwdb/hwdb-util.c2
-rw-r--r--src/libsystemd/sd-hwdb/sd-hwdb.c2
-rw-r--r--src/libsystemd/sd-id128/sd-id128.c2
-rw-r--r--src/libsystemd/sd-login/sd-login.c4
-rw-r--r--src/libsystemd/sd-netlink/netlink-message.c36
-rw-r--r--src/libsystemd/sd-netlink/netlink-types.c4
-rw-r--r--src/libsystemd/sd-netlink/netlink-types.h1
-rw-r--r--src/libsystemd/sd-network/sd-network.c4
-rw-r--r--src/libsystemd/sd-resolve/sd-resolve.c1
-rw-r--r--src/libudev/libudev-list.c2
-rw-r--r--src/libudev/libudev-util.c13
-rw-r--r--src/libudev/libudev.pc.in2
-rw-r--r--src/libudev/meson.build7
-rw-r--r--src/login/logind-action.c2
-rw-r--r--src/login/logind-dbus.c27
-rw-r--r--src/login/logind-inhibit.h18
-rw-r--r--src/login/logind-seat.c2
-rw-r--r--src/login/logind-session.c58
-rw-r--r--src/login/logind.c2
-rw-r--r--src/login/pam_systemd.c56
-rw-r--r--src/login/user-runtime-dir.c2
-rw-r--r--src/machine/machine-dbus.c2
-rw-r--r--src/machine/machinectl.c9
-rw-r--r--src/machine/machined.c2
-rw-r--r--src/network/netdev/bridge.c2
-rw-r--r--src/network/netdev/netdev.c11
-rw-r--r--src/network/netdev/netdev.h1
-rw-r--r--src/network/netdev/wireguard.c233
-rw-r--r--src/network/networkd-address.c53
-rw-r--r--src/network/networkd-brvlan.c3
-rw-r--r--src/network/networkd-dhcp4.c2
-rw-r--r--src/network/networkd-dhcp6.c2
-rw-r--r--src/network/networkd-link.c291
-rw-r--r--src/network/networkd-link.h2
-rw-r--r--src/network/networkd-manager.c2
-rw-r--r--src/network/networkd-ndisc.c1
-rw-r--r--src/network/networkd-network.c50
-rw-r--r--src/network/wait-online/manager.c31
-rw-r--r--src/nspawn/nspawn-network.c2
-rw-r--r--src/nspawn/nspawn.c11
-rw-r--r--src/nss-myhostname/nss-myhostname.c13
-rw-r--r--src/nss-mymachines/nss-mymachines.c13
-rw-r--r--src/nss-resolve/nss-resolve.c8
-rw-r--r--src/nss-systemd/nss-systemd.c10
-rw-r--r--src/portable/portabled.c2
-rw-r--r--src/resolve/resolved-dns-answer.h10
-rw-r--r--src/resolve/resolved-dns-dnssec.c2
-rw-r--r--src/resolve/resolved-dns-query.c2
-rw-r--r--src/resolve/resolved-dns-scope.c30
-rw-r--r--src/resolve/resolved-etc-hosts.c4
-rw-r--r--src/resolve/resolved-manager.c2
-rw-r--r--src/resolve/resolved.c4
-rw-r--r--src/shared/acl-util.c8
-rw-r--r--src/shared/ask-password-api.c4
-rw-r--r--src/shared/ask-password-api.h1
-rw-r--r--src/shared/bus-unit-util.c2
-rw-r--r--src/shared/bus-util.c8
-rw-r--r--src/shared/conf-parser.c4
-rw-r--r--src/shared/dissect-image.c4
-rw-r--r--src/shared/efivars.c134
-rw-r--r--src/shared/install.c6
-rw-r--r--src/shared/journal-importer.c5
-rw-r--r--src/shared/journal-importer.h3
-rw-r--r--src/shared/json.c7
-rw-r--r--src/shared/json.h3
-rw-r--r--src/shared/lockfile-util.c1
-rw-r--r--src/shared/logs-show.c4
-rw-r--r--src/shared/loop-util.c7
-rw-r--r--src/shared/pager.c4
-rw-r--r--src/shared/seccomp-util.c1
-rw-r--r--src/shared/switch-root.c2
-rw-r--r--src/shared/xml.c2
-rw-r--r--src/sleep/sleep.conf25
-rw-r--r--src/socket-proxy/socket-proxyd.c2
-rw-r--r--src/stdio-bridge/stdio-bridge.c2
-rw-r--r--src/systemctl/systemctl.c4
-rw-r--r--src/systemd/_sd-common.h8
-rw-r--r--src/systemd/meson.build3
-rw-r--r--src/systemd/sd-bus.h2
-rw-r--r--src/systemd/sd-id128.h2
-rw-r--r--src/systemd/sd-lldp.h20
-rw-r--r--src/systemd/sd-netlink.h3
-rw-r--r--src/test/meson.build5
-rw-r--r--src/test/test-barrier.c17
-rw-r--r--src/test/test-bpf.c36
-rw-r--r--src/test/test-capability.c1
-rw-r--r--src/test/test-conf-parser.c22
-rw-r--r--src/test/test-execute.c4
-rw-r--r--src/test/test-fileio.c34
-rw-r--r--src/test/test-fs-util.c6
-rw-r--r--src/test/test-hexdecoct.c1
-rw-r--r--src/test/test-in-addr-util.c122
-rw-r--r--src/test/test-json.c23
-rw-r--r--src/test/test-libudev.c30
-rw-r--r--src/test/test-mountpoint-util.c1
-rw-r--r--src/test/test-path-util.c2
-rw-r--r--src/test/test-prioq.c16
-rw-r--r--src/test/test-process-util.c2
-rw-r--r--src/test/test-procfs-util.c2
-rw-r--r--src/test/test-sizeof.c11
-rw-r--r--src/test/test-stat-util.c1
-rw-r--r--src/test/test-time-util.c2
-rw-r--r--src/test/test-udev.c3
-rw-r--r--src/test/test-util.c29
-rw-r--r--src/timedate/timedated.c15
-rw-r--r--src/timesync/timesyncd-manager.c7
-rw-r--r--src/timesync/timesyncd.c4
-rw-r--r--src/tmpfiles/tmpfiles.c4
-rw-r--r--src/udev/meson.build9
-rw-r--r--src/udev/net/ethtool-util.c12
-rw-r--r--src/udev/net/ethtool-util.h16
-rw-r--r--src/udev/net/link-config.c136
-rw-r--r--src/udev/net/link-config.h1
-rw-r--r--src/udev/net/naming-scheme.c64
-rw-r--r--src/udev/net/naming-scheme.h48
-rw-r--r--src/udev/scsi_id/scsi_id.c3
-rw-r--r--src/udev/udev-builtin-blkid.c2
-rw-r--r--src/udev/udev-builtin-btrfs.c2
-rw-r--r--src/udev/udev-builtin-hwdb.c4
-rw-r--r--src/udev/udev-builtin-input_id.c2
-rw-r--r--src/udev/udev-builtin-keyboard.c6
-rw-r--r--src/udev/udev-builtin-net_id.c103
-rw-r--r--src/udev/udev-builtin-net_setup_link.c2
-rw-r--r--src/udev/udev-builtin-path_id.c1
-rw-r--r--src/udev/udev-builtin.c2
-rw-r--r--src/udev/udev-ctrl.c68
-rw-r--r--src/udev/udev-ctrl.h17
-rw-r--r--src/udev/udev-event.c54
-rw-r--r--src/udev/udev-node.c5
-rw-r--r--src/udev/udev-rules.c226
-rw-r--r--src/udev/udev.pc.in2
-rw-r--r--src/udev/udevadm-control.c79
-rw-r--r--src/udev/udevadm-info.c13
-rw-r--r--src/udev/udevadm-monitor.c10
-rw-r--r--src/udev/udevadm-settle.c10
-rw-r--r--src/udev/udevadm-trigger.c55
-rw-r--r--src/udev/udevadm.c3
-rw-r--r--src/udev/udevadm.h6
-rw-r--r--src/udev/udevd.c169
-rw-r--r--src/version/version.h.in1
272 files changed, 3026 insertions, 2072 deletions
diff --git a/src/analyze/analyze-security.c b/src/analyze/analyze-security.c
index 1fc3c1e02f..a007ed1da4 100644
--- a/src/analyze/analyze-security.c
+++ b/src/analyze/analyze-security.c
@@ -485,24 +485,24 @@ static bool syscall_names_in_filter(Set *s, bool whitelist, const SyscallFilterS
const char *syscall;
NULSTR_FOREACH(syscall, f->value) {
- bool b;
+ int id;
if (syscall[0] == '@') {
const SyscallFilterSet *g;
- assert_se(g = syscall_filter_set_find(syscall));
- b = syscall_names_in_filter(s, whitelist, g);
- } else {
- int id;
- /* Let's see if the system call actually exists on this platform, before complaining */
- id = seccomp_syscall_resolve_name(syscall);
- if (id < 0)
- continue;
+ assert_se(g = syscall_filter_set_find(syscall));
+ if (syscall_names_in_filter(s, whitelist, g))
+ return true; /* bad! */
- b = set_contains(s, syscall);
+ continue;
}
- if (whitelist == b) {
+ /* Let's see if the system call actually exists on this platform, before complaining */
+ id = seccomp_syscall_resolve_name(syscall);
+ if (id < 0)
+ continue;
+
+ if (set_contains(s, syscall) == whitelist) {
log_debug("Offending syscall filter item: %s", syscall);
return true; /* bad! */
}
@@ -1859,7 +1859,6 @@ static int acquire_security_info(sd_bus *bus, const char *name, struct security_
{ "PrivateNetwork", "b", NULL, offsetof(struct security_info, private_network) },
{ "PrivateTmp", "b", NULL, offsetof(struct security_info, private_tmp) },
{ "PrivateUsers", "b", NULL, offsetof(struct security_info, private_users) },
- { "PrivateUsers", "b", NULL, offsetof(struct security_info, private_users) },
{ "ProtectControlGroups", "b", NULL, offsetof(struct security_info, protect_control_groups) },
{ "ProtectHome", "s", NULL, offsetof(struct security_info, protect_home) },
{ "ProtectKernelModules", "b", NULL, offsetof(struct security_info, protect_kernel_modules) },
diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c
index 1f69b9fda1..3915b66739 100644
--- a/src/analyze/analyze.c
+++ b/src/analyze/analyze.c
@@ -14,6 +14,7 @@
#include "alloc-util.h"
#include "analyze-security.h"
#include "analyze-verify.h"
+#include "build.h"
#include "bus-error.h"
#include "bus-unit-util.h"
#include "bus-util.h"
@@ -696,7 +697,7 @@ static int analyze_plot(int argc, char *argv[], void *userdata) {
"<!-- that render these files properly but much slower are ImageMagick, -->\n"
"<!-- gimp, inkscape, etc. To display the files on your system, just -->\n"
"<!-- point your browser to this file. -->\n\n"
- "<!-- This plot was generated by systemd-analyze version %-16.16s -->\n\n", PACKAGE_VERSION);
+ "<!-- This plot was generated by systemd-analyze version %-16.16s -->\n\n", GIT_VERSION);
/* style sheet */
svg("<defs>\n <style type=\"text/css\">\n <![CDATA[\n"
diff --git a/src/basic/alloc-util.h b/src/basic/alloc-util.h
index ff7a46793a..893a1238ff 100644
--- a/src/basic/alloc-util.h
+++ b/src/basic/alloc-util.h
@@ -10,20 +10,28 @@
typedef void (*free_func_t)(void *p);
+/* If for some reason more than 4M are allocated on the stack, let's abort immediately. It's better than
+ * proceeding and smashing the stack limits. Note that by default RLIMIT_STACK is 8M on Linux. */
+#define ALLOCA_MAX (4U*1024U*1024U)
+
#define new(t, n) ((t*) malloc_multiply(sizeof(t), (n)))
#define new0(t, n) ((t*) calloc((n) ?: 1, sizeof(t)))
-#define newa(t, n) \
- ({ \
- assert(!size_multiply_overflow(sizeof(t), n)); \
- (t*) alloca(sizeof(t)*(n)); \
+#define newa(t, n) \
+ ({ \
+ size_t _n_ = n; \
+ assert(!size_multiply_overflow(sizeof(t), _n_)); \
+ assert(sizeof(t)*_n_ <= ALLOCA_MAX); \
+ (t*) alloca(sizeof(t)*_n_); \
})
-#define newa0(t, n) \
- ({ \
- assert(!size_multiply_overflow(sizeof(t), n)); \
- (t*) alloca0(sizeof(t)*(n)); \
+#define newa0(t, n) \
+ ({ \
+ size_t _n_ = n; \
+ assert(!size_multiply_overflow(sizeof(t), _n_)); \
+ assert(sizeof(t)*_n_ <= ALLOCA_MAX); \
+ (t*) alloca0(sizeof(t)*_n_); \
})
#define newdup(t, p, n) ((t*) memdup_multiply(p, sizeof(t), (n)))
@@ -51,16 +59,20 @@ void* memdup_suffix0(const void *p, size_t l) _alloc_(2);
#define memdupa(p, l) \
({ \
void *_q_; \
- _q_ = alloca(l); \
- memcpy(_q_, p, l); \
+ size_t _l_ = l; \
+ assert(_l_ <= ALLOCA_MAX); \
+ _q_ = alloca(_l_); \
+ memcpy(_q_, p, _l_); \
})
#define memdupa_suffix0(p, l) \
({ \
void *_q_; \
- _q_ = alloca(l + 1); \
- ((uint8_t*) _q_)[l] = 0; \
- memcpy(_q_, p, l); \
+ size_t _l_ = l; \
+ assert(_l_ <= ALLOCA_MAX); \
+ _q_ = alloca(_l_ + 1); \
+ ((uint8_t*) _q_)[_l_] = 0; \
+ memcpy(_q_, p, _l_); \
})
static inline void freep(void *p) {
@@ -116,6 +128,7 @@ void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size);
({ \
char *_new_; \
size_t _len_ = n; \
+ assert(_len_ <= ALLOCA_MAX); \
_new_ = alloca(_len_); \
(void *) memset(_new_, 0, _len_); \
})
@@ -125,16 +138,18 @@ void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size);
({ \
void *_ptr_; \
size_t _mask_ = (align) - 1; \
- _ptr_ = alloca((size) + _mask_); \
+ size_t _size_ = size; \
+ assert(_size_ <= ALLOCA_MAX); \
+ _ptr_ = alloca(_size_ + _mask_); \
(void*)(((uintptr_t)_ptr_ + _mask_) & ~_mask_); \
})
#define alloca0_align(size, align) \
({ \
void *_new_; \
- size_t _size_ = (size); \
- _new_ = alloca_align(_size_, (align)); \
- (void*)memset(_new_, 0, _size_); \
+ size_t _xsize_ = (size); \
+ _new_ = alloca_align(_xsize_, (align)); \
+ (void*)memset(_new_, 0, _xsize_); \
})
/* Takes inspiration from Rusts's Option::take() method: reads and returns a pointer, but at the same time resets it to
diff --git a/src/basic/btrfs-util.c b/src/basic/btrfs-util.c
index d08e7546d0..da4dd2a827 100644
--- a/src/basic/btrfs-util.c
+++ b/src/basic/btrfs-util.c
@@ -941,7 +941,7 @@ int btrfs_qgroup_destroy_recursive(int fd, uint64_t qgroupid) {
/* Destroys the specified qgroup, but unassigns it from all
* its parents first. Also, it recursively destroys all
- * qgroups it is assgined to that have the same id part of the
+ * qgroups it is assigned to that have the same id part of the
* qgroupid as the specified group. */
r = btrfs_qgroupid_split(qgroupid, NULL, &subvol_id);
diff --git a/src/basic/btrfs-util.h b/src/basic/btrfs-util.h
index 085aca4dbc..7d848a75d3 100644
--- a/src/basic/btrfs-util.h
+++ b/src/basic/btrfs-util.h
@@ -28,17 +28,17 @@ typedef struct BtrfsQuotaInfo {
} BtrfsQuotaInfo;
typedef enum BtrfsSnapshotFlags {
- BTRFS_SNAPSHOT_FALLBACK_COPY = 1, /* If the source isn't a subvolume, reflink everything */
- BTRFS_SNAPSHOT_READ_ONLY = 2,
- BTRFS_SNAPSHOT_RECURSIVE = 4,
- BTRFS_SNAPSHOT_QUOTA = 8,
- BTRFS_SNAPSHOT_FALLBACK_DIRECTORY = 16, /* If the destination doesn't support subvolumes, reflink/copy instead */
- BTRFS_SNAPSHOT_FALLBACK_IMMUTABLE = 32, /* When we can't create a subvolume, use the FS_IMMUTABLE attribute for indicating read-only */
+ BTRFS_SNAPSHOT_FALLBACK_COPY = 1 << 0, /* If the source isn't a subvolume, reflink everything */
+ BTRFS_SNAPSHOT_READ_ONLY = 1 << 1,
+ BTRFS_SNAPSHOT_RECURSIVE = 1 << 2,
+ BTRFS_SNAPSHOT_QUOTA = 1 << 3,
+ BTRFS_SNAPSHOT_FALLBACK_DIRECTORY = 1 << 4, /* If the destination doesn't support subvolumes, reflink/copy instead */
+ BTRFS_SNAPSHOT_FALLBACK_IMMUTABLE = 1 << 5, /* When we can't create a subvolume, use the FS_IMMUTABLE attribute for indicating read-only */
} BtrfsSnapshotFlags;
typedef enum BtrfsRemoveFlags {
- BTRFS_REMOVE_RECURSIVE = 1,
- BTRFS_REMOVE_QUOTA = 2,
+ BTRFS_REMOVE_RECURSIVE = 1 << 0,
+ BTRFS_REMOVE_QUOTA = 1 << 1,
} BtrfsRemoveFlags;
int btrfs_is_filesystem(int fd);
diff --git a/src/basic/build.h b/src/basic/build.h
index 2c46550300..7a59059080 100644
--- a/src/basic/build.h
+++ b/src/basic/build.h
@@ -1,6 +1,8 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
+#include "version.h"
+
#if HAVE_PAM
#define _PAM_FEATURE_ "+PAM"
#else
diff --git a/src/basic/capability-util.c b/src/basic/capability-util.c
index a3f3ca9f52..b944ee6ea1 100644
--- a/src/basic/capability-util.c
+++ b/src/basic/capability-util.c
@@ -13,6 +13,7 @@
#include "fileio.h"
#include "log.h"
#include "macro.h"
+#include "missing_prctl.h"
#include "parse-util.h"
#include "user-util.h"
#include "util.h"
diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c
index 830a63c185..8ce7ccb960 100644
--- a/src/basic/cgroup-util.c
+++ b/src/basic/cgroup-util.c
@@ -872,7 +872,7 @@ int cg_set_access(
bool fatal;
};
- /* cgroupsv1, aka legacy/non-unified */
+ /* cgroup v1, aka legacy/non-unified */
static const struct Attribute legacy_attributes[] = {
{ "cgroup.procs", true },
{ "tasks", false },
@@ -880,7 +880,7 @@ int cg_set_access(
{},
};
- /* cgroupsv2, aka unified */
+ /* cgroup v2, aka unified */
static const struct Attribute unified_attributes[] = {
{ "cgroup.procs", true },
{ "cgroup.subtree_control", true },
@@ -2039,7 +2039,7 @@ int cg_get_keyed_attribute(
char **v;
int r;
- /* Reads one or more fields of a cgroupsv2 keyed attribute file. The 'keys' parameter should be an strv with
+ /* Reads one or more fields of a cgroup v2 keyed attribute file. The 'keys' parameter should be an strv with
* all keys to retrieve. The 'ret_values' parameter should be passed as string size with the same number of
* entries as 'keys'. On success each entry will be set to the value of the matching key.
*
@@ -2491,7 +2491,7 @@ int cg_kernel_controllers(Set **ret) {
static thread_local CGroupUnified unified_cache = CGROUP_UNIFIED_UNKNOWN;
-/* The hybrid mode was initially implemented in v232 and simply mounted cgroup v2 on /sys/fs/cgroup/systemd. This
+/* The hybrid mode was initially implemented in v232 and simply mounted cgroup2 on /sys/fs/cgroup/systemd. This
* unfortunately broke other tools (such as docker) which expected the v1 "name=systemd" hierarchy on
* /sys/fs/cgroup/systemd. From v233 and on, the hybrid mode mountnbs v2 on /sys/fs/cgroup/unified and maintains
* "name=systemd" hierarchy on /sys/fs/cgroup/systemd for compatibility with other tools.
@@ -2739,13 +2739,13 @@ bool cg_is_legacy_wanted(void) {
if (wanted >= 0)
return wanted;
- /* Check if we have cgroups2 already mounted. */
+ /* Check if we have cgroup v2 already mounted. */
if (cg_unified_flush() >= 0 &&
unified_cache == CGROUP_UNIFIED_ALL)
return (wanted = false);
/* Otherwise, assume that at least partial legacy is wanted,
- * since cgroups2 should already be mounted at this point. */
+ * since cgroup v2 should already be mounted at this point. */
return (wanted = true);
}
diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h
index ea9a333290..119b493dc6 100644
--- a/src/basic/cgroup-util.h
+++ b/src/basic/cgroup-util.h
@@ -48,13 +48,13 @@ typedef enum CGroupMask {
CGROUP_MASK_BPF_FIREWALL = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_BPF_FIREWALL),
CGROUP_MASK_BPF_DEVICES = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_BPF_DEVICES),
- /* All real cgroupv1 controllers */
+ /* All real cgroup v1 controllers */
CGROUP_MASK_V1 = CGROUP_MASK_CPU|CGROUP_MASK_CPUACCT|CGROUP_MASK_BLKIO|CGROUP_MASK_MEMORY|CGROUP_MASK_DEVICES|CGROUP_MASK_PIDS,
- /* All real cgroupv2 controllers */
+ /* All real cgroup v2 controllers */
CGROUP_MASK_V2 = CGROUP_MASK_CPU|CGROUP_MASK_IO|CGROUP_MASK_MEMORY|CGROUP_MASK_PIDS,
- /* All cgroupv2 BPF pseudo-controllers */
+ /* All cgroup v2 BPF pseudo-controllers */
CGROUP_MASK_BPF = CGROUP_MASK_BPF_FIREWALL|CGROUP_MASK_BPF_DEVICES,
_CGROUP_MASK_ALL = CGROUP_CONTROLLER_TO_MASK(_CGROUP_CONTROLLER_MAX) - 1
@@ -162,9 +162,9 @@ int cg_enumerate_subgroups(const char *controller, const char *path, DIR **_d);
int cg_read_subgroup(DIR *d, char **fn);
typedef enum CGroupFlags {
- CGROUP_SIGCONT = 1,
- CGROUP_IGNORE_SELF = 2,
- CGROUP_REMOVE = 4,
+ CGROUP_SIGCONT = 1 << 0,
+ CGROUP_IGNORE_SELF = 1 << 1,
+ CGROUP_REMOVE = 1 << 2,
} CGroupFlags;
typedef void (*cg_kill_log_func_t)(pid_t pid, int sig, void *userdata);
diff --git a/src/basic/copy.c b/src/basic/copy.c
index 34e01ea1cf..46e02a3759 100644
--- a/src/basic/copy.c
+++ b/src/basic/copy.c
@@ -24,6 +24,7 @@
#include "macro.h"
#include "missing.h"
#include "mountpoint-util.h"
+#include "stat-util.h"
#include "string-util.h"
#include "strv.h"
#include "time-util.h"
@@ -501,7 +502,7 @@ static int fd_copy_directory(
_cleanup_close_ int fdf = -1, fdt = -1;
_cleanup_closedir_ DIR *d = NULL;
struct dirent *de;
- bool created;
+ bool exists, created;
int r;
assert(st);
@@ -522,13 +523,26 @@ static int fd_copy_directory(
return -errno;
fdf = -1;
- r = mkdirat(dt, to, st->st_mode & 07777);
- if (r >= 0)
- created = true;
- else if (errno == EEXIST && (copy_flags & COPY_MERGE))
+ exists = false;
+ if (copy_flags & COPY_MERGE_EMPTY) {
+ r = dir_is_empty_at(dt, to);
+ if (r < 0 && r != -ENOENT)
+ return r;
+ else if (r == 1)
+ exists = true;
+ }
+
+ if (exists)
created = false;
- else
- return -errno;
+ else {
+ r = mkdirat(dt, to, st->st_mode & 07777);
+ if (r >= 0)
+ created = true;
+ else if (errno == EEXIST && (copy_flags & COPY_MERGE))
+ created = false;
+ else
+ return -errno;
+ }
fdt = openat(dt, to, O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
if (fdt < 0)
diff --git a/src/basic/copy.h b/src/basic/copy.h
index a41b44c70a..f677021881 100644
--- a/src/basic/copy.h
+++ b/src/basic/copy.h
@@ -9,10 +9,11 @@
#include <sys/types.h>
typedef enum CopyFlags {
- COPY_REFLINK = 1 << 0, /* Try to reflink */
- COPY_MERGE = 1 << 1, /* Merge existing trees with our new one to copy */
- COPY_REPLACE = 1 << 2, /* Replace an existing file if there's one */
- COPY_SAME_MOUNT = 1 << 3, /* Don't descend recursively into other file systems, across mount point boundaries */
+ COPY_REFLINK = 1 << 0, /* Try to reflink */
+ COPY_MERGE = 1 << 1, /* Merge existing trees with our new one to copy */
+ COPY_REPLACE = 1 << 2, /* Replace an existing file if there's one */
+ COPY_SAME_MOUNT = 1 << 3, /* Don't descend recursively into other file systems, across mount point boundaries */
+ COPY_MERGE_EMPTY = 1 << 4, /* Merge an existing, empty directory with our new tree to copy */
} CopyFlags;
typedef int (*copy_progress_bytes_t)(uint64_t n_bytes, void *userdata);
diff --git a/src/basic/env-file.c b/src/basic/env-file.c
index 6a7d6746a1..7f10f9ad39 100644
--- a/src/basic/env-file.c
+++ b/src/basic/env-file.c
@@ -35,7 +35,6 @@ static int parse_env_file_internal(
VALUE,
VALUE_ESCAPE,
SINGLE_QUOTE_VALUE,
- SINGLE_QUOTE_VALUE_ESCAPE,
DOUBLE_QUOTE_VALUE,
DOUBLE_QUOTE_VALUE_ESCAPE,
COMMENT,
@@ -113,7 +112,7 @@ static int parse_env_file_internal(
} else if (c == '\'')
state = SINGLE_QUOTE_VALUE;
- else if (c == '\"')
+ else if (c == '"')
state = DOUBLE_QUOTE_VALUE;
else if (c == '\\')
state = VALUE_ESCAPE;
@@ -186,8 +185,6 @@ static int parse_env_file_internal(
case SINGLE_QUOTE_VALUE:
if (c == '\'')
state = PRE_VALUE;
- else if (c == '\\')
- state = SINGLE_QUOTE_VALUE_ESCAPE;
else {
if (!GREEDY_REALLOC(value, value_alloc, n_value+2))
return -ENOMEM;
@@ -197,19 +194,8 @@ static int parse_env_file_internal(
break;
- case SINGLE_QUOTE_VALUE_ESCAPE:
- state = SINGLE_QUOTE_VALUE;
-
- if (!strchr(NEWLINE, c)) {
- if (!GREEDY_REALLOC(value, value_alloc, n_value+2))
- return -ENOMEM;
-
- value[n_value++] = c;
- }
- break;
-
case DOUBLE_QUOTE_VALUE:
- if (c == '\"')
+ if (c == '"')
state = PRE_VALUE;
else if (c == '\\')
state = DOUBLE_QUOTE_VALUE_ESCAPE;
@@ -225,12 +211,17 @@ static int parse_env_file_internal(
case DOUBLE_QUOTE_VALUE_ESCAPE:
state = DOUBLE_QUOTE_VALUE;
- if (!strchr(NEWLINE, c)) {
+ if (c == '"') {
if (!GREEDY_REALLOC(value, value_alloc, n_value+2))
return -ENOMEM;
-
+ value[n_value++] = '"';
+ } else if (!strchr(NEWLINE, c)) {
+ if (!GREEDY_REALLOC(value, value_alloc, n_value+3))
+ return -ENOMEM;
+ value[n_value++] = '\\';
value[n_value++] = c;
}
+
break;
case COMMENT:
@@ -253,7 +244,6 @@ static int parse_env_file_internal(
VALUE,
VALUE_ESCAPE,
SINGLE_QUOTE_VALUE,
- SINGLE_QUOTE_VALUE_ESCAPE,
DOUBLE_QUOTE_VALUE,
DOUBLE_QUOTE_VALUE_ESCAPE)) {
@@ -527,7 +517,7 @@ static void write_env_var(FILE *f, const char *v) {
fwrite_unlocked(v, 1, p-v, f);
if (string_has_cc(p, NULL) || chars_intersect(p, WHITESPACE SHELL_NEED_QUOTES)) {
- fputc_unlocked('\"', f);
+ fputc_unlocked('"', f);
for (; *p; p++) {
if (strchr(SHELL_NEED_ESCAPE, *p))
@@ -536,7 +526,7 @@ static void write_env_var(FILE *f, const char *v) {
fputc_unlocked(*p, f);
}
- fputc_unlocked('\"', f);
+ fputc_unlocked('"', f);
} else
fputs_unlocked(p, f);
diff --git a/src/basic/env-util.c b/src/basic/env-util.c
index e494f65c98..fd449dcce0 100644
--- a/src/basic/env-util.c
+++ b/src/basic/env-util.c
@@ -339,7 +339,6 @@ char **strv_env_unset(char **l, const char *p) {
}
char **strv_env_unset_many(char **l, ...) {
-
char **f, **t;
if (!l)
@@ -408,7 +407,6 @@ int strv_env_replace(char ***l, char *p) {
}
char **strv_env_set(char **x, const char *p) {
-
_cleanup_strv_free_ char **ret = NULL;
size_t n, m;
char **k;
diff --git a/src/basic/env-util.h b/src/basic/env-util.h
index 4d21ea6bef..d54f99658b 100644
--- a/src/basic/env-util.h
+++ b/src/basic/env-util.h
@@ -13,9 +13,9 @@ bool env_value_is_valid(const char *e);
bool env_assignment_is_valid(const char *e);
enum {
- REPLACE_ENV_USE_ENVIRONMENT = 1u,
- REPLACE_ENV_ALLOW_BRACELESS = 2u,
- REPLACE_ENV_ALLOW_EXTENDED = 4u,
+ REPLACE_ENV_USE_ENVIRONMENT = 1 << 0,
+ REPLACE_ENV_ALLOW_BRACELESS = 1 << 1,
+ REPLACE_ENV_ALLOW_EXTENDED = 1 << 2,
};
char *replace_env_n(const char *format, size_t n, char **env, unsigned flags);
diff --git a/src/basic/extract-word.h b/src/basic/extract-word.h
index 8c63b7c306..705ebbe95b 100644
--- a/src/basic/extract-word.h
+++ b/src/basic/extract-word.h
@@ -4,12 +4,12 @@
#include "macro.h"
typedef enum ExtractFlags {
- EXTRACT_RELAX = 1,
- EXTRACT_CUNESCAPE = 2,
- EXTRACT_CUNESCAPE_RELAX = 4,
- EXTRACT_QUOTES = 8,
- EXTRACT_DONT_COALESCE_SEPARATORS = 16,
- EXTRACT_RETAIN_ESCAPE = 32,
+ EXTRACT_RELAX = 1 << 0,
+ EXTRACT_CUNESCAPE = 1 << 1,
+ EXTRACT_CUNESCAPE_RELAX = 1 << 2,
+ EXTRACT_QUOTES = 1 << 3,
+ EXTRACT_DONT_COALESCE_SEPARATORS = 1 << 4,
+ EXTRACT_RETAIN_ESCAPE = 1 << 5,
} ExtractFlags;
int extract_first_word(const char **p, char **ret, const char *separators, ExtractFlags flags);
diff --git a/src/basic/fd-util.c b/src/basic/fd-util.c
index c06f2fac7e..3e6ef5a06a 100644
--- a/src/basic/fd-util.c
+++ b/src/basic/fd-util.c
@@ -70,7 +70,7 @@ int safe_close(int fd) {
return -1;
}
-void safe_close_pair(int p[]) {
+void safe_close_pair(int p[static 2]) {
assert(p);
if (p[0] == p[1]) {
@@ -189,6 +189,27 @@ _pure_ static bool fd_in_set(int fd, const int fdset[], size_t n_fdset) {
return false;
}
+static int get_max_fd(void) {
+ struct rlimit rl;
+ rlim_t m;
+
+ /* Return the highest possible fd, based RLIMIT_NOFILE, but enforcing FD_SETSIZE-1 as lower boundary
+ * and INT_MAX as upper boundary. */
+
+ if (getrlimit(RLIMIT_NOFILE, &rl) < 0)
+ return -errno;
+
+ m = MAX(rl.rlim_cur, rl.rlim_max);
+ if (m < FD_SETSIZE) /* Let's always cover at least 1024 fds */
+ return FD_SETSIZE-1;
+
+ if (m == RLIM_INFINITY || m > INT_MAX) /* Saturate on overflow. After all fds are "int", hence can
+ * never be above INT_MAX */
+ return INT_MAX;
+
+ return (int) (m - 1);
+}
+
int close_all_fds(const int except[], size_t n_except) {
_cleanup_closedir_ DIR *d = NULL;
struct dirent *de;
@@ -198,20 +219,14 @@ int close_all_fds(const int except[], size_t n_except) {
d = opendir("/proc/self/fd");
if (!d) {
- struct rlimit rl;
int fd, max_fd;
- /* When /proc isn't available (for example in chroots) the fallback is brute forcing through the fd
- * table */
-
- assert_se(getrlimit(RLIMIT_NOFILE, &rl) >= 0);
-
- if (rl.rlim_max == 0)
- return -EINVAL;
+ /* When /proc isn't available (for example in chroots) the fallback is brute forcing through
+ * the fd table */
- /* Let's take special care if the resource limit is set to unlimited, or actually larger than the range
- * of 'int'. Let's avoid implicit overflows. */
- max_fd = (rl.rlim_max == RLIM_INFINITY || rl.rlim_max > INT_MAX) ? INT_MAX : (int) (rl.rlim_max - 1);
+ max_fd = get_max_fd();
+ if (max_fd < 0)
+ return max_fd;
for (fd = 3; fd >= 0; fd = fd < max_fd ? fd + 1 : -1) {
int q;
diff --git a/src/basic/fd-util.h b/src/basic/fd-util.h
index 00303a7e45..4085a244d2 100644
--- a/src/basic/fd-util.h
+++ b/src/basic/fd-util.h
@@ -14,7 +14,7 @@
int close_nointr(int fd);
int safe_close(int fd);
-void safe_close_pair(int p[]);
+void safe_close_pair(int p[static 2]);
static inline int safe_close_above_stdio(int fd) {
if (fd < 3) /* Don't close stdin/stdout/stderr, but still invalidate the fd by returning -1 */
diff --git a/src/basic/hashmap.c b/src/basic/hashmap.c
index 5a4bb37b82..66e9e0046b 100644
--- a/src/basic/hashmap.c
+++ b/src/basic/hashmap.c
@@ -345,7 +345,7 @@ static unsigned base_bucket_hash(HashmapBase *h, const void *p) {
}
#define bucket_hash(h, p) base_bucket_hash(HASHMAP_BASE(h), p)
-static inline void base_set_dirty(HashmapBase *h) {
+static void base_set_dirty(HashmapBase *h) {
h->dirty = true;
}
#define hashmap_set_dirty(h) base_set_dirty(HASHMAP_BASE(h))
@@ -888,7 +888,8 @@ void internal_hashmap_clear(HashmapBase *h, free_func_t default_free_key, free_f
* themselves from our hash table a second time, the entry is already gone. */
while (internal_hashmap_size(h) > 0) {
- void *v, *k;
+ void *k = NULL;
+ void *v;
v = internal_hashmap_first_key_and_value(h, true, &k);
@@ -1515,8 +1516,11 @@ void *internal_hashmap_first_key_and_value(HashmapBase *h, bool remove, void **r
unsigned idx;
idx = find_first_entry(h);
- if (idx == IDX_NIL)
+ if (idx == IDX_NIL) {
+ if (ret_key)
+ *ret_key = NULL;
return NULL;
+ }
e = bucket_at(h, idx);
key = (void*) e->key;
diff --git a/src/basic/hashmap.h b/src/basic/hashmap.h
index 5bf807a76f..e16a9f9e30 100644
--- a/src/basic/hashmap.h
+++ b/src/basic/hashmap.h
@@ -326,7 +326,6 @@ static inline void *ordered_hashmap_first_key_and_value(OrderedHashmap *h, void
return internal_hashmap_first_key_and_value(HASHMAP_BASE(h), false, ret);
}
-
static inline void *hashmap_steal_first(Hashmap *h) {
return internal_hashmap_first_key_and_value(HASHMAP_BASE(h), true, NULL);
}
diff --git a/src/basic/in-addr-util.c b/src/basic/in-addr-util.c
index 411efb242b..2bffe473ca 100644
--- a/src/basic/in-addr-util.c
+++ b/src/basic/in-addr-util.c
@@ -495,9 +495,8 @@ int in_addr_parse_prefixlen(int family, const char *p, unsigned char *ret) {
return 0;
}
-int in_addr_prefix_from_string_internal(
+int in_addr_prefix_from_string(
const char *p,
- bool use_default_prefixlen,
int family,
union in_addr_union *ret_prefix,
unsigned char *ret_prefixlen) {
@@ -531,13 +530,6 @@ int in_addr_prefix_from_string_internal(
r = in_addr_parse_prefixlen(family, e+1, &k);
if (r < 0)
return r;
- } else if (use_default_prefixlen) {
- if (family == AF_INET) {
- r = in4_addr_default_prefixlen(&buffer.in, &k);
- if (r < 0)
- return r;
- } else
- k = 0;
} else
k = FAMILY_ADDRESS_SIZE(family) * 8;
@@ -551,7 +543,7 @@ int in_addr_prefix_from_string_internal(
int in_addr_prefix_from_string_auto_internal(
const char *p,
- bool use_default_prefixlen,
+ InAddrPrefixLenMode mode,
int *ret_family,
union in_addr_union *ret_prefix,
unsigned char *ret_prefixlen) {
@@ -582,15 +574,24 @@ int in_addr_prefix_from_string_auto_internal(
r = in_addr_parse_prefixlen(family, e+1, &k);
if (r < 0)
return r;
- } else if (use_default_prefixlen) {
- if (family == AF_INET) {
- r = in4_addr_default_prefixlen(&buffer.in, &k);
- if (r < 0)
- return r;
- } else
- k = 0;
} else
- k = FAMILY_ADDRESS_SIZE(family) * 8;
+ switch (mode) {
+ case PREFIXLEN_FULL:
+ k = FAMILY_ADDRESS_SIZE(family) * 8;
+ break;
+ case PREFIXLEN_REFUSE:
+ return -ENOANO; /* To distinguish this error from others. */
+ case PREFIXLEN_LEGACY:
+ if (family == AF_INET) {
+ r = in4_addr_default_prefixlen(&buffer.in, &k);
+ if (r < 0)
+ return r;
+ } else
+ k = 0;
+ break;
+ default:
+ assert_not_reached("Invalid prefixlen mode");
+ }
if (ret_family)
*ret_family = family;
diff --git a/src/basic/in-addr-util.h b/src/basic/in-addr-util.h
index 5de85cc422..3069790519 100644
--- a/src/basic/in-addr-util.h
+++ b/src/basic/in-addr-util.h
@@ -45,19 +45,17 @@ int in4_addr_default_subnet_mask(const struct in_addr *addr, struct in_addr *mas
int in_addr_mask(int family, union in_addr_union *addr, unsigned char prefixlen);
int in_addr_prefix_covers(int family, const union in_addr_union *prefix, unsigned char prefixlen, const union in_addr_union *address);
int in_addr_parse_prefixlen(int family, const char *p, unsigned char *ret);
-int in_addr_prefix_from_string_internal(const char *p, bool use_default_prefixlen, int family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen);
-int in_addr_prefix_from_string_auto_internal(const char *p, bool use_default_prefixlen, int *ret_family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen);
-static inline int in_addr_prefix_from_string(const char *p, int family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen) {
- return in_addr_prefix_from_string_internal(p, false, family, ret_prefix, ret_prefixlen);
-}
+int in_addr_prefix_from_string(const char *p, int family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen);
+
+typedef enum InAddrPrefixLenMode {
+ PREFIXLEN_FULL, /* Default to prefixlen of address size, 32 for IPv4 or 128 for IPv6, if not specified. */
+ PREFIXLEN_REFUSE, /* Fail with -ENOANO if prefixlen is not specified. */
+ PREFIXLEN_LEGACY, /* Default to legacy default prefixlen calculation from address if not specified. */
+} InAddrPrefixLenMode;
+
+int in_addr_prefix_from_string_auto_internal(const char *p, InAddrPrefixLenMode mode, int *ret_family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen);
static inline int in_addr_prefix_from_string_auto(const char *p, int *ret_family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen) {
- return in_addr_prefix_from_string_auto_internal(p, false, ret_family, ret_prefix, ret_prefixlen);
-}
-static inline int in_addr_default_prefix_from_string(const char *p, int family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen) {
- return in_addr_prefix_from_string_internal(p, true, family, ret_prefix, ret_prefixlen);
-}
-static inline int in_addr_default_prefix_from_string_auto(const char *p, int *ret_family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen) {
- return in_addr_prefix_from_string_auto_internal(p, true, ret_family, ret_prefix, ret_prefixlen);
+ return in_addr_prefix_from_string_auto_internal(p, PREFIXLEN_FULL, ret_family, ret_prefix, ret_prefixlen);
}
static inline size_t FAMILY_ADDRESS_SIZE(int family) {
diff --git a/src/basic/io-util.c b/src/basic/io-util.c
index 1f64cc933b..575398fbe6 100644
--- a/src/basic/io-util.c
+++ b/src/basic/io-util.c
@@ -8,6 +8,7 @@
#include <unistd.h>
#include "io-util.h"
+#include "string-util.h"
#include "time-util.h"
int flush_fd(int fd) {
@@ -252,3 +253,12 @@ ssize_t sparse_write(int fd, const void *p, size_t sz, size_t run_length) {
return q - (const uint8_t*) p;
}
+
+char* set_iovec_string_field(struct iovec *iovec, size_t *n_iovec, const char *field, const char *value) {
+ char *x;
+
+ x = strappend(field, value);
+ if (x)
+ iovec[(*n_iovec)++] = IOVEC_MAKE_STRING(x);
+ return x;
+}
diff --git a/src/basic/io-util.h b/src/basic/io-util.h
index ed189b5820..792a64ad5e 100644
--- a/src/basic/io-util.h
+++ b/src/basic/io-util.h
@@ -71,3 +71,5 @@ static inline bool FILE_SIZE_VALID_OR_INFINITY(uint64_t l) {
#define IOVEC_MAKE(base, len) (struct iovec) IOVEC_INIT(base, len)
#define IOVEC_INIT_STRING(string) IOVEC_INIT((char*) string, strlen(string))
#define IOVEC_MAKE_STRING(string) (struct iovec) IOVEC_INIT_STRING(string)
+
+char* set_iovec_string_field(struct iovec *iovec, size_t *n_iovec, const char *field, const char *value);
diff --git a/src/basic/meson.build b/src/basic/meson.build
index 23b5e75bd8..e5852f32f9 100644
--- a/src/basic/meson.build
+++ b/src/basic/meson.build
@@ -292,7 +292,8 @@ libbasic = static_library(
'basic',
basic_sources,
include_directories : includes,
- dependencies : [threads,
+ dependencies : [versiondep,
+ threads,
libcap,
libselinux,
libm],
diff --git a/src/basic/missing_if_link.h b/src/basic/missing_if_link.h
index 07675426bb..761797f56a 100644
--- a/src/basic/missing_if_link.h
+++ b/src/basic/missing_if_link.h
@@ -110,6 +110,9 @@ enum ipvlan_mode {
#define IFLA_MAX 51
#endif
+#if !HAVE_IFLA_BOND_MODE /* linux@90af231106c0b8d223c27d35464af95cb3d9cacf (3.13) */
+#define IFLA_BOND_MODE 1
+#endif
#if !HAVE_IFLA_BOND_ACTIVE_SLAVE /* linux@ec76aa49855f6d6fea5e01de179fb57dd47c619d (3.13) */
#define IFLA_BOND_ACTIVE_SLAVE 2
#endif
diff --git a/src/basic/missing_syscall.h b/src/basic/missing_syscall.h
index d5d4b26acb..d1aa32218b 100644
--- a/src/basic/missing_syscall.h
+++ b/src/basic/missing_syscall.h
@@ -3,6 +3,7 @@
/* Missing glibc definitions to access certain kernel APIs */
+#include <errno.h>
#include <fcntl.h>
#include <sys/syscall.h>
#include <sys/types.h>
diff --git a/src/basic/path-util.h b/src/basic/path-util.h
index 094aa47c01..86c5a577cb 100644
--- a/src/basic/path-util.h
+++ b/src/basic/path-util.h
@@ -131,7 +131,7 @@ char *prefix_root(const char *root, const char *path);
_ret = _path; \
else { \
_l = strlen(_root) + 1 + strlen(_path) + 1; \
- _n = alloca(_l); \
+ _n = newa(char, _l); \
_p = stpcpy(_n, _root); \
while (_p > _n && _p[-1] == '/') \
_p--; \
diff --git a/src/basic/prioq.c b/src/basic/prioq.c
index cfd08d5d23..76b27fa0a8 100644
--- a/src/basic/prioq.c
+++ b/src/basic/prioq.c
@@ -259,15 +259,14 @@ int prioq_reshuffle(Prioq *q, void *data, unsigned *idx) {
return 1;
}
-void *prioq_peek(Prioq *q) {
-
+void *prioq_peek_by_index(Prioq *q, unsigned idx) {
if (!q)
return NULL;
- if (q->n_items <= 0)
+ if (idx >= q->n_items)
return NULL;
- return q->items[0].data;
+ return q->items[idx].data;
}
void *prioq_pop(Prioq *q) {
diff --git a/src/basic/prioq.h b/src/basic/prioq.h
index bba5c7caa4..1fb57bfa4c 100644
--- a/src/basic/prioq.h
+++ b/src/basic/prioq.h
@@ -19,8 +19,14 @@ int prioq_put(Prioq *q, void *data, unsigned *idx);
int prioq_remove(Prioq *q, void *data, unsigned *idx);
int prioq_reshuffle(Prioq *q, void *data, unsigned *idx);
-void *prioq_peek(Prioq *q) _pure_;
+void *prioq_peek_by_index(Prioq *q, unsigned idx) _pure_;
+static inline void *prioq_peek(Prioq *q) {
+ return prioq_peek_by_index(q, 0);
+}
void *prioq_pop(Prioq *q);
+#define PRIOQ_FOREACH_ITEM(q, p) \
+ for (unsigned _i = 0; (p = prioq_peek_by_index(q, _i)); _i++)
+
unsigned prioq_size(Prioq *q) _pure_;
bool prioq_isempty(Prioq *q) _pure_;
diff --git a/src/basic/process-util.c b/src/basic/process-util.c
index 448503409b..78ce43b944 100644
--- a/src/basic/process-util.c
+++ b/src/basic/process-util.c
@@ -102,7 +102,8 @@ int get_process_comm(pid_t pid, char **ret) {
int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char **line) {
_cleanup_fclose_ FILE *f = NULL;
bool space = false;
- char *k, *ans = NULL;
+ char *k;
+ _cleanup_free_ char *ans = NULL;
const char *p;
int c;
@@ -129,6 +130,13 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char *
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
+ if (max_length == 0) {
+ /* This is supposed to be a safety guard against runaway command lines. */
+ long l = sysconf(_SC_ARG_MAX);
+ assert(l > 0);
+ max_length = l;
+ }
+
if (max_length == 1) {
/* If there's only room for one byte, return the empty string */
@@ -136,35 +144,9 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char *
if (!ans)
return -ENOMEM;
- *line = ans;
+ *line = TAKE_PTR(ans);
return 0;
- } else if (max_length == 0) {
- size_t len = 0, allocated = 0;
-
- while ((c = getc(f)) != EOF) {
-
- if (!GREEDY_REALLOC(ans, allocated, len+3)) {
- free(ans);
- return -ENOMEM;
- }
-
- if (isprint(c)) {
- if (space) {
- ans[len++] = ' ';
- space = false;
- }
-
- ans[len++] = c;
- } else if (len > 0)
- space = true;
- }
-
- if (len > 0)
- ans[len] = '\0';
- else
- ans = mfree(ans);
-
} else {
bool dotdotdot = false;
size_t left;
@@ -227,7 +209,7 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char *
_cleanup_free_ char *t = NULL;
int h;
- free(ans);
+ ans = mfree(ans);
if (!comm_fallback)
return -ENOENT;
@@ -236,37 +218,42 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char *
if (h < 0)
return h;
- if (max_length == 0)
- ans = strjoin("[", t, "]");
- else {
- size_t l;
-
- l = strlen(t);
+ size_t l = strlen(t);
- if (l + 3 <= max_length)
- ans = strjoin("[", t, "]");
- else if (max_length <= 6) {
+ if (l + 3 <= max_length) {
+ ans = strjoin("[", t, "]");
+ if (!ans)
+ return -ENOMEM;
- ans = new(char, max_length);
- if (!ans)
- return -ENOMEM;
+ } else if (max_length <= 6) {
+ ans = new(char, max_length);
+ if (!ans)
+ return -ENOMEM;
- memcpy(ans, "[...]", max_length-1);
- ans[max_length-1] = 0;
- } else {
- t[max_length - 6] = 0;
+ memcpy(ans, "[...]", max_length-1);
+ ans[max_length-1] = 0;
+ } else {
+ t[max_length - 6] = 0;
- /* Chop off final spaces */
- delete_trailing_chars(t, WHITESPACE);
+ /* Chop off final spaces */
+ delete_trailing_chars(t, WHITESPACE);
- ans = strjoin("[", t, "...]");
- }
+ ans = strjoin("[", t, "...]");
+ if (!ans)
+ return -ENOMEM;
}
- if (!ans)
- return -ENOMEM;
+
+ *line = TAKE_PTR(ans);
+ return 0;
}
- *line = ans;
+ k = realloc(ans, strlen(ans) + 1);
+ if (!k)
+ return -ENOMEM;
+
+ ans = NULL;
+ *line = k;
+
return 0;
}
diff --git a/src/basic/process-util.h b/src/basic/process-util.h
index 496e14d3de..c85ea30ecc 100644
--- a/src/basic/process-util.h
+++ b/src/basic/process-util.h
@@ -24,8 +24,8 @@
if (_pid_ == 0) { \
_r_ = ("/proc/self/" field); \
} else { \
- _r_ = alloca(STRLEN("/proc/") + DECIMAL_STR_MAX(pid_t) + 1 + sizeof(field)); \
- sprintf((char*) _r_, "/proc/"PID_FMT"/" field, _pid_); \
+ _r_ = newa(char, STRLEN("/proc/") + DECIMAL_STR_MAX(pid_t) + 1 + sizeof(field)); \
+ sprintf((char*) _r_, "/proc/"PID_FMT"/" field, _pid_); \
} \
_r_; \
})
diff --git a/src/basic/procfs-util.c b/src/basic/procfs-util.c
index a159e344b3..7aaf95bfce 100644
--- a/src/basic/procfs-util.c
+++ b/src/basic/procfs-util.c
@@ -201,13 +201,11 @@ int procfs_cpu_get_usage(nsec_t *ret) {
return 0;
}
-int procfs_memory_get_current(uint64_t *ret) {
+int procfs_memory_get(uint64_t *ret_total, uint64_t *ret_used) {
uint64_t mem_total = UINT64_MAX, mem_free = UINT64_MAX;
_cleanup_fclose_ FILE *f = NULL;
int r;
- assert(ret);
-
f = fopen("/proc/meminfo", "re");
if (!f)
return -errno;
@@ -262,6 +260,9 @@ int procfs_memory_get_current(uint64_t *ret) {
if (mem_free > mem_total)
return -EINVAL;
- *ret = (mem_total - mem_free) * 1024U;
+ if (ret_total)
+ *ret_total = mem_total * 1024U;
+ if (ret_used)
+ *ret_used = (mem_total - mem_free) * 1024U;
return 0;
}
diff --git a/src/basic/procfs-util.h b/src/basic/procfs-util.h
index f697ed92bc..5a44e9eff7 100644
--- a/src/basic/procfs-util.h
+++ b/src/basic/procfs-util.h
@@ -11,4 +11,7 @@ int procfs_tasks_get_current(uint64_t *ret);
int procfs_cpu_get_usage(nsec_t *ret);
-int procfs_memory_get_current(uint64_t *ret);
+int procfs_memory_get(uint64_t *ret_total, uint64_t *ret_used);
+static inline int procfs_memory_get_used(uint64_t *ret) {
+ return procfs_memory_get(NULL, ret);
+}
diff --git a/src/basic/siphash24.c b/src/basic/siphash24.c
index 30c228a78a..61180819b1 100644
--- a/src/basic/siphash24.c
+++ b/src/basic/siphash24.c
@@ -23,13 +23,13 @@
#include "siphash24.h"
#include "unaligned.h"
-static inline uint64_t rotate_left(uint64_t x, uint8_t b) {
+static uint64_t rotate_left(uint64_t x, uint8_t b) {
assert(b < 64);
return (x << b) | (x >> (64 - b));
}
-static inline void sipround(struct siphash *state) {
+static void sipround(struct siphash *state) {
assert(state);
state->v0 += state->v1;
@@ -48,7 +48,7 @@ static inline void sipround(struct siphash *state) {
state->v2 = rotate_left(state->v2, 32);
}
-void siphash24_init(struct siphash *state, const uint8_t k[16]) {
+void siphash24_init(struct siphash *state, const uint8_t k[static 16]) {
uint64_t k0, k1;
assert(state);
@@ -187,7 +187,7 @@ uint64_t siphash24_finalize(struct siphash *state) {
return state->v0 ^ state->v1 ^ state->v2 ^ state->v3;
}
-uint64_t siphash24(const void *in, size_t inlen, const uint8_t k[16]) {
+uint64_t siphash24(const void *in, size_t inlen, const uint8_t k[static 16]) {
struct siphash state;
assert(in);
diff --git a/src/basic/siphash24.h b/src/basic/siphash24.h
index 70a4a03f6a..67c4f7560c 100644
--- a/src/basic/siphash24.h
+++ b/src/basic/siphash24.h
@@ -15,14 +15,14 @@ struct siphash {
size_t inlen;
};
-void siphash24_init(struct siphash *state, const uint8_t k[16]);
+void siphash24_init(struct siphash *state, const uint8_t k[static 16]);
void siphash24_compress(const void *in, size_t inlen, struct siphash *state);
#define siphash24_compress_byte(byte, state) siphash24_compress((const uint8_t[]) { (byte) }, 1, (state))
uint64_t siphash24_finalize(struct siphash *state);
-uint64_t siphash24(const void *in, size_t inlen, const uint8_t k[16]);
+uint64_t siphash24(const void *in, size_t inlen, const uint8_t k[static 16]);
-static inline uint64_t siphash24_string(const char *s, const uint8_t k[16]) {
+static inline uint64_t siphash24_string(const char *s, const uint8_t k[static 16]) {
return siphash24(s, strlen(s) + 1, k);
}
diff --git a/src/basic/stat-util.c b/src/basic/stat-util.c
index 57700e2388..ea2bbc368b 100644
--- a/src/basic/stat-util.c
+++ b/src/basic/stat-util.c
@@ -67,13 +67,22 @@ int is_device_node(const char *path) {
return !!(S_ISBLK(info.st_mode) || S_ISCHR(info.st_mode));
}
-int dir_is_empty(const char *path) {
- _cleanup_closedir_ DIR *d;
+int dir_is_empty_at(int dir_fd, const char *path) {
+ _cleanup_close_ int fd = -1;
+ _cleanup_closedir_ DIR *d = NULL;
struct dirent *de;
- d = opendir(path);
+ if (path)
+ fd = openat(dir_fd, path, O_RDONLY|O_DIRECTORY|O_CLOEXEC);
+ else
+ fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
+ if (fd < 0)
+ return -errno;
+
+ d = fdopendir(fd);
if (!d)
return -errno;
+ fd = -1;
FOREACH_DIRENT(de, d, return -errno)
return 0;
@@ -338,7 +347,6 @@ int device_path_make_major_minor(mode_t mode, dev_t devno, char **ret) {
return -ENOMEM;
return 0;
-
}
int device_path_make_canonical(mode_t mode, dev_t devno, char **ret) {
diff --git a/src/basic/stat-util.h b/src/basic/stat-util.h
index 0a08e642b5..74fb7251b3 100644
--- a/src/basic/stat-util.h
+++ b/src/basic/stat-util.h
@@ -15,7 +15,10 @@ int is_dir(const char *path, bool follow);
int is_dir_fd(int fd);
int is_device_node(const char *path);
-int dir_is_empty(const char *path);
+int dir_is_empty_at(int dir_fd, const char *path);
+static inline int dir_is_empty(const char *path) {
+ return dir_is_empty_at(AT_FDCWD, path);
+}
static inline int dir_is_populated(const char *path) {
int r;
diff --git a/src/basic/string-util.c b/src/basic/string-util.c
index 05469ac01f..93917bc0f0 100644
--- a/src/basic/string-util.c
+++ b/src/basic/string-util.c
@@ -742,7 +742,7 @@ char *strreplace(const char *text, const char *old_string, const char *new_strin
return ret;
}
-static void advance_offsets(ssize_t diff, size_t offsets[2], size_t shift[2], size_t size) {
+static void advance_offsets(ssize_t diff, size_t offsets[static 2], size_t shift[static 2], size_t size) {
if (!offsets)
return;
diff --git a/src/basic/string-util.h b/src/basic/string-util.h
index a5b5a16a5d..38070abb22 100644
--- a/src/basic/string-util.h
+++ b/src/basic/string-util.h
@@ -6,6 +6,7 @@
#include <stddef.h>
#include <string.h>
+#include "alloc-util.h"
#include "macro.h"
/* What is interpreted as whitespace? */
@@ -111,7 +112,7 @@ char *strjoin_real(const char *x, ...) _sentinel_;
size_t _i_; \
for (_i_ = 0; _i_ < ELEMENTSOF(_appendees_) && _appendees_[_i_]; _i_++) \
_len_ += strlen(_appendees_[_i_]); \
- _p_ = _d_ = alloca(_len_ + 1); \
+ _p_ = _d_ = newa(char, _len_ + 1); \
for (_i_ = 0; _i_ < ELEMENTSOF(_appendees_) && _appendees_[_i_]; _i_++) \
_p_ = stpcpy(_p_, _appendees_[_i_]); \
*_p_ = 0; \
diff --git a/src/basic/strv.h b/src/basic/strv.h
index aa4cd4aaca..392cab65be 100644
--- a/src/basic/strv.h
+++ b/src/basic/strv.h
@@ -156,17 +156,10 @@ void strv_print(char **l);
_found; \
})
-#define FOREACH_STRING(x, ...) \
- for (char **_l = ({ \
- char **_ll = STRV_MAKE(__VA_ARGS__); \
- x = _ll ? _ll[0] : NULL; \
- _ll; \
- }); \
- _l && *_l; \
- x = ({ \
- _l ++; \
- _l[0]; \
- }))
+#define FOREACH_STRING(x, y, ...) \
+ for (char **_l = STRV_MAKE(({ x = y; }), ##__VA_ARGS__); \
+ x; \
+ x = *(++_l))
char **strv_reverse(char **l);
char **strv_shell_escape(char **l, const char *bad);
diff --git a/src/basic/time-util.c b/src/basic/time-util.c
index 557c75debc..62cdc305f9 100644
--- a/src/basic/time-util.c
+++ b/src/basic/time-util.c
@@ -24,7 +24,6 @@
#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
-#include "serialize.h"
#include "stat-util.h"
#include "string-util.h"
#include "strv.h"
diff --git a/src/basic/tmpfile-util.c b/src/basic/tmpfile-util.c
index 669eb2666c..bc92d6a6de 100644
--- a/src/basic/tmpfile-util.c
+++ b/src/basic/tmpfile-util.c
@@ -8,6 +8,7 @@
#include "hexdecoct.h"
#include "macro.h"
#include "memfd-util.h"
+#include "missing_fcntl.h"
#include "missing_syscall.h"
#include "path-util.h"
#include "process-util.h"
diff --git a/src/basic/unit-name.h b/src/basic/unit-name.h
index d373f03aca..0629db3f67 100644
--- a/src/basic/unit-name.h
+++ b/src/basic/unit-name.h
@@ -9,9 +9,9 @@
#define UNIT_NAME_MAX 256
typedef enum UnitNameFlags {
- UNIT_NAME_PLAIN = 1, /* Allow foo.service */
- UNIT_NAME_INSTANCE = 2, /* Allow foo@bar.service */
- UNIT_NAME_TEMPLATE = 4, /* Allow foo@.service */
+ UNIT_NAME_PLAIN = 1 << 0, /* Allow foo.service */
+ UNIT_NAME_INSTANCE = 1 << 1, /* Allow foo@bar.service */
+ UNIT_NAME_TEMPLATE = 1 << 2, /* Allow foo@.service */
UNIT_NAME_ANY = UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE,
} UnitNameFlags;
@@ -50,8 +50,8 @@ int unit_name_from_path_instance(const char *prefix, const char *path, const cha
int unit_name_to_path(const char *name, char **ret);
typedef enum UnitNameMangle {
- UNIT_NAME_MANGLE_GLOB = 1,
- UNIT_NAME_MANGLE_WARN = 2,
+ UNIT_NAME_MANGLE_GLOB = 1 << 0,
+ UNIT_NAME_MANGLE_WARN = 1 << 1,
} UnitNameMangle;
int unit_name_mangle_with_suffix(const char *name, UnitNameMangle flags, const char *suffix, char **ret);
diff --git a/src/basic/user-util.c b/src/basic/user-util.c
index d410c9068b..260f3d2057 100644
--- a/src/basic/user-util.c
+++ b/src/basic/user-util.c
@@ -87,7 +87,7 @@ char *getusername_malloc(void) {
return uid_to_name(getuid());
}
-static inline bool is_nologin_shell(const char *shell) {
+static bool is_nologin_shell(const char *shell) {
return PATH_IN_SET(shell,
/* 'nologin' is the friendliest way to disable logins for a user account. It prints a nice
@@ -733,10 +733,6 @@ int maybe_setgroups(size_t size, const gid_t *list) {
}
bool synthesize_nobody(void) {
-
-#ifdef NOLEGACY
- return true;
-#else
/* Returns true when we shall synthesize the "nobody" user (which we do by default). This can be turned off by
* touching /etc/systemd/dont-synthesize-nobody in order to provide upgrade compatibility with legacy systems
* that used the "nobody" user name and group name for other UIDs/GIDs than 65534.
@@ -750,7 +746,6 @@ bool synthesize_nobody(void) {
cache = access("/etc/systemd/dont-synthesize-nobody", F_OK) < 0;
return cache;
-#endif
}
int putpwent_sane(const struct passwd *pw, FILE *stream) {
diff --git a/src/basic/util.c b/src/basic/util.c
index c4f12a6daa..e577c93e60 100644
--- a/src/basic/util.c
+++ b/src/basic/util.c
@@ -557,7 +557,7 @@ uint64_t system_tasks_max_scale(uint64_t v, uint64_t max) {
}
int version(void) {
- puts(PACKAGE_STRING "\n"
+ puts("systemd " STRINGIFY(PROJECT_VERSION) " (" GIT_VERSION ")\n"
SYSTEMD_FEATURES);
return 0;
}
diff --git a/src/basic/util.h b/src/basic/util.h
index f009d37d4c..dc33d66067 100644
--- a/src/basic/util.h
+++ b/src/basic/util.h
@@ -174,12 +174,21 @@ static inline void *mempset(void *s, int c, size_t n) {
}
static inline void _reset_errno_(int *saved_errno) {
+ if (*saved_errno < 0) /* Invalidated by UNPROTECT_ERRNO? */
+ return;
+
errno = *saved_errno;
}
#define PROTECT_ERRNO \
_cleanup_(_reset_errno_) _unused_ int _saved_errno_ = errno
+#define UNPROTECT_ERRNO \
+ do { \
+ errno = _saved_errno_; \
+ _saved_errno_ = -1; \
+ } while (false)
+
static inline int negative_errno(void) {
/* This helper should be used to shut up gcc if you know 'errno' is
* negative. Instead of "return -errno;", use "return negative_errno();"
diff --git a/src/boot/efi/boot.c b/src/boot/efi/boot.c
index 4719eeaf4b..9bf6895831 100644
--- a/src/boot/efi/boot.c
+++ b/src/boot/efi/boot.c
@@ -17,7 +17,7 @@
#endif
/* magic string to find in the binary image */
-static const char __attribute__((used)) magic[] = "#### LoaderInfo: systemd-boot " PACKAGE_VERSION " ####";
+static const char __attribute__((used)) magic[] = "#### LoaderInfo: systemd-boot " GIT_VERSION " ####";
static const EFI_GUID global_guid = EFI_GLOBAL_VARIABLE;
@@ -361,7 +361,7 @@ static VOID print_status(Config *config, CHAR16 *loaded_image_path) {
uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, EFI_LIGHTGRAY|EFI_BACKGROUND_BLACK);
uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
- Print(L"systemd-boot version: " PACKAGE_VERSION "\n");
+ Print(L"systemd-boot version: " GIT_VERSION "\n");
Print(L"architecture: " EFI_MACHINE_TYPE_NAME "\n");
Print(L"loaded image: %s\n", loaded_image_path);
Print(L"UEFI specification: %d.%02d\n", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff);
@@ -804,7 +804,7 @@ static BOOLEAN menu_run(
break;
case KEYPRESS(0, 0, 'v'):
- status = PoolPrint(L"systemd-boot " PACKAGE_VERSION " (" EFI_MACHINE_TYPE_NAME "), UEFI Specification %d.%02d, Vendor %s %d.%02d",
+ status = PoolPrint(L"systemd-boot " GIT_VERSION " (" EFI_MACHINE_TYPE_NAME "), UEFI Specification %d.%02d, Vendor %s %d.%02d",
ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff,
ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff);
break;
@@ -1000,7 +1000,7 @@ skip:
value++;
/* unquote */
- if (value[0] == '\"' && line[linelen-1] == '\"') {
+ if (value[0] == '"' && line[linelen-1] == '"') {
value++;
line[linelen-1] = '\0';
}
@@ -2097,7 +2097,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
InitializeLib(image, sys_table);
init_usec = time_usec();
efivar_set_time_usec(L"LoaderTimeInitUSec", init_usec);
- efivar_set(L"LoaderInfo", L"systemd-boot " PACKAGE_VERSION, FALSE);
+ efivar_set(L"LoaderInfo", L"systemd-boot " GIT_VERSION, FALSE);
infostr = PoolPrint(L"%s %d.%02d", ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff);
efivar_set(L"LoaderFirmwareInfo", infostr, FALSE);
diff --git a/src/boot/efi/disk.c b/src/boot/efi/disk.c
index a31b7bb478..49ee81b4d7 100644
--- a/src/boot/efi/disk.c
+++ b/src/boot/efi/disk.c
@@ -5,7 +5,7 @@
#include "util.h"
-EFI_STATUS disk_get_part_uuid(EFI_HANDLE *handle, CHAR16 uuid[37]) {
+EFI_STATUS disk_get_part_uuid(EFI_HANDLE *handle, CHAR16 uuid[static 37]) {
EFI_DEVICE_PATH *device_path;
/* export the device path this image is started from */
diff --git a/src/boot/efi/disk.h b/src/boot/efi/disk.h
index 2a0b8ff2a7..41c4cce434 100644
--- a/src/boot/efi/disk.h
+++ b/src/boot/efi/disk.h
@@ -1,4 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-EFI_STATUS disk_get_part_uuid(EFI_HANDLE *handle, CHAR16 uuid[37]);
+EFI_STATUS disk_get_part_uuid(EFI_HANDLE *handle, CHAR16 uuid[static 37]);
diff --git a/src/boot/efi/linux.c b/src/boot/efi/linux.c
index d1605523d8..5b4c085880 100644
--- a/src/boot/efi/linux.c
+++ b/src/boot/efi/linux.c
@@ -52,7 +52,7 @@ struct SetupHeader {
#ifdef __x86_64__
typedef VOID(*handover_f)(VOID *image, EFI_SYSTEM_TABLE *table, struct SetupHeader *setup);
-static inline VOID linux_efi_handover(EFI_HANDLE image, struct SetupHeader *setup) {
+static VOID linux_efi_handover(EFI_HANDLE image, struct SetupHeader *setup) {
handover_f handover;
asm volatile ("cli");
@@ -61,7 +61,7 @@ static inline VOID linux_efi_handover(EFI_HANDLE image, struct SetupHeader *setu
}
#else
typedef VOID(*handover_f)(VOID *image, EFI_SYSTEM_TABLE *table, struct SetupHeader *setup) __attribute__((regparm(0)));
-static inline VOID linux_efi_handover(EFI_HANDLE image, struct SetupHeader *setup) {
+static VOID linux_efi_handover(EFI_HANDLE image, struct SetupHeader *setup) {
handover_f handover;
handover = (handover_f)((UINTN)setup->code32_start + setup->handover_offset);
diff --git a/src/boot/efi/meson.build b/src/boot/efi/meson.build
index aa897c62a1..2140151844 100644
--- a/src/boot/efi/meson.build
+++ b/src/boot/efi/meson.build
@@ -78,7 +78,6 @@ endif
if have_gnu_efi
efi_conf = configuration_data()
- efi_conf.set_quoted('PACKAGE_VERSION', meson.project_version())
efi_conf.set_quoted('EFI_MACHINE_TYPE_NAME', EFI_MACHINE_TYPE_NAME)
efi_conf.set10('ENABLE_TPM', get_option('tpm'))
efi_conf.set('SD_TPM_PCR', get_option('tpm-pcrindex'))
@@ -117,7 +116,8 @@ if have_gnu_efi
'-Wno-missing-field-initializers',
'-isystem', efi_incdir,
'-isystem', join_paths(efi_incdir, gnu_efi_path_arch),
- '-include', efi_config_h]
+ '-include', efi_config_h,
+ '-include', version_h]
if efi_arch == 'x86_64'
compile_args += ['-mno-red-zone',
'-mno-sse',
@@ -194,9 +194,7 @@ if have_gnu_efi
'-j', '.data',
'-j', '.dynamic',
'-j', '.dynsym',
- '-j', '.rel',
- '-j', '.rela',
- '-j', '.reloc']
+ '-j', '.rel*']
+ efi_format +
['@INPUT@', '@OUTPUT@'],
install : true,
diff --git a/src/boot/efi/stub.c b/src/boot/efi/stub.c
index d11e555748..6b07879971 100644
--- a/src/boot/efi/stub.c
+++ b/src/boot/efi/stub.c
@@ -12,7 +12,7 @@
#include "util.h"
/* magic string to find in the binary image */
-static const char __attribute__((used)) magic[] = "#### LoaderInfo: systemd-stub " PACKAGE_VERSION " ####";
+static const char __attribute__((used)) magic[] = "#### LoaderInfo: systemd-stub " GIT_VERSION " ####";
static const EFI_GUID global_guid = EFI_GLOBAL_VARIABLE;
@@ -117,7 +117,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
/* add StubInfo */
if (efivar_get_raw(&global_guid, L"StubInfo", &b, &size) != EFI_SUCCESS)
- efivar_set(L"StubInfo", L"systemd-stub " PACKAGE_VERSION, FALSE);
+ efivar_set(L"StubInfo", L"systemd-stub " GIT_VERSION, FALSE);
if (szs[3] > 0)
graphics_splash((UINT8 *)((UINTN)loaded_image->ImageBase + addrs[3]), szs[3], NULL);
diff --git a/src/busctl/busctl.c b/src/busctl/busctl.c
index 96b4177495..08d9e70c96 100644
--- a/src/busctl/busctl.c
+++ b/src/busctl/busctl.c
@@ -67,7 +67,7 @@ static int json_transform_message(sd_bus_message *m, JsonVariant **ret);
static void json_dump_with_flags(JsonVariant *v, FILE *f);
static int acquire_bus(bool set_monitor, sd_bus **ret) {
- _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
+ _cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL;
int r;
r = sd_bus_new(&bus);
diff --git a/src/cgtop/cgtop.c b/src/cgtop/cgtop.c
index 5abfab03de..b3bda30cec 100644
--- a/src/cgtop/cgtop.c
+++ b/src/cgtop/cgtop.c
@@ -104,7 +104,7 @@ static const char *maybe_format_bytes(char *buf, size_t l, bool is_valid, uint64
static bool is_root_cgroup(const char *path) {
- /* Returns true if the specified path belongs to the root cgroup. The root cgroup is special on cgroupsv2 as it
+ /* Returns true if the specified path belongs to the root cgroup. The root cgroup is special on cgroup v2 as it
* carries only very few attributes in order not to export multiple truth about system state as most
* information is available elsewhere in /proc anyway. We need to be able to deal with that, and need to get
* our data from different sources in that case.
@@ -291,7 +291,7 @@ static int process(
} else if (streq(controller, "memory")) {
if (is_root_cgroup(path)) {
- r = procfs_memory_get_current(&g->memory);
+ r = procfs_memory_get_used(&g->memory);
if (r < 0)
return r;
} else {
diff --git a/src/core/automount.c b/src/core/automount.c
index de8010bf2e..6a8373920e 100644
--- a/src/core/automount.c
+++ b/src/core/automount.c
@@ -48,7 +48,7 @@ struct expire_data {
int ioctl_fd;
};
-static inline void expire_data_free(struct expire_data *data) {
+static void expire_data_free(struct expire_data *data) {
if (!data)
return;
@@ -578,10 +578,13 @@ static void automount_enter_waiting(Automount *a) {
goto fail;
}
- if (pipe2(p, O_NONBLOCK|O_CLOEXEC) < 0) {
+ if (pipe2(p, O_CLOEXEC) < 0) {
r = -errno;
goto fail;
}
+ r = fd_nonblock(p[0], true);
+ if (r < 0)
+ goto fail;
xsprintf(options, "fd=%i,pgrp="PID_FMT",minproto=5,maxproto=5,direct", p[1], getpgrp());
xsprintf(name, "systemd-"PID_FMT, getpid_cached());
diff --git a/src/core/bpf-devices.c b/src/core/bpf-devices.c
index dade7f0490..81e91fcb36 100644
--- a/src/core/bpf-devices.c
+++ b/src/core/bpf-devices.c
@@ -202,7 +202,6 @@ int cgroup_apply_device_bpf(Unit *u, BPFProgram *prog, CGroupDevicePolicy policy
if (r < 0)
return log_error_errno(r, "Failed to determine cgroup path: %m");
-
r = bpf_program_cgroup_attach(prog, BPF_CGROUP_DEVICE, path, BPF_F_ALLOW_MULTI);
if (r < 0)
return log_error_errno(r, "Attaching device control BPF program to cgroup %s failed: %m", path);
diff --git a/src/core/cgroup.c b/src/core/cgroup.c
index a7ce3fceaa..18d470b6d6 100644
--- a/src/core/cgroup.c
+++ b/src/core/cgroup.c
@@ -396,26 +396,31 @@ static void cgroup_xattr_apply(Unit *u) {
}
static int lookup_block_device(const char *p, dev_t *ret) {
- struct stat st = {};
+ dev_t rdev, dev = 0;
+ mode_t mode;
int r;
assert(p);
assert(ret);
- r = device_path_parse_major_minor(p, &st.st_mode, &st.st_rdev);
+ r = device_path_parse_major_minor(p, &mode, &rdev);
if (r == -ENODEV) { /* not a parsable device node, need to go to disk */
+ struct stat st;
if (stat(p, &st) < 0)
return log_warning_errno(errno, "Couldn't stat device '%s': %m", p);
+ rdev = (dev_t)st.st_rdev;
+ dev = (dev_t)st.st_dev;
+ mode = st.st_mode;
} else if (r < 0)
return log_warning_errno(r, "Failed to parse major/minor from path '%s': %m", p);
- if (S_ISCHR(st.st_mode)) {
+ if (S_ISCHR(mode)) {
log_warning("Device node '%s' is a character device, but block device needed.", p);
return -ENOTBLK;
- } else if (S_ISBLK(st.st_mode))
- *ret = st.st_rdev;
- else if (major(st.st_dev) != 0)
- *ret = st.st_dev; /* If this is not a device node then use the block device this file is stored on */
+ } else if (S_ISBLK(mode))
+ *ret = rdev;
+ else if (major(dev) != 0)
+ *ret = dev; /* If this is not a device node then use the block device this file is stored on */
else {
/* If this is btrfs, getting the backing block device is a bit harder */
r = btrfs_get_block_device(p, ret);
@@ -436,7 +441,8 @@ static int lookup_block_device(const char *p, dev_t *ret) {
}
static int whitelist_device(BPFProgram *prog, const char *path, const char *node, const char *acc) {
- struct stat st = {};
+ dev_t rdev;
+ mode_t mode;
int r;
assert(path);
@@ -445,11 +451,12 @@ static int whitelist_device(BPFProgram *prog, const char *path, const char *node
/* Some special handling for /dev/block/%u:%u, /dev/char/%u:%u, /run/systemd/inaccessible/chr and
* /run/systemd/inaccessible/blk paths. Instead of stat()ing these we parse out the major/minor directly. This
* means clients can use these path without the device node actually around */
- r = device_path_parse_major_minor(node, &st.st_mode, &st.st_rdev);
+ r = device_path_parse_major_minor(node, &mode, &rdev);
if (r < 0) {
if (r != -ENODEV)
return log_warning_errno(r, "Couldn't parse major/minor from device path '%s': %m", node);
+ struct stat st;
if (stat(node, &st) < 0)
return log_warning_errno(errno, "Couldn't stat device %s: %m", node);
@@ -457,22 +464,24 @@ static int whitelist_device(BPFProgram *prog, const char *path, const char *node
log_warning("%s is not a device.", node);
return -ENODEV;
}
+ rdev = (dev_t) st.st_rdev;
+ mode = st.st_mode;
}
if (cg_all_unified() > 0) {
if (!prog)
return 0;
- return cgroup_bpf_whitelist_device(prog, S_ISCHR(st.st_mode) ? BPF_DEVCG_DEV_CHAR : BPF_DEVCG_DEV_BLOCK,
- major(st.st_rdev), minor(st.st_rdev), acc);
+ return cgroup_bpf_whitelist_device(prog, S_ISCHR(mode) ? BPF_DEVCG_DEV_CHAR : BPF_DEVCG_DEV_BLOCK,
+ major(rdev), minor(rdev), acc);
} else {
char buf[2+DECIMAL_STR_MAX(dev_t)*2+2+4];
sprintf(buf,
"%c %u:%u %s",
- S_ISCHR(st.st_mode) ? 'c' : 'b',
- major(st.st_rdev), minor(st.st_rdev),
+ S_ISCHR(mode) ? 'c' : 'b',
+ major(rdev), minor(rdev),
acc);
/* Changing the devices list of a populated cgroup might result in EINVAL, hence ignore EINVAL here. */
@@ -881,7 +890,7 @@ static void cgroup_context_apply(
/* In fully unified mode these attributes don't exist on the host cgroup root. On legacy the weights exist, but
* setting the weight makes very little sense on the host root cgroup, as there are no other cgroups at this
* level. The quota exists there too, but any attempt to write to it is refused with EINVAL. Inside of
- * containers we want to leave control of these to the container manager (and if cgroupsv2 delegation is used
+ * containers we want to leave control of these to the container manager (and if cgroup v2 delegation is used
* we couldn't even write to them if we wanted to). */
if ((apply_mask & CGROUP_MASK_CPU) && !is_local_root) {
@@ -925,7 +934,7 @@ static void cgroup_context_apply(
}
}
- /* The 'io' controller attributes are not exported on the host's root cgroup (being a pure cgroupsv2
+ /* The 'io' controller attributes are not exported on the host's root cgroup (being a pure cgroup v2
* controller), and in case of containers we want to leave control of these attributes to the container manager
* (and we couldn't access that stuff anyway, even if we tried if proper delegation is used). */
if ((apply_mask & CGROUP_MASK_IO) && !is_local_root) {
@@ -1067,7 +1076,7 @@ static void cgroup_context_apply(
/* In unified mode 'memory' attributes do not exist on the root cgroup. In legacy mode 'memory.limit_in_bytes'
* exists on the root cgroup, but any writes to it are refused with EINVAL. And if we run in a container we
- * want to leave control to the container manager (and if proper cgroupsv2 delegation is used we couldn't even
+ * want to leave control to the container manager (and if proper cgroup v2 delegation is used we couldn't even
* write to this if we wanted to.) */
if ((apply_mask & CGROUP_MASK_MEMORY) && !is_local_root) {
@@ -1109,7 +1118,7 @@ static void cgroup_context_apply(
}
}
- /* On cgroupsv2 we can apply BPF everywhere. On cgroupsv1 we apply it everywhere except for the root of
+ /* On cgroup v2 we can apply BPF everywhere. On cgroup v1 we apply it everywhere except for the root of
* containers, where we leave this to the manager */
if ((apply_mask & (CGROUP_MASK_DEVICES | CGROUP_MASK_BPF_DEVICES)) &&
(is_host_root || cg_all_unified() > 0 || !is_local_root)) {
@@ -1841,14 +1850,14 @@ static bool unit_has_mask_realized(
/* Returns true if this unit is fully realized. We check four things:
*
* 1. Whether the cgroup was created at all
- * 2. Whether the cgroup was created in all the hierarchies we need it to be created in (in case of cgroupsv1)
- * 3. Whether the cgroup has all the right controllers enabled (in case of cgroupsv2)
+ * 2. Whether the cgroup was created in all the hierarchies we need it to be created in (in case of cgroup v1)
+ * 3. Whether the cgroup has all the right controllers enabled (in case of cgroup v2)
* 4. Whether the invalidation mask is currently zero
*
* If you wonder why we mask the target realization and enable mask with CGROUP_MASK_V1/CGROUP_MASK_V2: note
- * that there are three sets of bitmasks: CGROUP_MASK_V1 (for real cgroupv1 controllers), CGROUP_MASK_V2 (for
- * real cgroupv2 controllers) and CGROUP_MASK_BPF (for BPF-based pseudo-controllers). Now, cgroup_realized_mask
- * is only matters for cgroupsv1 controllers, and cgroup_enabled_mask only used for cgroupsv2, and if they
+ * that there are three sets of bitmasks: CGROUP_MASK_V1 (for real cgroup v1 controllers), CGROUP_MASK_V2 (for
+ * real cgroup v2 controllers) and CGROUP_MASK_BPF (for BPF-based pseudo-controllers). Now, cgroup_realized_mask
+ * is only matters for cgroup v1 controllers, and cgroup_enabled_mask only used for cgroup v2, and if they
* differ in the others, we don't really care. (After all, the cgroup_enabled_mask tracks with controllers are
* enabled through cgroup.subtree_control, and since the BPF pseudo-controllers don't show up there, they
* simply don't matter. */
@@ -2771,7 +2780,7 @@ int unit_get_memory_current(Unit *u, uint64_t *ret) {
/* The root cgroup doesn't expose this information, let's get it from /proc instead */
if (unit_has_host_root_cgroup(u))
- return procfs_memory_get_current(ret);
+ return procfs_memory_get_used(ret);
if ((u->cgroup_realized_mask & CGROUP_MASK_MEMORY) == 0)
return -ENODATA;
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
index 8da07adfe7..88e4c6bb95 100644
--- a/src/core/dbus-manager.c
+++ b/src/core/dbus-manager.c
@@ -43,7 +43,7 @@ static UnitFileFlags unit_file_bools_to_flags(bool runtime, bool force) {
(force ? UNIT_FILE_FORCE : 0);
}
-static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_version, "s", PACKAGE_VERSION);
+static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_version, "s", GIT_VERSION);
static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_features, "s", SYSTEMD_FEATURES);
static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_architecture, "s", architecture_to_string(uname_architecture()));
static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_log_target, "s", log_target_to_string(log_get_target()));
diff --git a/src/core/dbus-service.c b/src/core/dbus-service.c
index ec61ea2772..0904cc09c0 100644
--- a/src/core/dbus-service.c
+++ b/src/core/dbus-service.c
@@ -320,29 +320,35 @@ static int bus_service_set_transient_property(
if (r < 0)
return r;
- n = path_make_absolute(v, u->manager->prefix[EXEC_DIRECTORY_RUNTIME]);
- if (!n)
- return -ENOMEM;
+ if (!isempty(v)) {
+ n = path_make_absolute(v, u->manager->prefix[EXEC_DIRECTORY_RUNTIME]);
+ if (!n)
+ return -ENOMEM;
- path_simplify(n, true);
+ path_simplify(n, true);
- if (!path_is_normalized(n))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "PIDFile= path '%s' is not valid", n);
+ if (!path_is_normalized(n))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "PIDFile= path '%s' is not valid", n);
- e = path_startswith(n, "/var/run/");
- if (e) {
- char *z;
+ e = path_startswith(n, "/var/run/");
+ if (e) {
+ char *z;
- z = strjoin("/run/", e);
- if (!z)
- return log_oom();
+ z = strjoin("/run/", e);
+ if (!z)
+ return log_oom();
- if (!UNIT_WRITE_FLAGS_NOOP(flags))
- log_unit_notice(u, "Transient unit's PIDFile= property references path below legacy directory /var/run, updating %s → %s; please update client accordingly.", n, z);
+ if (!UNIT_WRITE_FLAGS_NOOP(flags))
+ log_unit_notice(u, "Transient unit's PIDFile= property references path below legacy directory /var/run, updating %s → %s; please update client accordingly.", n, z);
- free_and_replace(s->pid_file, z);
- } else
+ free_and_replace(n, z);
+ }
+ }
+
+ if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
free_and_replace(s->pid_file, n);
+ unit_write_settingf(u, flags, name, "%s=%s", name, strempty(s->pid_file));
+ }
return 1;
}
diff --git a/src/core/dbus-socket.c b/src/core/dbus-socket.c
index 37cf9d204c..83ac7ad110 100644
--- a/src/core/dbus-socket.c
+++ b/src/core/dbus-socket.c
@@ -134,11 +134,11 @@ const sd_bus_vtable bus_socket_vtable[] = {
SD_BUS_VTABLE_END
};
-static inline bool check_size_t_truncation(uint64_t t) {
+static bool check_size_t_truncation(uint64_t t) {
return (size_t) t == t;
}
-static inline const char* socket_protocol_to_string(int32_t i) {
+static const char* socket_protocol_to_string(int32_t i) {
if (i == IPPROTO_IP)
return "";
diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c
index 968166ee60..17c2003c8f 100644
--- a/src/core/dbus-unit.c
+++ b/src/core/dbus-unit.c
@@ -1385,9 +1385,9 @@ static int bus_set_transient_emergency_action(
system = MANAGER_IS_SYSTEM(u->manager);
r = parse_emergency_action(s, system, &v);
- if (v < 0)
+ if (r < 0)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
- v == -EOPNOTSUPP ? "EmergencyAction setting invalid for manager type: %s"
+ r == -EOPNOTSUPP ? "%s setting invalid for manager type: %s"
: "Invalid %s setting: %s",
name, s);
diff --git a/src/core/dbus.c b/src/core/dbus.c
index 5908ad792a..255b86e7a4 100644
--- a/src/core/dbus.c
+++ b/src/core/dbus.c
@@ -611,7 +611,7 @@ static int bus_setup_disconnected_match(Manager *m, sd_bus *bus) {
}
static int bus_on_connection(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
- _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
+ _cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL;
_cleanup_close_ int nfd = -1;
Manager *m = userdata;
sd_id128_t id;
@@ -876,7 +876,7 @@ static int bus_setup_api(Manager *m, sd_bus *bus) {
}
int bus_init_api(Manager *m) {
- _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
+ _cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL;
int r;
if (m->api_bus)
@@ -940,7 +940,7 @@ static int bus_setup_system(Manager *m, sd_bus *bus) {
}
int bus_init_system(Manager *m) {
- _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
+ _cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL;
int r;
if (m->system_bus)
@@ -1080,8 +1080,7 @@ static void destroy_bus(Manager *m, sd_bus **bus) {
sd_bus_flush(*bus);
/* And destroy the object */
- sd_bus_close(*bus);
- *bus = sd_bus_unref(*bus);
+ *bus = sd_bus_close_unref(*bus);
}
void bus_done_api(Manager *m) {
diff --git a/src/core/device.c b/src/core/device.c
index 960f403718..b006add405 100644
--- a/src/core/device.c
+++ b/src/core/device.c
@@ -631,7 +631,7 @@ static int device_process_new(Manager *m, sd_device *dev) {
if (r == -ENOMEM)
return log_oom();
if (r < 0)
- return log_device_warning_errno(dev, r, "Failed to add parse SYSTEMD_ALIAS property: %m");
+ return log_device_warning_errno(dev, r, "Failed to parse SYSTEMD_ALIAS property: %m");
if (!path_is_absolute(word))
log_device_warning(dev, "SYSTEMD_ALIAS is not an absolute path, ignoring: %s", word);
diff --git a/src/core/dynamic-user.c b/src/core/dynamic-user.c
index 089461a18a..530df70b80 100644
--- a/src/core/dynamic-user.c
+++ b/src/core/dynamic-user.c
@@ -35,7 +35,7 @@ static DynamicUser* dynamic_user_free(DynamicUser *d) {
return mfree(d);
}
-static int dynamic_user_add(Manager *m, const char *name, int storage_socket[2], DynamicUser **ret) {
+static int dynamic_user_add(Manager *m, const char *name, int storage_socket[static 2], DynamicUser **ret) {
DynamicUser *d;
int r;
diff --git a/src/core/execute.c b/src/core/execute.c
index 595a3c6eca..a7082310ba 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -1595,7 +1595,7 @@ static int apply_lock_personality(const Unit* u, const ExecContext *c) {
#endif
-static void do_idle_pipe_dance(int idle_pipe[4]) {
+static void do_idle_pipe_dance(int idle_pipe[static 4]) {
assert(idle_pipe);
idle_pipe[1] = safe_close(idle_pipe[1]);
@@ -2160,8 +2160,21 @@ static int setup_exec_directory(
r = mkdir_label(p, context->directories[type].mode);
if (r < 0 && r != -EEXIST)
goto fail;
- if (r == -EEXIST && !context->dynamic_user)
- continue;
+ if (r == -EEXIST) {
+ struct stat st;
+
+ if (stat(p, &st) < 0) {
+ r = -errno;
+ goto fail;
+ }
+ if (((st.st_mode ^ context->directories[type].mode) & 07777) != 0)
+ log_warning("%s \'%s\' already exists but the mode is different. "
+ "(filesystem: %o %sMode: %o)",
+ exec_directory_type_to_string(type), *rt,
+ st.st_mode & 07777, exec_directory_type_to_string(type), context->directories[type].mode & 07777);
+ if (!context->dynamic_user)
+ continue;
+ }
}
/* Don't change the owner of the configuration directory, as in the common case it is not written to by
@@ -2618,7 +2631,7 @@ out:
return r;
}
-static void append_socket_pair(int *array, size_t *n, const int pair[2]) {
+static void append_socket_pair(int *array, size_t *n, const int pair[static 2]) {
assert(array);
assert(n);
@@ -3137,9 +3150,9 @@ static int exec_child(
}
}
- /* If delegation is enabled we'll pass ownership of the cgroup to the user of the new process. On cgroupsv1
+ /* If delegation is enabled we'll pass ownership of the cgroup to the user of the new process. On cgroup v1
* this is only about systemd's own hierarchy, i.e. not the controller hierarchies, simply because that's not
- * safe. On cgroupsv2 there's only one hierarchy anyway, and delegation is safe there, hence in that case only
+ * safe. On cgroup v2 there's only one hierarchy anyway, and delegation is safe there, hence in that case only
* touch a single hierarchy too. */
if (params->cgroup_path && context->user && (params->flags & EXEC_CGROUP_DELEGATE)) {
r = cg_set_access(SYSTEMD_CGROUP_CONTROLLER, params->cgroup_path, uid, gid);
@@ -3226,7 +3239,24 @@ static int exec_child(
#endif
}
+ if (needs_sandboxing) {
+ int which_failed;
+
+ /* Let's set the resource limits before we call into PAM, so that pam_limits wins over what
+ * is set here. (See below.) */
+
+ r = setrlimit_closest_all((const struct rlimit* const *) context->rlimit, &which_failed);
+ if (r < 0) {
+ *exit_status = EXIT_LIMITS;
+ return log_unit_error_errno(unit, r, "Failed to adjust resource limit RLIMIT_%s: %m", rlimit_to_string(which_failed));
+ }
+ }
+
if (needs_setuid) {
+
+ /* Let's call into PAM after we set up our own idea of resource limits to that pam_limits
+ * wins here. (See above.) */
+
if (context->pam_name && username) {
r = setup_pam(context->pam_name, username, uid, gid, context->tty_path, &accum_env, fds, n_fds);
if (r < 0) {
@@ -3343,15 +3373,10 @@ static int exec_child(
if (needs_sandboxing) {
uint64_t bset;
- int which_failed;
-
- r = setrlimit_closest_all((const struct rlimit* const *) context->rlimit, &which_failed);
- if (r < 0) {
- *exit_status = EXIT_LIMITS;
- return log_unit_error_errno(unit, r, "Failed to adjust resource limit RLIMIT_%s: %m", rlimit_to_string(which_failed));
- }
- /* Set the RTPRIO resource limit to 0, but only if nothing else was explicitly requested. */
+ /* Set the RTPRIO resource limit to 0, but only if nothing else was explicitly
+ * requested. (Note this is placed after the general resource limit initialization, see
+ * above, in order to take precedence.) */
if (context->restrict_realtime && !context->rlimit[RLIMIT_RTPRIO]) {
if (setrlimit(RLIMIT_RTPRIO, &RLIMIT_MAKE_CONST(0)) < 0) {
*exit_status = EXIT_LIMITS;
@@ -3942,7 +3967,7 @@ const char* exec_context_fdname(const ExecContext *c, int fd_index) {
}
}
-static int exec_context_named_iofds(const ExecContext *c, const ExecParameters *p, int named_iofds[3]) {
+static int exec_context_named_iofds(const ExecContext *c, const ExecParameters *p, int named_iofds[static 3]) {
size_t i, targets;
const char* stdio_fdname[3];
size_t n_fds;
diff --git a/src/core/job.c b/src/core/job.c
index f635b7e933..59bb9d2162 100644
--- a/src/core/job.c
+++ b/src/core/job.c
@@ -151,6 +151,8 @@ void job_uninstall(Job *j) {
unit_add_to_gc_queue(j->unit);
+ unit_add_to_dbus_queue(j->unit); /* The Job property of the unit has changed now */
+
hashmap_remove_value(j->manager->jobs, UINT32_TO_PTR(j->id), j);
j->installed = false;
}
@@ -206,8 +208,9 @@ Job* job_install(Job *j) {
(job_type_allows_late_merge(j->type) && job_type_is_superset(uj->type, j->type))) {
job_merge_into_installed(uj, j);
log_unit_debug(uj->unit,
- "Merged into installed job %s/%s as %u",
- uj->unit->id, job_type_to_string(uj->type), (unsigned) uj->id);
+ "Merged %s/%s into installed job %s/%s as %"PRIu32,
+ j->unit->id, job_type_to_string(j->type), uj->unit->id,
+ job_type_to_string(uj->type), uj->id);
return uj;
} else {
/* already running and not safe to merge into */
@@ -216,8 +219,8 @@ Job* job_install(Job *j) {
* not currently possible to have more than one installed job per unit. */
job_merge_into_installed(uj, j);
log_unit_debug(uj->unit,
- "Merged into running job, re-running: %s/%s as %u",
- uj->unit->id, job_type_to_string(uj->type), (unsigned) uj->id);
+ "Merged into running job, re-running: %s/%s as %"PRIu32,
+ uj->unit->id, job_type_to_string(uj->type), uj->id);
job_set_state(uj, JOB_WAITING);
return uj;
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index 4ebe92fd45..44f00a3046 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -3749,7 +3749,7 @@ int config_parse_exec_directories(
if (path_startswith(k, "private")) {
log_syntax(unit, LOG_ERR, filename, line, 0,
- "%s= path can't be 'private', ingoring assignment: %s", lvalue, word);
+ "%s= path can't be 'private', ignoring assignment: %s", lvalue, word);
continue;
}
@@ -4254,6 +4254,12 @@ int config_parse_pid_file(
assert(rvalue);
assert(u);
+ if (isempty(rvalue)) {
+ /* An empty assignment removes already set value. */
+ *s = mfree(*s);
+ return 0;
+ }
+
r = unit_full_printf(u, rvalue, &k);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue);
diff --git a/src/core/locale-setup.c b/src/core/locale-setup.c
index 584fb220a1..aa4a89c17a 100644
--- a/src/core/locale-setup.c
+++ b/src/core/locale-setup.c
@@ -74,9 +74,9 @@ int locale_setup(char ***environment) {
}
if (strv_isempty(add)) {
- /* If no locale is configured then default to C.UTF-8. */
+ /* If no locale is configured then default to compile-time default. */
- add = strv_new("LANG=C.UTF-8");
+ add = strv_new("LANG=" SYSTEMD_DEFAULT_LOCALE);
if (!add)
return -ENOMEM;
}
diff --git a/src/core/macros.systemd.in b/src/core/macros.systemd.in
index 9ccad5ebfe..d9e7f573ba 100644
--- a/src/core/macros.systemd.in
+++ b/src/core/macros.systemd.in
@@ -43,7 +43,7 @@ OrderWithRequires(postun): systemd \
%systemd_post() \
if [ $1 -eq 1 ] ; then \
# Initial installation \
- systemctl --no-reload preset %{?*} &>/dev/null || : \
+ systemctl --no-reload preset %{?*} >/dev/null 2>&1 || : \
fi \
%{nil}
@@ -52,14 +52,14 @@ fi \
%systemd_preun() \
if [ $1 -eq 0 ] ; then \
# Package removal, not upgrade \
- systemctl --no-reload disable --now %{?*} &>/dev/null || : \
+ systemctl --no-reload disable --now %{?*} >/dev/null 2>&1 || : \
fi \
%{nil}
%systemd_user_preun() \
if [ $1 -eq 0 ] ; then \
# Package removal, not upgrade \
- systemctl --global disable %{?*} &>/dev/null || : \
+ systemctl --global disable %{?*} >/dev/null 2>&1 || : \
fi \
%{nil}
@@ -70,7 +70,7 @@ fi \
%systemd_postun_with_restart() \
if [ $1 -ge 1 ] ; then \
# Package upgrade, not uninstall \
- systemctl try-restart %{?*} &>/dev/null || : \
+ systemctl try-restart %{?*} >/dev/null 2>&1 || : \
fi \
%{nil}
@@ -84,16 +84,16 @@ fi \
# Deprecated. Use %tmpfiles_create_package instead
%tmpfiles_create() \
-systemd-tmpfiles --create %{?*} &>/dev/null || : \
+systemd-tmpfiles --create %{?*} >/dev/null 2>&1 || : \
%{nil}
# Deprecated. Use %sysusers_create_package instead
%sysusers_create() \
-systemd-sysusers %{?*} &>/dev/null || : \
+systemd-sysusers %{?*} >/dev/null 2>&1 || : \
%{nil}
%sysusers_create_inline() \
-systemd-sysusers - <<SYSTEMD_INLINE_EOF &>/dev/null || : \
+systemd-sysusers - <<SYSTEMD_INLINE_EOF >/dev/null 2>&1 || : \
%{?*} \
SYSTEMD_INLINE_EOF \
%{nil}
@@ -112,7 +112,7 @@ SYSTEMD_INLINE_EOF \
# %files
# %{_sysusersdir}/%{name}.conf
%sysusers_create_package() \
-systemd-sysusers --replace=%_sysusersdir/%1.conf - <<SYSTEMD_INLINE_EOF &>/dev/null || : \
+systemd-sysusers --replace=%_sysusersdir/%1.conf - <<SYSTEMD_INLINE_EOF >/dev/null 2>&1 || : \
%(cat %2) \
SYSTEMD_INLINE_EOF \
%{nil}
@@ -131,15 +131,15 @@ SYSTEMD_INLINE_EOF \
# %files
# %{_tmpfilesdir}/%{name}.conf
%tmpfiles_create_package() \
-systemd-tmpfiles --replace=%_tmpfilesdir/%1.conf --create - <<SYSTEMD_INLINE_EOF &>/dev/null || : \
+systemd-tmpfiles --replace=%_tmpfilesdir/%1.conf --create - <<SYSTEMD_INLINE_EOF >/dev/null 2>&1 || : \
%(cat %2) \
SYSTEMD_INLINE_EOF \
%{nil}
%sysctl_apply() \
-@rootlibexecdir@/systemd-sysctl %{?*} &>/dev/null || : \
+@rootlibexecdir@/systemd-sysctl %{?*} >/dev/null 2>&1 || : \
%{nil}
%binfmt_apply() \
-@rootlibexecdir@/systemd-binfmt %{?*} &>/dev/null || : \
+@rootlibexecdir@/systemd-binfmt %{?*} >/dev/null 2>&1 || : \
%{nil}
diff --git a/src/core/main.c b/src/core/main.c
index 839dc062ff..561f956f0a 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -83,6 +83,10 @@
#include "virt.h"
#include "watchdog.h"
+#if HAS_FEATURE_ADDRESS_SANITIZER
+#include <sanitizer/lsan_interface.h>
+#endif
+
static enum {
ACTION_RUN,
ACTION_HELP,
@@ -1265,6 +1269,7 @@ static void bump_file_max_and_nr_open(void) {
}
static int bump_rlimit_nofile(struct rlimit *saved_rlimit) {
+ struct rlimit new_rlimit;
int r, nr;
assert(saved_rlimit);
@@ -1299,12 +1304,30 @@ static int bump_rlimit_nofile(struct rlimit *saved_rlimit) {
if (arg_system)
rl->rlim_max = MIN((rlim_t) nr, MAX(rl->rlim_max, (rlim_t) HIGH_RLIMIT_NOFILE));
+ /* If for some reason we were invoked with a soft limit above 1024 (which should never
+ * happen!, but who knows what we get passed in from pam_limit when invoked as --user
+ * instance), then lower what we pass on to not confuse our children */
+ rl->rlim_cur = MIN(rl->rlim_cur, (rlim_t) FD_SETSIZE);
+
arg_default_rlimit[RLIMIT_NOFILE] = rl;
}
+ /* Calculate the new limits to use for us. Never lower from what we inherited. */
+ new_rlimit = (struct rlimit) {
+ .rlim_cur = MAX((rlim_t) nr, saved_rlimit->rlim_cur),
+ .rlim_max = MAX((rlim_t) nr, saved_rlimit->rlim_max),
+ };
+
+ /* Shortcut if nothing changes. */
+ if (saved_rlimit->rlim_max >= new_rlimit.rlim_max &&
+ saved_rlimit->rlim_cur >= new_rlimit.rlim_cur) {
+ log_debug("RLIMIT_NOFILE is already as high or higher than we need it, not bumping.");
+ return 0;
+ }
+
/* Bump up the resource limit for ourselves substantially, all the way to the maximum the kernel allows, for
* both hard and soft. */
- r = setrlimit_closest(RLIMIT_NOFILE, &RLIMIT_MAKE_CONST(nr));
+ r = setrlimit_closest(RLIMIT_NOFILE, &new_rlimit);
if (r < 0)
return log_warning_errno(r, "Setting RLIMIT_NOFILE failed, ignoring: %m");
@@ -1312,6 +1335,7 @@ static int bump_rlimit_nofile(struct rlimit *saved_rlimit) {
}
static int bump_rlimit_memlock(struct rlimit *saved_rlimit) {
+ struct rlimit new_rlimit;
int r;
assert(saved_rlimit);
@@ -1323,7 +1347,33 @@ static int bump_rlimit_memlock(struct rlimit *saved_rlimit) {
if (getrlimit(RLIMIT_MEMLOCK, saved_rlimit) < 0)
return log_warning_errno(errno, "Reading RLIMIT_MEMLOCK failed, ignoring: %m");
- r = setrlimit_closest(RLIMIT_MEMLOCK, &RLIMIT_MAKE_CONST(HIGH_RLIMIT_MEMLOCK));
+ /* Pass the original value down to invoked processes */
+ if (!arg_default_rlimit[RLIMIT_MEMLOCK]) {
+ struct rlimit *rl;
+
+ rl = newdup(struct rlimit, saved_rlimit, 1);
+ if (!rl)
+ return log_oom();
+
+ arg_default_rlimit[RLIMIT_MEMLOCK] = rl;
+ }
+
+ /* Using MAX() on resource limits only is safe if RLIM_INFINITY is > 0. POSIX declares that rlim_t
+ * must be unsigned, hence this is a given, but let's make this clear here. */
+ assert_cc(RLIM_INFINITY > 0);
+
+ new_rlimit = (struct rlimit) {
+ .rlim_cur = MAX(HIGH_RLIMIT_MEMLOCK, saved_rlimit->rlim_cur),
+ .rlim_max = MAX(HIGH_RLIMIT_MEMLOCK, saved_rlimit->rlim_max),
+ };
+
+ if (saved_rlimit->rlim_max >= new_rlimit.rlim_cur &&
+ saved_rlimit->rlim_cur >= new_rlimit.rlim_max) {
+ log_debug("RLIMIT_MEMLOCK is already as high or higher than we need it, not bumping.");
+ return 0;
+ }
+
+ r = setrlimit_closest(RLIMIT_MEMLOCK, &new_rlimit);
if (r < 0)
return log_warning_errno(r, "Setting RLIMIT_MEMLOCK failed, ignoring: %m");
@@ -1660,12 +1710,11 @@ static void do_reexecute(
* we do that */
watchdog_close(true);
- /* Reset the RLIMIT_NOFILE to the kernel default, so that the new systemd can pass the kernel default to its
- * child processes */
-
- if (saved_rlimit_nofile->rlim_cur > 0)
+ /* Reset RLIMIT_NOFILE + RLIMIT_MEMLOCK back to the kernel defaults, so that the new systemd can pass
+ * the kernel default to its child processes */
+ if (saved_rlimit_nofile->rlim_cur != 0)
(void) setrlimit(RLIMIT_NOFILE, saved_rlimit_nofile);
- if (saved_rlimit_memlock->rlim_cur != (rlim_t) -1)
+ if (saved_rlimit_memlock->rlim_cur != RLIM_INFINITY)
(void) setrlimit(RLIMIT_MEMLOCK, saved_rlimit_memlock);
if (switch_root_dir) {
@@ -1914,7 +1963,7 @@ static void log_execution_mode(bool *ret_first_boot) {
if (arg_system) {
int v;
- log_info(PACKAGE_STRING " running in %ssystem mode. (" SYSTEMD_FEATURES ")",
+ log_info("systemd " GIT_VERSION " running in %ssystem mode. (" SYSTEMD_FEATURES ")",
arg_action == ACTION_TEST ? "test " : "" );
v = detect_virtualization();
@@ -1942,7 +1991,7 @@ static void log_execution_mode(bool *ret_first_boot) {
_cleanup_free_ char *t;
t = uid_to_name(getuid());
- log_debug(PACKAGE_STRING " running in %suser mode for user " UID_FMT "/%s. (" SYSTEMD_FEATURES ")",
+ log_debug("systemd " GIT_VERSION " running in %suser mode for user " UID_FMT "/%s. (" SYSTEMD_FEATURES ")",
arg_action == ACTION_TEST ? " test" : "", getuid(), strna(t));
}
@@ -2298,7 +2347,11 @@ int main(int argc, char *argv[]) {
dual_timestamp initrd_timestamp = DUAL_TIMESTAMP_NULL, userspace_timestamp = DUAL_TIMESTAMP_NULL, kernel_timestamp = DUAL_TIMESTAMP_NULL,
security_start_timestamp = DUAL_TIMESTAMP_NULL, security_finish_timestamp = DUAL_TIMESTAMP_NULL;
- struct rlimit saved_rlimit_nofile = RLIMIT_MAKE_CONST(0), saved_rlimit_memlock = RLIMIT_MAKE_CONST((rlim_t) -1);
+ struct rlimit saved_rlimit_nofile = RLIMIT_MAKE_CONST(0),
+ saved_rlimit_memlock = RLIMIT_MAKE_CONST(RLIM_INFINITY); /* The original rlimits we passed
+ * in. Note we use different values
+ * for the two that indicate whether
+ * these fields are initialized! */
bool skip_setup, loaded_policy = false, queue_default_job = false, first_boot = false, reexecute = false;
char *switch_root_dir = NULL, *switch_root_init = NULL;
usec_t before_startup, after_startup;
@@ -2612,6 +2665,10 @@ finish:
}
#endif
+#if HAS_FEATURE_ADDRESS_SANITIZER
+ __lsan_do_leak_check();
+#endif
+
if (shutdown_verb) {
r = become_shutdown(shutdown_verb, retval);
log_error_errno(r, "Failed to execute shutdown binary, %s: %m", getpid_cached() == 1 ? "freezing" : "quitting");
diff --git a/src/core/manager.c b/src/core/manager.c
index 35d9753b12..6086531bab 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -3243,11 +3243,11 @@ static int manager_deserialize_one_unit(Manager *m, const char *name, FILE *f, F
}
static int manager_deserialize_units(Manager *m, FILE *f, FDSet *fds) {
- _cleanup_free_ char *line = NULL;
const char *unit_name;
int r;
for (;;) {
+ _cleanup_free_ char *line = NULL;
/* Start marker */
r = read_line(f, LONG_LINE_MAX, &line);
if (r < 0)
diff --git a/src/core/meson.build b/src/core/meson.build
index 450d6f72a9..85021bdc01 100644
--- a/src/core/meson.build
+++ b/src/core/meson.build
@@ -173,26 +173,19 @@ systemd_shutdown_sources = files('''
'''.split())
in_files = [['macros.systemd', rpmmacrosdir],
- ['triggers.systemd', ''],
+ ['system.conf', pkgsysconfdir],
['systemd.pc', pkgconfigdatadir],
- ['system.conf', pkgsysconfdir]]
+ ['triggers.systemd', '']]
foreach item : in_files
file = item[0]
dir = item[1]
- # If 'no', disable generation completely.
- # If '', generate, but do not install.
- if dir != 'no'
- gen = configure_file(
- input : file + '.in',
- output : file,
- configuration : substs)
- if dir != ''
- install_data(gen,
- install_dir : dir)
- endif
- endif
+ configure_file(
+ input : file + '.in',
+ output : file,
+ configuration : substs,
+ install_dir : dir == 'no' ? '' : dir)
endforeach
install_data('org.freedesktop.systemd1.conf',
diff --git a/src/core/mount.c b/src/core/mount.c
index ead9bc1f44..c31cad6b52 100644
--- a/src/core/mount.c
+++ b/src/core/mount.c
@@ -251,6 +251,32 @@ _pure_ static MountParameters* get_mount_parameters(Mount *m) {
return get_mount_parameters_fragment(m);
}
+static int update_parameters_proc_self_mount_info(
+ Mount *m,
+ const char *what,
+ const char *options,
+ const char *fstype) {
+
+ MountParameters *p;
+ int r, q, w;
+
+ p = &m->parameters_proc_self_mountinfo;
+
+ r = free_and_strdup(&p->what, what);
+ if (r < 0)
+ return r;
+
+ q = free_and_strdup(&p->options, options);
+ if (q < 0)
+ return q;
+
+ w = free_and_strdup(&p->fstype, fstype);
+ if (w < 0)
+ return w;
+
+ return r > 0 || q > 0 || w > 0;
+}
+
static int mount_add_mount_dependencies(Mount *m) {
MountParameters *pm;
Unit *other;
@@ -352,7 +378,8 @@ static int mount_add_device_dependencies(Mount *m) {
* automatically stopped when the device disappears suddenly. */
dep = mount_is_bound_to_device(m) ? UNIT_BINDS_TO : UNIT_REQUIRES;
- mask = m->from_fragment ? UNIT_DEPENDENCY_FILE : UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT;
+ /* We always use 'what' from /proc/self/mountinfo if mounted */
+ mask = m->from_proc_self_mountinfo ? UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT : UNIT_DEPENDENCY_FILE;
r = unit_add_node_dependency(UNIT(m), p->what, device_wants_mount, dep, mask);
if (r < 0)
@@ -426,6 +453,7 @@ static int mount_add_default_dependencies(Mount *m) {
const char *after, *before;
UnitDependencyMask mask;
MountParameters *p;
+ bool nofail;
int r;
assert(m);
@@ -444,6 +472,7 @@ static int mount_add_default_dependencies(Mount *m) {
return 0;
mask = m->from_fragment ? UNIT_DEPENDENCY_FILE : UNIT_DEPENDENCY_MOUNTINFO_DEFAULT;
+ nofail = m->from_fragment ? fstab_test_yes_no_option(m->parameters_fragment.options, "nofail\0" "fail\0") : false;
if (mount_is_network(p)) {
/* We order ourselves after network.target. This is
@@ -474,9 +503,11 @@ static int mount_add_default_dependencies(Mount *m) {
before = SPECIAL_LOCAL_FS_TARGET;
}
- r = unit_add_dependency_by_name(UNIT(m), UNIT_BEFORE, before, true, mask);
- if (r < 0)
- return r;
+ if (!nofail) {
+ r = unit_add_dependency_by_name(UNIT(m), UNIT_BEFORE, before, true, mask);
+ if (r < 0)
+ return r;
+ }
r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, after, true, mask);
if (r < 0)
@@ -733,7 +764,7 @@ static void mount_dump(Unit *u, FILE *f, const char *prefix) {
"%sSloppyOptions: %s\n"
"%sLazyUnmount: %s\n"
"%sForceUnmount: %s\n"
- "%sTimoutSec: %s\n",
+ "%sTimeoutSec: %s\n",
prefix, mount_state_to_string(m->state),
prefix, mount_result_to_string(m->result),
prefix, m->where,
@@ -823,6 +854,9 @@ static void mount_enter_dead(Mount *m, MountResult f) {
unit_unref_uid_gid(UNIT(m), true);
dynamic_creds_destroy(&m->dynamic_creds);
+
+ /* Any dependencies based on /proc/self/mountinfo are now stale */
+ unit_remove_dependencies(UNIT(m), UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT);
}
static void mount_enter_mounted(Mount *m, MountResult f) {
@@ -1428,32 +1462,6 @@ static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *user
return 0;
}
-static int update_parameters_proc_self_mount_info(
- Mount *m,
- const char *what,
- const char *options,
- const char *fstype) {
-
- MountParameters *p;
- int r, q, w;
-
- p = &m->parameters_proc_self_mountinfo;
-
- r = free_and_strdup(&p->what, what);
- if (r < 0)
- return r;
-
- q = free_and_strdup(&p->options, options);
- if (q < 0)
- return q;
-
- w = free_and_strdup(&p->fstype, fstype);
- if (w < 0)
- return w;
-
- return r > 0 || q > 0 || w > 0;
-}
-
static int mount_setup_new_unit(
Manager *m,
const char *name,
@@ -1528,10 +1536,10 @@ static int mount_setup_existing_unit(
if (r > 0)
flags |= MOUNT_PROC_JUST_CHANGED;
- if (!MOUNT(u)->from_proc_self_mountinfo) {
+ if (!MOUNT(u)->from_proc_self_mountinfo || FLAGS_SET(MOUNT(u)->proc_flags, MOUNT_PROC_JUST_MOUNTED))
flags |= MOUNT_PROC_JUST_MOUNTED;
- MOUNT(u)->from_proc_self_mountinfo = true;
- }
+
+ MOUNT(u)->from_proc_self_mountinfo = true;
if (IN_SET(u->load_state, UNIT_NOT_FOUND, UNIT_BAD_SETTING, UNIT_ERROR)) {
/* The unit was previously not found or otherwise not loaded. Now that the unit shows up in
@@ -1844,6 +1852,7 @@ static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents,
}
mount->from_proc_self_mountinfo = false;
+ assert_se(update_parameters_proc_self_mount_info(mount, NULL, NULL, NULL) >= 0);
switch (mount->state) {
diff --git a/src/core/namespace.c b/src/core/namespace.c
index c2ca3e0334..7f553a42c2 100644
--- a/src/core/namespace.c
+++ b/src/core/namespace.c
@@ -1628,7 +1628,7 @@ int setup_tmp_dirs(const char *id, char **tmp_dir, char **var_tmp_dir) {
return 0;
}
-int setup_netns(int netns_storage_socket[2]) {
+int setup_netns(int netns_storage_socket[static 2]) {
_cleanup_close_ int netns = -1;
int r, q;
diff --git a/src/core/namespace.h b/src/core/namespace.h
index 1188c6d595..5e0ec97969 100644
--- a/src/core/namespace.h
+++ b/src/core/namespace.h
@@ -91,7 +91,7 @@ int setup_tmp_dirs(
char **tmp_dir,
char **var_tmp_dir);
-int setup_netns(int netns_storage_socket[2]);
+int setup_netns(int netns_storage_socket[static 2]);
const char* protect_home_to_string(ProtectHome p) _const_;
ProtectHome protect_home_from_string(const char *s) _pure_;
diff --git a/src/core/service.c b/src/core/service.c
index cfa3271232..324dcf2311 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -2154,7 +2154,7 @@ static void service_enter_restart(Service *s) {
* restarted. We use JOB_RESTART (instead of the more obvious
* JOB_START) here so that those dependency jobs will be added
* as well. */
- r = manager_add_job(UNIT(s)->manager, JOB_RESTART, UNIT(s), JOB_FAIL, &error, NULL);
+ r = manager_add_job(UNIT(s)->manager, JOB_RESTART, UNIT(s), JOB_REPLACE, &error, NULL);
if (r < 0)
goto fail;
diff --git a/src/core/socket.c b/src/core/socket.c
index dd126a7f21..af95e9027e 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -561,7 +561,7 @@ int socket_acquire_peer(Socket *s, int fd, SocketPeer **p) {
r = getpeername(fd, &sa.peer.sa, &salen);
if (r < 0)
- return log_error_errno(errno, "getpeername failed: %m");
+ return log_unit_error_errno(UNIT(s), errno, "getpeername failed: %m");
if (!IN_SET(sa.peer.sa.sa_family, AF_INET, AF_INET6, AF_VSOCK)) {
*p = NULL;
@@ -1465,6 +1465,14 @@ static int socket_address_listen_do(
label);
}
+#define log_address_error_errno(u, address, error, fmt) \
+ ({ \
+ _cleanup_free_ char *_t = NULL; \
+ \
+ (void) socket_address_print(address, &_t); \
+ log_unit_error_errno(u, error, fmt, strna(_t)); \
+ })
+
static int socket_address_listen_in_cgroup(
Socket *s,
const SocketAddress *address,
@@ -1503,13 +1511,13 @@ static int socket_address_listen_in_cgroup(
fd = socket_address_listen_do(s, address, label);
if (fd < 0) {
- log_unit_error_errno(UNIT(s), fd, "Failed to create listening socket: %m");
+ log_address_error_errno(UNIT(s), address, fd, "Failed to create listening socket (%s): %m");
_exit(EXIT_FAILURE);
}
r = send_one_fd(pair[1], fd, 0);
if (r < 0) {
- log_unit_error_errno(UNIT(s), r, "Failed to send listening socket to parent: %m");
+ log_address_error_errno(UNIT(s), address, r, "Failed to send listening socket (%s) to parent: %m");
_exit(EXIT_FAILURE);
}
@@ -1527,19 +1535,22 @@ static int socket_address_listen_in_cgroup(
}
if (fd < 0)
- return log_unit_error_errno(UNIT(s), fd, "Failed to receive listening socket: %m");
+ return log_address_error_errno(UNIT(s), address, fd, "Failed to receive listening socket (%s): %m");
return fd;
shortcut:
fd = socket_address_listen_do(s, address, label);
if (fd < 0)
- return log_error_errno(fd, "Failed to create listening socket: %m");
+ return log_address_error_errno(UNIT(s), address, fd, "Failed to create listening socket (%s): %m");
return fd;
}
-static int socket_open_fds(Socket *s) {
+DEFINE_TRIVIAL_CLEANUP_FUNC(Socket *, socket_close_fds);
+
+static int socket_open_fds(Socket *_s) {
+ _cleanup_(socket_close_fdsp) Socket *s = _s;
_cleanup_(mac_selinux_freep) char *label = NULL;
bool know_label = false;
SocketPort *p;
@@ -1562,7 +1573,7 @@ static int socket_open_fds(Socket *s) {
r = socket_determine_selinux_label(s, &label);
if (r < 0)
- goto rollback;
+ return log_unit_error_errno(UNIT(s), r, "Failed to determine SELinux label: %m");
know_label = true;
}
@@ -1582,11 +1593,10 @@ static int socket_open_fds(Socket *s) {
break;
}
- r = socket_address_listen_in_cgroup(s, &p->address, label);
- if (r < 0)
- goto rollback;
+ p->fd = socket_address_listen_in_cgroup(s, &p->address, label);
+ if (p->fd < 0)
+ return p->fd;
- p->fd = r;
socket_apply_socket_options(s, p->fd);
socket_symlink(s);
break;
@@ -1594,10 +1604,8 @@ static int socket_open_fds(Socket *s) {
case SOCKET_SPECIAL:
p->fd = special_address_create(p->path, s->writable);
- if (p->fd < 0) {
- r = p->fd;
- goto rollback;
- }
+ if (p->fd < 0)
+ return log_unit_error_errno(UNIT(s), p->fd, "Failed to open special file %s: %m", p->path);
break;
case SOCKET_FIFO:
@@ -1606,10 +1614,8 @@ static int socket_open_fds(Socket *s) {
p->path,
s->directory_mode,
s->socket_mode);
- if (p->fd < 0) {
- r = p->fd;
- goto rollback;
- }
+ if (p->fd < 0)
+ return log_unit_error_errno(UNIT(s), p->fd, "Failed to open FIFO %s: %m", p->path);
socket_apply_fifo_options(s, p->fd);
socket_symlink(s);
@@ -1622,10 +1628,8 @@ static int socket_open_fds(Socket *s) {
s->socket_mode,
s->mq_maxmsg,
s->mq_msgsize);
- if (p->fd < 0) {
- r = p->fd;
- goto rollback;
- }
+ if (p->fd < 0)
+ return log_unit_error_errno(UNIT(s), p->fd, "Failed to open message queue %s: %m", p->path);
break;
case SOCKET_USB_FUNCTION: {
@@ -1634,18 +1638,16 @@ static int socket_open_fds(Socket *s) {
ep = path_make_absolute("ep0", p->path);
p->fd = usbffs_address_create(ep);
- if (p->fd < 0) {
- r = p->fd;
- goto rollback;
- }
+ if (p->fd < 0)
+ return p->fd;
r = usbffs_write_descs(p->fd, SERVICE(UNIT_DEREF(s->service)));
if (r < 0)
- goto rollback;
+ return r;
r = usbffs_dispatch_eps(p);
if (r < 0)
- goto rollback;
+ return r;
break;
}
@@ -1654,11 +1656,8 @@ static int socket_open_fds(Socket *s) {
}
}
+ s = NULL;
return 0;
-
-rollback:
- socket_close_fds(s);
- return r;
}
static void socket_unwatch_fds(Socket *s) {
@@ -2521,14 +2520,14 @@ static int socket_serialize(Unit *u, FILE *f, FDSet *fds) {
copy = fdset_put_dup(fds, p->fd);
if (copy < 0)
- return log_warning_errno(copy, "Failed to serialize socket fd: %m");
+ return log_unit_warning_errno(u, copy, "Failed to serialize socket fd: %m");
if (p->type == SOCKET_SOCKET) {
_cleanup_free_ char *t = NULL;
r = socket_address_print(&p->address, &t);
if (r < 0)
- return log_error_errno(r, "Failed to format socket address: %m");
+ return log_unit_error_errno(u, r, "Failed to format socket address: %m");
if (socket_address_family(&p->address) == AF_NETLINK)
(void) serialize_item_format(f, "netlink", "%i %s", copy, t);
diff --git a/src/core/systemd.pc.in b/src/core/systemd.pc.in
index 655773ea8a..0dae950473 100644
--- a/src/core/systemd.pc.in
+++ b/src/core/systemd.pc.in
@@ -36,5 +36,5 @@ containeruidbasemax=@containeruidbasemax@
Name: systemd
Description: systemd System and Service Manager
-URL: @PACKAGE_URL@
-Version: @PACKAGE_VERSION@
+URL: @PROJECT_URL@
+Version: @PROJECT_VERSION@
diff --git a/src/core/transaction.c b/src/core/transaction.c
index 486c6a4a05..2418332b9a 100644
--- a/src/core/transaction.c
+++ b/src/core/transaction.c
@@ -300,7 +300,7 @@ rescan:
goto next_unit;
}
- /* log_debug("Found redundant job %s/%s, dropping.", j->unit->id, job_type_to_string(j->type)); */
+ log_trace("Found redundant job %s/%s, dropping from transaction.", j->unit->id, job_type_to_string(j->type));
transaction_delete_job(tr, j, false);
goto rescan;
next_unit:;
@@ -494,15 +494,17 @@ static void transaction_collect_garbage(Transaction *tr) {
rescan:
HASHMAP_FOREACH(j, tr->jobs, i) {
- if (tr->anchor_job == j || j->object_list) {
- /* log_debug("Keeping job %s/%s because of %s/%s", */
- /* j->unit->id, job_type_to_string(j->type), */
- /* j->object_list->subject ? j->object_list->subject->unit->id : "root", */
- /* j->object_list->subject ? job_type_to_string(j->object_list->subject->type) : "root"); */
+ if (tr->anchor_job == j)
+ continue;
+ if (j->object_list) {
+ log_trace("Keeping job %s/%s because of %s/%s",
+ j->unit->id, job_type_to_string(j->type),
+ j->object_list->subject ? j->object_list->subject->unit->id : "root",
+ j->object_list->subject ? job_type_to_string(j->object_list->subject->type) : "root");
continue;
}
- /* log_debug("Garbage collecting job %s/%s", j->unit->id, job_type_to_string(j->type)); */
+ log_trace("Garbage collecting job %s/%s", j->unit->id, job_type_to_string(j->type));
transaction_delete_job(tr, j, true);
goto rescan;
}
@@ -798,7 +800,7 @@ static Job* transaction_add_one_job(Transaction *tr, JobType type, Unit *unit, b
if (is_new)
*is_new = true;
- /* log_debug("Added job %s/%s to transaction.", unit->id, job_type_to_string(type)); */
+ log_trace("Added job %s/%s to transaction.", unit->id, job_type_to_string(type));
return j;
}
@@ -892,10 +894,8 @@ int transaction_add_job_and_dependencies(
if (MANAGER_IS_RELOADING(unit->manager))
unit_coldplug(unit);
- /* log_debug("Pulling in %s/%s from %s/%s", */
- /* unit->id, job_type_to_string(type), */
- /* by ? by->unit->id : "NA", */
- /* by ? job_type_to_string(by->type) : "NA"); */
+ if (by)
+ log_trace("Pulling in %s/%s from %s/%s", unit->id, job_type_to_string(type), by->unit->id, job_type_to_string(by->type));
/* Safety check that the unit is a valid state, i.e. not in UNIT_STUB or UNIT_MERGED which should only be set
* temporarily. */
@@ -1053,7 +1053,7 @@ int transaction_add_job_and_dependencies(
if (type == JOB_RELOAD)
transaction_add_propagate_reload_jobs(tr, ret->unit, ret, ignore_order, e);
- /* JOB_VERIFY_STARTED require no dependency handling */
+ /* JOB_VERIFY_ACTIVE requires no dependency handling */
}
return 0;
diff --git a/src/core/unit-printf.c b/src/core/unit-printf.c
index a8e84ebe80..72391ace3a 100644
--- a/src/core/unit-printf.c
+++ b/src/core/unit-printf.c
@@ -195,6 +195,7 @@ int unit_name_printf(Unit *u, const char* format, char **ret) {
{ 'N', specifier_prefix_and_instance, NULL },
{ 'p', specifier_prefix, NULL },
{ 'i', specifier_string, u->instance },
+ { 'j', specifier_last_component, NULL },
{ 'g', specifier_group_name, NULL },
{ 'G', specifier_group_id, NULL },
diff --git a/src/core/unit.h b/src/core/unit.h
index 6fd39eaca3..43cf15715a 100644
--- a/src/core/unit.h
+++ b/src/core/unit.h
@@ -248,8 +248,8 @@ typedef struct Unit {
/* Counterparts in the cgroup filesystem */
char *cgroup_path;
- CGroupMask cgroup_realized_mask; /* In which hierarchies does this unit's cgroup exist? (only relevant on cgroupsv1) */
- CGroupMask cgroup_enabled_mask; /* Which controllers are enabled (or more correctly: enabled for the children) for this unit's cgroup? (only relevant on cgroupsv2) */
+ CGroupMask cgroup_realized_mask; /* In which hierarchies does this unit's cgroup exist? (only relevant on cgroup v1) */
+ CGroupMask cgroup_enabled_mask; /* Which controllers are enabled (or more correctly: enabled for the children) for this unit's cgroup? (only relevant on cgroup v2) */
CGroupMask cgroup_invalidated_mask; /* A mask specifiying controllers which shall be considered invalidated, and require re-realization */
CGroupMask cgroup_members_mask; /* A cache for the controllers required by all children of this cgroup (only relevant for slice units) */
int cgroup_inotify_wd;
diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c
index 0c888b26f9..ecbb4bffc9 100644
--- a/src/coredump/coredump.c
+++ b/src/coredump/coredump.c
@@ -142,7 +142,7 @@ static int parse_config(void) {
CONFIG_PARSE_WARN, NULL);
}
-static inline uint64_t storage_size_max(void) {
+static uint64_t storage_size_max(void) {
if (arg_storage == COREDUMP_STORAGE_EXTERNAL)
return arg_external_size_max;
if (arg_storage == COREDUMP_STORAGE_JOURNAL)
@@ -229,7 +229,7 @@ static int fix_xattr(int fd, const char *context[_CONTEXT_MAX]) {
#define filename_escape(s) xescape((s), "./ ")
-static inline const char *coredump_tmpfile_name(const char *s) {
+static const char *coredump_tmpfile_name(const char *s) {
return s ? s : "(unnamed temporary file)";
}
@@ -794,15 +794,16 @@ log:
core_message = strjoin("MESSAGE=Process ", context[CONTEXT_PID],
" (", context[CONTEXT_COMM], ") of user ",
context[CONTEXT_UID], " dumped core.",
- journald_crash ? "\nCoredump diverted to " : NULL,
- journald_crash ? filename : NULL);
+ journald_crash && filename ? "\nCoredump diverted to " : NULL,
+ journald_crash && filename ? filename : NULL);
if (!core_message)
return log_oom();
if (journald_crash) {
- /* We cannot log to the journal, so just print the MESSAGE.
+ /* We cannot log to the journal, so just print the message.
* The target was set previously to something safe. */
- log_dispatch(LOG_ERR, 0, core_message);
+ assert(startswith(core_message, "MESSAGE="));
+ log_dispatch(LOG_ERR, 0, core_message + strlen("MESSAGE="));
return 0;
}
@@ -1062,19 +1063,10 @@ static int send_iovec(const struct iovec iovec[], size_t n_iovec, int input_fd)
return 0;
}
-static char* set_iovec_field(struct iovec *iovec, size_t *n_iovec, const char *field, const char *value) {
- char *x;
-
- x = strappend(field, value);
- if (x)
- iovec[(*n_iovec)++] = IOVEC_MAKE_STRING(x);
- return x;
-}
-
static char* set_iovec_field_free(struct iovec *iovec, size_t *n_iovec, const char *field, char *value) {
char *x;
- x = set_iovec_field(iovec, n_iovec, field, value);
+ x = set_iovec_string_field(iovec, n_iovec, field, value);
free(value);
return x;
}
@@ -1124,36 +1116,36 @@ static int gather_pid_metadata(
disable_coredumps();
}
- set_iovec_field(iovec, n_iovec, "COREDUMP_UNIT=", context[CONTEXT_UNIT]);
+ set_iovec_string_field(iovec, n_iovec, "COREDUMP_UNIT=", context[CONTEXT_UNIT]);
}
if (cg_pid_get_user_unit(pid, &t) >= 0)
set_iovec_field_free(iovec, n_iovec, "COREDUMP_USER_UNIT=", t);
/* The next few are mandatory */
- if (!set_iovec_field(iovec, n_iovec, "COREDUMP_PID=", context[CONTEXT_PID]))
+ if (!set_iovec_string_field(iovec, n_iovec, "COREDUMP_PID=", context[CONTEXT_PID]))
return log_oom();
- if (!set_iovec_field(iovec, n_iovec, "COREDUMP_UID=", context[CONTEXT_UID]))
+ if (!set_iovec_string_field(iovec, n_iovec, "COREDUMP_UID=", context[CONTEXT_UID]))
return log_oom();
- if (!set_iovec_field(iovec, n_iovec, "COREDUMP_GID=", context[CONTEXT_GID]))
+ if (!set_iovec_string_field(iovec, n_iovec, "COREDUMP_GID=", context[CONTEXT_GID]))
return log_oom();
- if (!set_iovec_field(iovec, n_iovec, "COREDUMP_SIGNAL=", context[CONTEXT_SIGNAL]))
+ if (!set_iovec_string_field(iovec, n_iovec, "COREDUMP_SIGNAL=", context[CONTEXT_SIGNAL]))
return log_oom();
- if (!set_iovec_field(iovec, n_iovec, "COREDUMP_RLIMIT=", context[CONTEXT_RLIMIT]))
+ if (!set_iovec_string_field(iovec, n_iovec, "COREDUMP_RLIMIT=", context[CONTEXT_RLIMIT]))
return log_oom();
- if (!set_iovec_field(iovec, n_iovec, "COREDUMP_HOSTNAME=", context[CONTEXT_HOSTNAME]))
+ if (!set_iovec_string_field(iovec, n_iovec, "COREDUMP_HOSTNAME=", context[CONTEXT_HOSTNAME]))
return log_oom();
- if (!set_iovec_field(iovec, n_iovec, "COREDUMP_COMM=", context[CONTEXT_COMM]))
+ if (!set_iovec_string_field(iovec, n_iovec, "COREDUMP_COMM=", context[CONTEXT_COMM]))
return log_oom();
if (context[CONTEXT_EXE] &&
- !set_iovec_field(iovec, n_iovec, "COREDUMP_EXE=", context[CONTEXT_EXE]))
+ !set_iovec_string_field(iovec, n_iovec, "COREDUMP_EXE=", context[CONTEXT_EXE]))
return log_oom();
if (sd_pid_get_session(pid, &t) >= 0)
@@ -1221,7 +1213,7 @@ static int gather_pid_metadata(
iovec[(*n_iovec)++] = IOVEC_MAKE_STRING(t);
if (safe_atoi(context[CONTEXT_SIGNAL], &signo) >= 0 && SIGNAL_VALID(signo))
- set_iovec_field(iovec, n_iovec, "COREDUMP_SIGNAL_NAME=SIG", signal_to_string(signo));
+ set_iovec_string_field(iovec, n_iovec, "COREDUMP_SIGNAL_NAME=SIG", signal_to_string(signo));
return 0; /* we successfully acquired all metadata */
}
diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c
index daf26aad70..9cb52ddf26 100644
--- a/src/cryptsetup/cryptsetup.c
+++ b/src/cryptsetup/cryptsetup.c
@@ -408,8 +408,7 @@ static int get_password(const char *vol, const char *src, usec_t until, bool acc
return log_oom();
strncpy(c, *p, arg_key_size);
- free(*p);
- *p = c;
+ free_and_replace(*p, c);
}
*ret = TAKE_PTR(passwords);
@@ -451,7 +450,7 @@ static int attach_tcrypt(
r = read_one_line_file(key_file, &passphrase);
if (r < 0) {
log_error_errno(r, "Failed to read password file '%s': %m", key_file);
- return -EAGAIN;
+ return -EAGAIN; /* log with the actual error, but return EAGAIN */
}
params.passphrase = passphrase;
@@ -461,14 +460,19 @@ static int attach_tcrypt(
r = crypt_load(cd, CRYPT_TCRYPT, &params);
if (r < 0) {
- if (key_file && r == -EPERM)
- return log_error_errno(SYNTHETIC_ERRNO(EAGAIN),
- "Failed to activate using password file '%s'.",
- key_file);
- return r;
+ if (key_file && r == -EPERM) {
+ log_error_errno(r, "Failed to activate using password file '%s'. (Key data not correct?)", key_file);
+ return -EAGAIN; /* log the actual error, but return EAGAIN */
+ }
+
+ return log_error_errno(r, "Failed to load tcrypt superblock on device %s: %m", crypt_get_device_name(cd));
}
- return crypt_activate_by_volume_key(cd, name, NULL, 0, flags);
+ r = crypt_activate_by_volume_key(cd, name, NULL, 0, flags);
+ if (r < 0)
+ return log_error_errno(r, "Failed to activate tcrypt device %s: %m", crypt_get_device_name(cd));
+
+ return 0;
}
static int attach_luks_or_plain(struct crypt_device *cd,
@@ -486,10 +490,8 @@ static int attach_luks_or_plain(struct crypt_device *cd,
if (!arg_type || STR_IN_SET(arg_type, ANY_LUKS, CRYPT_LUKS1)) {
r = crypt_load(cd, CRYPT_LUKS, NULL);
- if (r < 0) {
- log_error("crypt_load() failed on device %s.\n", crypt_get_device_name(cd));
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to load LUKS superblock on device %s: %m", crypt_get_device_name(cd));
if (data_device)
r = crypt_set_data_device(cd, data_device);
@@ -530,23 +532,16 @@ static int attach_luks_or_plain(struct crypt_device *cd,
cipher_mode = "cbc-essiv:sha256";
}
- /* for CRYPT_PLAIN limit reads
- * from keyfile to key length, and
- * ignore keyfile-size */
+ /* for CRYPT_PLAIN limit reads from keyfile to key length, and ignore keyfile-size */
arg_keyfile_size = arg_key_size;
- /* In contrast to what the name
- * crypt_setup() might suggest this
- * doesn't actually format anything,
- * it just configures encryption
- * parameters when used for plain
- * mode. */
+ /* In contrast to what the name crypt_setup() might suggest this doesn't actually format
+ * anything, it just configures encryption parameters when used for plain mode. */
r = crypt_format(cd, CRYPT_PLAIN, cipher, cipher_mode, NULL, NULL, arg_keyfile_size, &params);
/* hash == NULL implies the user passed "plain" */
pass_volume_key = (params.hash == NULL);
}
-
if (r < 0)
return log_error_errno(r, "Loading of cryptographic parameters failed: %m");
@@ -558,22 +553,30 @@ static int attach_luks_or_plain(struct crypt_device *cd,
if (key_file) {
r = crypt_activate_by_keyfile_offset(cd, name, arg_key_slot, key_file, arg_keyfile_size, arg_keyfile_offset, flags);
- if (r < 0) {
- log_error_errno(r, "Failed to activate with key file '%s': %m", key_file);
- return -EAGAIN;
+ if (r == -EPERM) {
+ log_error_errno(r, "Failed to activate with key file '%s'. (Key data incorrect?)", key_file);
+ return -EAGAIN; /* Log actual error, but return EAGAIN */
}
+ if (r < 0)
+ return log_error_errno(r, "Failed to activate with key file '%s': %m", key_file);
} else {
char **p;
+ r = -EINVAL;
STRV_FOREACH(p, passwords) {
if (pass_volume_key)
r = crypt_activate_by_volume_key(cd, name, *p, arg_key_size, flags);
else
r = crypt_activate_by_passphrase(cd, name, arg_key_slot, *p, strlen(*p), flags);
-
if (r >= 0)
break;
}
+ if (r == -EPERM) {
+ log_error_errno(r, "Failed to activate with specified passphrase. (Passphrase incorrect?)");
+ return -EAGAIN; /* log actual error, but return EAGAIN */
+ }
+ if (r < 0)
+ return log_error_errno(r, "Failed to activate with specified passphrase: %m");
}
return r;
@@ -624,10 +627,8 @@ static int run(int argc, char *argv[]) {
/* Arguments: systemd-cryptsetup attach VOLUME SOURCE-DEVICE [PASSWORD] [OPTIONS] */
- if (argc < 4) {
- log_error("attach requires at least two arguments.");
- return -EINVAL;
- }
+ if (argc < 4)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "attach requires at least two arguments.");
if (argc >= 5 &&
argv[4][0] &&
@@ -635,7 +636,7 @@ static int run(int argc, char *argv[]) {
!streq(argv[4], "none")) {
if (!path_is_absolute(argv[4]))
- log_error("Password file path '%s' is not absolute. Ignoring.", argv[4]);
+ log_warning("Password file path '%s' is not absolute. Ignoring.", argv[4]);
else
key_file = argv[4];
}
@@ -709,20 +710,15 @@ static int run(int argc, char *argv[]) {
flags);
if (r >= 0)
break;
- if (r == -EAGAIN) {
- key_file = NULL;
- continue;
- }
- if (r != -EPERM)
- return log_error_errno(r, "Failed to activate: %m");
+ if (r != -EAGAIN)
+ return r;
- log_warning("Invalid passphrase.");
+ /* Passphrase not correct? Let's try again! */
+ key_file = NULL;
}
- if (arg_tries != 0 && tries >= arg_tries) {
- log_error("Too many attempts; giving up.");
- return -EPERM;
- }
+ if (arg_tries != 0 && tries >= arg_tries)
+ return log_error_errno(SYNTHETIC_ERRNO(EPERM), "Too many attempts to activate; giving up.");
} else if (streq(argv[1], "detach")) {
@@ -740,10 +736,8 @@ static int run(int argc, char *argv[]) {
if (r < 0)
return log_error_errno(r, "Failed to deactivate: %m");
- } else {
- log_error("Unknown verb %s.", argv[1]);
- return -EINVAL;
- }
+ } else
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown verb %s.", argv[1]);
return 0;
}
diff --git a/src/fsck/fsck.c b/src/fsck/fsck.c
index ba39f596fc..524327c4da 100644
--- a/src/fsck/fsck.c
+++ b/src/fsck/fsck.c
@@ -414,7 +414,7 @@ static int run(int argc, char *argv[]) {
exit_status = wait_for_terminate_and_check("fsck", pid, WAIT_LOG_ABNORMAL);
if (exit_status < 0)
return exit_status;
- if (exit_status & ~1) {
+ if ((exit_status & ~FSCK_ERROR_CORRECTED) != FSCK_SUCCESS) {
log_error("fsck failed with exit status %i.", exit_status);
if ((exit_status & FSCK_SYSTEM_SHOULD_REBOOT) && root_directory) {
diff --git a/src/import/curl-util.c b/src/import/curl-util.c
index 05b17c3c78..7db03b2919 100644
--- a/src/import/curl-util.c
+++ b/src/import/curl-util.c
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#include "alloc-util.h"
+#include "build.h"
#include "curl-util.h"
#include "fd-util.h"
#include "locale-util.h"
@@ -283,14 +284,14 @@ int curl_glue_make(CURL **ret, const char *url, void *userdata) {
if (curl_easy_setopt(c, CURLOPT_PRIVATE, userdata) != CURLE_OK)
return -EIO;
- useragent = strjoina(program_invocation_short_name, "/" PACKAGE_VERSION);
+ useragent = strjoina(program_invocation_short_name, "/" GIT_VERSION);
if (curl_easy_setopt(c, CURLOPT_USERAGENT, useragent) != CURLE_OK)
return -EIO;
if (curl_easy_setopt(c, CURLOPT_FOLLOWLOCATION, 1L) != CURLE_OK)
return -EIO;
- *ret = c;
+ *ret = TAKE_PTR(c);
return 0;
}
diff --git a/src/import/pull-job.c b/src/import/pull-job.c
index a44e0a7eda..6881bd627f 100644
--- a/src/import/pull-job.c
+++ b/src/import/pull-job.c
@@ -537,7 +537,7 @@ int pull_job_new(PullJob **ret, const char *url, CurlGlue *glue, void *userdata)
assert(ret);
u = strdup(url);
- if (u)
+ if (!u)
return -ENOMEM;
j = new(PullJob, 1);
diff --git a/src/initctl/initctl.c b/src/initctl/initctl.c
index c60d4bd740..260dc2eb61 100644
--- a/src/initctl/initctl.c
+++ b/src/initctl/initctl.c
@@ -233,12 +233,8 @@ static void server_done(Server *s) {
while (s->fifos)
fifo_free(s->fifos);
- safe_close(s->epoll_fd);
-
- if (s->bus) {
- sd_bus_flush(s->bus);
- sd_bus_unref(s->bus);
- }
+ s->epoll_fd = safe_close(s->epoll_fd);
+ s->bus = sd_bus_flush_close_unref(s->bus);
}
static int server_init(Server *s, unsigned n_sockets) {
diff --git a/src/journal-remote/journal-gatewayd.c b/src/journal-remote/journal-gatewayd.c
index 4185af63e1..af45fa549a 100644
--- a/src/journal-remote/journal-gatewayd.c
+++ b/src/journal-remote/journal-gatewayd.c
@@ -461,7 +461,7 @@ static int request_handler_entries(
struct MHD_Connection *connection,
void *connection_cls) {
- struct MHD_Response *response;
+ _cleanup_(MHD_destroy_responsep) struct MHD_Response *response = NULL;
RequestMeta *m = connection_cls;
int r;
@@ -503,11 +503,7 @@ static int request_handler_entries(
return respond_oom(connection);
MHD_add_response_header(response, "Content-Type", mime_types[m->mode]);
-
- r = MHD_queue_response(connection, MHD_HTTP_OK, response);
- MHD_destroy_response(response);
-
- return r;
+ return MHD_queue_response(connection, MHD_HTTP_OK, response);
}
static int output_field(FILE *f, OutputMode m, const char *d, size_t l) {
@@ -619,7 +615,7 @@ static int request_handler_fields(
const char *field,
void *connection_cls) {
- struct MHD_Response *response;
+ _cleanup_(MHD_destroy_responsep) struct MHD_Response *response = NULL;
RequestMeta *m = connection_cls;
int r;
@@ -642,11 +638,7 @@ static int request_handler_fields(
return respond_oom(connection);
MHD_add_response_header(response, "Content-Type", mime_types[m->mode == OUTPUT_JSON ? OUTPUT_JSON : OUTPUT_SHORT]);
-
- r = MHD_queue_response(connection, MHD_HTTP_OK, response);
- MHD_destroy_response(response);
-
- return r;
+ return MHD_queue_response(connection, MHD_HTTP_OK, response);
}
static int request_handler_redirect(
@@ -654,8 +646,7 @@ static int request_handler_redirect(
const char *target) {
char *page;
- struct MHD_Response *response;
- int ret;
+ _cleanup_(MHD_destroy_responsep) struct MHD_Response *response = NULL;
assert(connection);
assert(target);
@@ -671,11 +662,7 @@ static int request_handler_redirect(
MHD_add_response_header(response, "Content-Type", "text/html");
MHD_add_response_header(response, "Location", target);
-
- ret = MHD_queue_response(connection, MHD_HTTP_MOVED_PERMANENTLY, response);
- MHD_destroy_response(response);
-
- return ret;
+ return MHD_queue_response(connection, MHD_HTTP_MOVED_PERMANENTLY, response);
}
static int request_handler_file(
@@ -683,8 +670,7 @@ static int request_handler_file(
const char *path,
const char *mime_type) {
- struct MHD_Response *response;
- int ret;
+ _cleanup_(MHD_destroy_responsep) struct MHD_Response *response = NULL;
_cleanup_close_ int fd = -1;
struct stat st;
@@ -702,15 +688,10 @@ static int request_handler_file(
response = MHD_create_response_from_fd_at_offset64(st.st_size, fd, 0);
if (!response)
return respond_oom(connection);
-
- fd = -1;
+ TAKE_FD(fd);
MHD_add_response_header(response, "Content-Type", mime_type);
-
- ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
- MHD_destroy_response(response);
-
- return ret;
+ return MHD_queue_response(connection, MHD_HTTP_OK, response);
}
static int get_virtualization(char **v) {
@@ -747,14 +728,13 @@ static int request_handler_machine(
struct MHD_Connection *connection,
void *connection_cls) {
- struct MHD_Response *response;
+ _cleanup_(MHD_destroy_responsep) struct MHD_Response *response = NULL;
RequestMeta *m = connection_cls;
int r;
_cleanup_free_ char* hostname = NULL, *os_name = NULL;
uint64_t cutoff_from = 0, cutoff_to = 0, usage = 0;
- char *json;
sd_id128_t mid, bid;
- _cleanup_free_ char *v = NULL;
+ _cleanup_free_ char *v = NULL, *json = NULL;
assert(connection);
assert(m);
@@ -803,21 +783,16 @@ static int request_handler_machine(
usage,
cutoff_from,
cutoff_to);
-
if (r < 0)
return respond_oom(connection);
response = MHD_create_response_from_buffer(strlen(json), json, MHD_RESPMEM_MUST_FREE);
- if (!response) {
- free(json);
+ if (!response)
return respond_oom(connection);
- }
+ TAKE_PTR(json);
MHD_add_response_header(response, "Content-Type", "application/json");
- r = MHD_queue_response(connection, MHD_HTTP_OK, response);
- MHD_destroy_response(response);
-
- return r;
+ return MHD_queue_response(connection, MHD_HTTP_OK, response);
}
static int request_handler(
diff --git a/src/journal-remote/journal-remote-main.c b/src/journal-remote/journal-remote-main.c
index e1748cb46b..802c3ea608 100644
--- a/src/journal-remote/journal-remote-main.c
+++ b/src/journal-remote/journal-remote-main.c
@@ -221,16 +221,17 @@ static int process_http_upload(
journal_remote_server_global->seal);
if (r == -EAGAIN)
break;
- else if (r < 0) {
- log_warning("Failed to process data for connection %p", connection);
- if (r == -E2BIG)
- return mhd_respondf(connection,
- r, MHD_HTTP_PAYLOAD_TOO_LARGE,
- "Entry is too large, maximum is " STRINGIFY(DATA_SIZE_MAX) " bytes.");
+ if (r < 0) {
+ if (r == -ENOBUFS)
+ log_warning_errno(r, "Entry is above the maximum of %u, aborting connection %p.",
+ DATA_SIZE_MAX, connection);
+ else if (r == -E2BIG)
+ log_warning_errno(r, "Entry with more fields than the maximum of %u, aborting connection %p.",
+ ENTRY_FIELD_COUNT_MAX, connection);
else
- return mhd_respondf(connection,
- r, MHD_HTTP_UNPROCESSABLE_ENTITY,
- "Processing failed: %m.");
+ log_warning_errno(r, "Failed to process data, aborting connection %p: %m",
+ connection);
+ return MHD_NO;
}
}
@@ -264,6 +265,7 @@ static int request_handler(
const char *header;
int r, code, fd;
_cleanup_free_ char *hostname = NULL;
+ size_t len;
assert(connection);
assert(connection_cls);
@@ -283,12 +285,27 @@ static int request_handler(
if (!streq(url, "/upload"))
return mhd_respond(connection, MHD_HTTP_NOT_FOUND, "Not found.");
- header = MHD_lookup_connection_value(connection,
- MHD_HEADER_KIND, "Content-Type");
+ header = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Content-Type");
if (!header || !streq(header, "application/vnd.fdo.journal"))
return mhd_respond(connection, MHD_HTTP_UNSUPPORTED_MEDIA_TYPE,
"Content-Type: application/vnd.fdo.journal is required.");
+ header = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Content-Length");
+ if (!header)
+ return mhd_respond(connection, MHD_HTTP_LENGTH_REQUIRED,
+ "Content-Length header is required.");
+ r = safe_atozu(header, &len);
+ if (r < 0)
+ return mhd_respondf(connection, r, MHD_HTTP_LENGTH_REQUIRED,
+ "Content-Length: %s cannot be parsed: %m", header);
+
+ if (len > ENTRY_SIZE_MAX)
+ /* When serialized, an entry of maximum size might be slightly larger,
+ * so this does not correspond exactly to the limit in journald. Oh well.
+ */
+ return mhd_respondf(connection, 0, MHD_HTTP_PAYLOAD_TOO_LARGE,
+ "Payload larger than maximum size of %u bytes", ENTRY_SIZE_MAX);
+
{
const union MHD_ConnectionInfo *ci;
diff --git a/src/journal-remote/journal-remote.c b/src/journal-remote/journal-remote.c
index 3c0916c438..1da32c5f85 100644
--- a/src/journal-remote/journal-remote.c
+++ b/src/journal-remote/journal-remote.c
@@ -407,6 +407,9 @@ int journal_remote_handle_raw_source(
log_debug("%zu active sources remaining", s->active);
return 0;
} else if (r == -E2BIG) {
+ log_notice("Entry with too many fields, skipped");
+ return 1;
+ } else if (r == -ENOBUFS) {
log_notice("Entry too big, skipped");
return 1;
} else if (r == -EAGAIN) {
diff --git a/src/journal-remote/journal-upload-journal.c b/src/journal-remote/journal-upload-journal.c
index be39f7c047..7d7e7384bf 100644
--- a/src/journal-remote/journal-upload-journal.c
+++ b/src/journal-remote/journal-upload-journal.c
@@ -235,7 +235,7 @@ static ssize_t write_entry(char *buf, size_t size, Uploader *u) {
assert_not_reached("WTF?");
}
-static inline void check_update_watchdog(Uploader *u) {
+static void check_update_watchdog(Uploader *u) {
usec_t after;
usec_t elapsed_time;
diff --git a/src/journal-remote/journal-upload.c b/src/journal-remote/journal-upload.c
index 1e08fcc554..ef3556f825 100644
--- a/src/journal-remote/journal-upload.c
+++ b/src/journal-remote/journal-upload.c
@@ -9,6 +9,7 @@
#include "sd-daemon.h"
#include "alloc-util.h"
+#include "build.h"
#include "conf-parser.h"
#include "daemon-util.h"
#include "def.h"
@@ -236,7 +237,7 @@ int start_upload(Uploader *u,
easy_setopt(curl, CURLOPT_VERBOSE, 1L, LOG_WARNING, );
easy_setopt(curl, CURLOPT_USERAGENT,
- "systemd-journal-upload " PACKAGE_STRING,
+ "systemd-journal-upload " GIT_VERSION,
LOG_WARNING, );
if (arg_key || startswith(u->url, "https://")) {
diff --git a/src/journal-remote/microhttpd-util.c b/src/journal-remote/microhttpd-util.c
index adf40b5abd..5f5691995d 100644
--- a/src/journal-remote/microhttpd-util.c
+++ b/src/journal-remote/microhttpd-util.c
@@ -32,21 +32,16 @@ static int mhd_respond_internal(struct MHD_Connection *connection,
const char *buffer,
size_t size,
enum MHD_ResponseMemoryMode mode) {
- struct MHD_Response *response;
- int r;
-
assert(connection);
- response = MHD_create_response_from_buffer(size, (char*) buffer, mode);
+ _cleanup_(MHD_destroy_responsep) struct MHD_Response *response
+ = MHD_create_response_from_buffer(size, (char*) buffer, mode);
if (!response)
return MHD_NO;
log_debug("Queueing response %u: %s", code, buffer);
MHD_add_response_header(response, "Content-Type", "text/plain");
- r = MHD_queue_response(connection, code, response);
- MHD_destroy_response(response);
-
- return r;
+ return MHD_queue_response(connection, code, response);
}
int mhd_respond(struct MHD_Connection *connection,
@@ -249,7 +244,7 @@ static int get_auth_dn(gnutls_x509_crt_t client_cert, char **buf) {
return 0;
}
-static inline void gnutls_x509_crt_deinitp(gnutls_x509_crt_t *p) {
+static void gnutls_x509_crt_deinitp(gnutls_x509_crt_t *p) {
gnutls_x509_crt_deinit(*p);
}
diff --git a/src/journal-remote/microhttpd-util.h b/src/journal-remote/microhttpd-util.h
index 364cd0f7cf..ba51d847e4 100644
--- a/src/journal-remote/microhttpd-util.h
+++ b/src/journal-remote/microhttpd-util.h
@@ -75,3 +75,4 @@ int check_permissions(struct MHD_Connection *connection, int *code, char **hostn
int setup_gnutls_logger(char **categories);
DEFINE_TRIVIAL_CLEANUP_FUNC(struct MHD_Daemon*, MHD_stop_daemon);
+DEFINE_TRIVIAL_CLEANUP_FUNC(struct MHD_Response*, MHD_destroy_response);
diff --git a/src/journal/audit-type.h b/src/journal/audit-type.h
index 069a883490..98e5c39420 100644
--- a/src/journal/audit-type.h
+++ b/src/journal/audit-type.h
@@ -4,6 +4,7 @@
#include <alloca.h>
#include <stdio.h>
+#include "alloc-util.h"
#include "macro.h"
const char *audit_type_to_string(int type);
@@ -15,7 +16,7 @@ int audit_type_from_string(const char *s);
const char *_s_; \
_s_ = audit_type_to_string(type); \
if (!_s_) { \
- _s_ = alloca(STRLEN("AUDIT") + DECIMAL_STR_MAX(int)); \
+ _s_ = newa(char, STRLEN("AUDIT") + DECIMAL_STR_MAX(int)); \
sprintf((char*) _s_, "AUDIT%04i", type); \
} \
_s_; \
diff --git a/src/journal/cat.c b/src/journal/cat.c
index a84350fbc9..9900bd2e86 100644
--- a/src/journal/cat.c
+++ b/src/journal/cat.c
@@ -20,6 +20,7 @@
static const char *arg_identifier = NULL;
static int arg_priority = LOG_INFO;
+static int arg_stderr_priority = -1;
static bool arg_level_prefix = true;
static int help(void) {
@@ -32,11 +33,12 @@ static int help(void) {
printf("%s [OPTIONS...] {COMMAND} ...\n\n"
"Execute process with stdout/stderr connected to the journal.\n\n"
- " -h --help Show this help\n"
- " --version Show package version\n"
- " -t --identifier=STRING Set syslog identifier\n"
- " -p --priority=PRIORITY Set priority value (0..7)\n"
- " --level-prefix=BOOL Control whether level prefix shall be parsed\n"
+ " -h --help Show this help\n"
+ " --version Show package version\n"
+ " -t --identifier=STRING Set syslog identifier\n"
+ " -p --priority=PRIORITY Set priority value (0..7)\n"
+ " --stderr-priority=PRIORITY Set priority value (0..7) used for stderr\n"
+ " --level-prefix=BOOL Control whether level prefix shall be parsed\n"
"\nSee the %s for details.\n"
, program_invocation_short_name
, link
@@ -49,15 +51,17 @@ static int parse_argv(int argc, char *argv[]) {
enum {
ARG_VERSION = 0x100,
+ ARG_STDERR_PRIORITY,
ARG_LEVEL_PREFIX
};
static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { "identifier", required_argument, NULL, 't' },
- { "priority", required_argument, NULL, 'p' },
- { "level-prefix", required_argument, NULL, ARG_LEVEL_PREFIX },
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, ARG_VERSION },
+ { "identifier", required_argument, NULL, 't' },
+ { "priority", required_argument, NULL, 'p' },
+ { "stderr-priority", required_argument, NULL, ARG_STDERR_PRIORITY },
+ { "level-prefix", required_argument, NULL, ARG_LEVEL_PREFIX },
{}
};
@@ -91,6 +95,13 @@ static int parse_argv(int argc, char *argv[]) {
"Failed to parse priority value.");
break;
+ case ARG_STDERR_PRIORITY:
+ arg_stderr_priority = log_level_from_string(optarg);
+ if (arg_stderr_priority < 0)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Failed to parse stderr priority value.");
+ break;
+
case ARG_LEVEL_PREFIX: {
int k;
@@ -113,7 +124,7 @@ static int parse_argv(int argc, char *argv[]) {
}
static int run(int argc, char *argv[]) {
- _cleanup_close_ int fd = -1, saved_stderr = -1;
+ _cleanup_close_ int outfd = -1, errfd = -1, saved_stderr = -1;
int r;
log_parse_environment();
@@ -123,14 +134,21 @@ static int run(int argc, char *argv[]) {
if (r <= 0)
return r;
- fd = sd_journal_stream_fd(arg_identifier, arg_priority, arg_level_prefix);
- if (fd < 0)
- return log_error_errno(fd, "Failed to create stream fd: %m");
+ outfd = sd_journal_stream_fd(arg_identifier, arg_priority, arg_level_prefix);
+ if (outfd < 0)
+ return log_error_errno(outfd, "Failed to create stream fd: %m");
+
+ if (arg_stderr_priority >= 0 && arg_stderr_priority != arg_priority) {
+ errfd = sd_journal_stream_fd(arg_identifier, arg_stderr_priority, arg_level_prefix);
+ if (errfd < 0)
+ return log_error_errno(errfd, "Failed to create stream fd: %m");
+ }
saved_stderr = fcntl(STDERR_FILENO, F_DUPFD_CLOEXEC, 3);
- r = rearrange_stdio(STDIN_FILENO, fd, fd); /* Invalidates fd on succcess + error! */
- TAKE_FD(fd);
+ r = rearrange_stdio(STDIN_FILENO, outfd, errfd < 0 ? outfd : errfd); /* Invalidates fd on succcess + error! */
+ TAKE_FD(outfd);
+ TAKE_FD(errfd);
if (r < 0)
return log_error_errno(r, "Failed to rearrange stdout/stderr: %m");
diff --git a/src/journal/catalog.c b/src/journal/catalog.c
index 3556a101bf..4062f12c2d 100644
--- a/src/journal/catalog.c
+++ b/src/journal/catalog.c
@@ -46,7 +46,8 @@ typedef struct CatalogHeader {
typedef struct CatalogItem {
sd_id128_t id;
- char language[32];
+ char language[32]; /* One byte is used for termination, so the maximum allowed
+ * length of the string is actually 31 bytes. */
le64_t offset;
} CatalogItem;
@@ -556,25 +557,44 @@ static const char *find_id(void *p, sd_id128_t id) {
const char *loc;
loc = setlocale(LC_MESSAGES, NULL);
- if (loc && loc[0] && !streq(loc, "C") && !streq(loc, "POSIX")) {
- strncpy(key.language, loc, sizeof(key.language));
- key.language[strcspn(key.language, ".@")] = 0;
-
- f = bsearch(&key, (const uint8_t*) p + le64toh(h->header_size), le64toh(h->n_items), le64toh(h->catalog_item_size), (comparison_fn_t) catalog_compare_func);
- if (!f) {
- char *e;
-
- e = strchr(key.language, '_');
- if (e) {
- *e = 0;
- f = bsearch(&key, (const uint8_t*) p + le64toh(h->header_size), le64toh(h->n_items), le64toh(h->catalog_item_size), (comparison_fn_t) catalog_compare_func);
+ if (!isempty(loc) && !STR_IN_SET(loc, "C", "POSIX")) {
+ size_t len;
+
+ len = strcspn(loc, ".@");
+ if (len > sizeof(key.language) - 1)
+ log_debug("LC_MESSAGES value too long, ignoring: \"%.*s\"", (int) len, loc);
+ else {
+ strncpy(key.language, loc, len);
+ key.language[len] = '\0';
+
+ f = bsearch(&key,
+ (const uint8_t*) p + le64toh(h->header_size),
+ le64toh(h->n_items),
+ le64toh(h->catalog_item_size),
+ (comparison_fn_t) catalog_compare_func);
+ if (!f) {
+ char *e;
+
+ e = strchr(key.language, '_');
+ if (e) {
+ *e = 0;
+ f = bsearch(&key,
+ (const uint8_t*) p + le64toh(h->header_size),
+ le64toh(h->n_items),
+ le64toh(h->catalog_item_size),
+ (comparison_fn_t) catalog_compare_func);
+ }
}
}
}
if (!f) {
zero(key.language);
- f = bsearch(&key, (const uint8_t*) p + le64toh(h->header_size), le64toh(h->n_items), le64toh(h->catalog_item_size), (comparison_fn_t) catalog_compare_func);
+ f = bsearch(&key,
+ (const uint8_t*) p + le64toh(h->header_size),
+ le64toh(h->n_items),
+ le64toh(h->catalog_item_size),
+ (comparison_fn_t) catalog_compare_func);
}
if (!f)
diff --git a/src/journal/journal-def.h b/src/journal/journal-def.h
index e48260206f..d68ce3894b 100644
--- a/src/journal/journal-def.h
+++ b/src/journal/journal-def.h
@@ -59,16 +59,20 @@ struct ObjectHeader {
uint8_t payload[];
} _packed_;
-struct DataObject {
- ObjectHeader object;
- le64_t hash;
- le64_t next_hash_offset;
- le64_t next_field_offset;
- le64_t entry_offset; /* the first array entry we store inline */
- le64_t entry_array_offset;
- le64_t n_entries;
- uint8_t payload[];
-} _packed_;
+#define DataObject__contents { \
+ ObjectHeader object; \
+ le64_t hash; \
+ le64_t next_hash_offset; \
+ le64_t next_field_offset; \
+ le64_t entry_offset; /* the first array entry we store inline */ \
+ le64_t entry_array_offset; \
+ le64_t n_entries; \
+ uint8_t payload[]; \
+ }
+
+struct DataObject DataObject__contents;
+struct DataObject__packed DataObject__contents _packed_;
+assert_cc(sizeof(struct DataObject) == sizeof(struct DataObject__packed));
struct FieldObject {
ObjectHeader object;
@@ -83,15 +87,20 @@ struct EntryItem {
le64_t hash;
} _packed_;
-struct EntryObject {
- ObjectHeader object;
- le64_t seqnum;
- le64_t realtime;
- le64_t monotonic;
- sd_id128_t boot_id;
- le64_t xor_hash;
- EntryItem items[];
-} _packed_;
+#define EntryObject__contents { \
+ ObjectHeader object; \
+ le64_t seqnum; \
+ le64_t realtime; \
+ le64_t monotonic; \
+ sd_id128_t boot_id; \
+ le64_t xor_hash; \
+ EntryItem items[]; \
+ }
+
+struct EntryObject EntryObject__contents;
+struct EntryObject__packed EntryObject__contents _packed_;
+assert_cc(sizeof(struct EntryObject) == sizeof(struct EntryObject__packed));
+
struct HashItem {
le64_t head_hash_offset;
@@ -166,40 +175,43 @@ enum {
#define HEADER_SIGNATURE ((char[]) { 'L', 'P', 'K', 'S', 'H', 'H', 'R', 'H' })
-struct Header {
- uint8_t signature[8]; /* "LPKSHHRH" */
- le32_t compatible_flags;
- le32_t incompatible_flags;
- uint8_t state;
- uint8_t reserved[7];
- sd_id128_t file_id;
- sd_id128_t machine_id;
- sd_id128_t boot_id; /* last writer */
- sd_id128_t seqnum_id;
- le64_t header_size;
- le64_t arena_size;
- le64_t data_hash_table_offset;
- le64_t data_hash_table_size;
- le64_t field_hash_table_offset;
- le64_t field_hash_table_size;
- le64_t tail_object_offset;
- le64_t n_objects;
- le64_t n_entries;
- le64_t tail_entry_seqnum;
- le64_t head_entry_seqnum;
- le64_t entry_array_offset;
- le64_t head_entry_realtime;
- le64_t tail_entry_realtime;
- le64_t tail_entry_monotonic;
- /* Added in 187 */
- le64_t n_data;
- le64_t n_fields;
- /* Added in 189 */
- le64_t n_tags;
- le64_t n_entry_arrays;
-
- /* Size: 240 */
-} _packed_;
+#define struct_Header__contents { \
+ uint8_t signature[8]; /* "LPKSHHRH" */ \
+ le32_t compatible_flags; \
+ le32_t incompatible_flags; \
+ uint8_t state; \
+ uint8_t reserved[7]; \
+ sd_id128_t file_id; \
+ sd_id128_t machine_id; \
+ sd_id128_t boot_id; /* last writer */ \
+ sd_id128_t seqnum_id; \
+ le64_t header_size; \
+ le64_t arena_size; \
+ le64_t data_hash_table_offset; \
+ le64_t data_hash_table_size; \
+ le64_t field_hash_table_offset; \
+ le64_t field_hash_table_size; \
+ le64_t tail_object_offset; \
+ le64_t n_objects; \
+ le64_t n_entries; \
+ le64_t tail_entry_seqnum; \
+ le64_t head_entry_seqnum; \
+ le64_t entry_array_offset; \
+ le64_t head_entry_realtime; \
+ le64_t tail_entry_realtime; \
+ le64_t tail_entry_monotonic; \
+ /* Added in 187 */ \
+ le64_t n_data; \
+ le64_t n_fields; \
+ /* Added in 189 */ \
+ le64_t n_tags; \
+ le64_t n_entry_arrays; \
+ }
+
+struct Header struct_Header__contents;
+struct Header__packed struct_Header__contents _packed_;
+assert_cc(sizeof(struct Header) == sizeof(struct Header__packed));
+assert_cc(sizeof(struct Header) == 240);
#define FSS_HEADER_SIGNATURE ((char[]) { 'K', 'S', 'H', 'H', 'R', 'H', 'L', 'P' })
diff --git a/src/journal/journal-send.c b/src/journal/journal-send.c
index 87056435fc..8618454131 100644
--- a/src/journal/journal-send.c
+++ b/src/journal/journal-send.c
@@ -30,7 +30,7 @@
const char *_func = (func); \
char **_f = &(f); \
_fl = strlen(_func) + 1; \
- *_f = alloca(_fl + 10); \
+ *_f = newa(char, _fl + 10); \
memcpy(*_f, "CODE_FUNC=", 10); \
memcpy(*_f + 10, _func, _fl); \
} while (false)
@@ -403,7 +403,7 @@ _public_ int sd_journal_stream_fd(const char *identifier, int priority, int leve
identifier = strempty(identifier);
l = strlen(identifier);
- header = alloca(l + 1 + 1 + 2 + 2 + 2 + 2 + 2);
+ header = newa(char, l + 1 + 1 + 2 + 2 + 2 + 2 + 2);
memcpy(header, identifier, l);
header[l++] = '\n';
diff --git a/src/journal/journald-audit.c b/src/journal/journald-audit.c
index 345e43ef44..accbad4180 100644
--- a/src/journal/journald-audit.c
+++ b/src/journal/journald-audit.c
@@ -162,7 +162,7 @@ static int map_generic_field(const char *prefix, const char **p, struct iovec **
if (e <= *p || e >= *p + 16)
return 0;
- c = alloca(strlen(prefix) + (e - *p) + 2);
+ c = newa(char, strlen(prefix) + (e - *p) + 2);
t = stpcpy(c, prefix);
for (f = *p; f < e; f++) {
diff --git a/src/journal/journald-context.c b/src/journal/journald-context.c
index 8253a45128..7c51f2f633 100644
--- a/src/journal/journald-context.c
+++ b/src/journal/journald-context.c
@@ -16,6 +16,7 @@
#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
+#include "procfs-util.h"
#include "string-util.h"
#include "syslog-util.h"
#include "unaligned.h"
@@ -60,7 +61,37 @@
/* Keep at most 16K entries in the cache. (Note though that this limit may be violated if enough streams pin entries in
* the cache, in which case we *do* permit this limit to be breached. That's safe however, as the number of stream
* clients itself is limited.) */
-#define CACHE_MAX (16*1024)
+#define CACHE_MAX_FALLBACK 128U
+#define CACHE_MAX_MAX (16*1024U)
+#define CACHE_MAX_MIN 64U
+
+static size_t cache_max(void) {
+ static size_t cached = -1;
+
+ if (cached == (size_t) -1) {
+ uint64_t mem_total;
+ int r;
+
+ r = procfs_memory_get(&mem_total, NULL);
+ if (r < 0) {
+ log_warning_errno(r, "Cannot query /proc/meminfo for MemTotal: %m");
+ cached = CACHE_MAX_FALLBACK;
+ } else {
+ /* Cache entries are usually a few kB, but the process cmdline is controlled by the
+ * user and can be up to _SC_ARG_MAX, usually 2MB. Let's say that approximately up to
+ * 1/8th of memory may be used by the cache.
+ *
+ * In the common case, this formula gives 64 cache entries for each GB of RAM.
+ */
+ long l = sysconf(_SC_ARG_MAX);
+ assert(l > 0);
+
+ cached = CLAMP(mem_total / 8 / (uint64_t) l, CACHE_MAX_MIN, CACHE_MAX_MAX);
+ }
+ }
+
+ return cached;
+}
static int client_context_compare(const void *a, const void *b) {
const ClientContext *x = a, *y = b;
@@ -246,7 +277,7 @@ static int client_context_read_label(
}
static int client_context_read_cgroup(Server *s, ClientContext *c, const char *unit_id) {
- char *t = NULL;
+ _cleanup_free_ char *t = NULL;
int r;
assert(c);
@@ -254,10 +285,9 @@ static int client_context_read_cgroup(Server *s, ClientContext *c, const char *u
/* Try to acquire the current cgroup path */
r = cg_pid_get_path_shifted(c->pid, s->cgroup_root, &t);
if (r < 0 || empty_or_root(t)) {
-
/* We use the unit ID passed in as fallback if we have nothing cached yet and cg_pid_get_path_shifted()
* failed or process is running in a root cgroup. Zombie processes are automatically migrated to root cgroup
- * on cgroupsv1 and we want to be able to map log messages from them too. */
+ * on cgroup v1 and we want to be able to map log messages from them too. */
if (unit_id && !c->unit) {
c->unit = strdup(unit_id);
if (c->unit)
@@ -268,10 +298,8 @@ static int client_context_read_cgroup(Server *s, ClientContext *c, const char *u
}
/* Let's shortcut this if the cgroup path didn't change */
- if (streq_ptr(c->cgroup, t)) {
- free(t);
+ if (streq_ptr(c->cgroup, t))
return 0;
- }
free_and_replace(c->cgroup, t);
@@ -553,15 +581,39 @@ refresh:
}
static void client_context_try_shrink_to(Server *s, size_t limit) {
+ ClientContext *c;
+ usec_t t;
+
assert(s);
+ /* Flush any cache entries for PIDs that have already moved on. Don't do this
+ * too often, since it's a slow process. */
+ t = now(CLOCK_MONOTONIC);
+ if (s->last_cache_pid_flush + MAX_USEC < t) {
+ unsigned n = prioq_size(s->client_contexts_lru), idx = 0;
+
+ /* We do a number of iterations based on the initial size of the prioq. When we remove an
+ * item, a new item is moved into its places, and items to the right might be reshuffled.
+ */
+ for (unsigned i = 0; i < n; i++) {
+ c = prioq_peek_by_index(s->client_contexts_lru, idx);
+
+ assert(c->n_ref == 0);
+
+ if (!pid_is_unwaited(c->pid))
+ client_context_free(s, c);
+ else
+ idx ++;
+ }
+
+ s->last_cache_pid_flush = t;
+ }
+
/* Bring the number of cache entries below the indicated limit, so that we can create a new entry without
* breaching the limit. Note that we only flush out entries that aren't pinned here. This means the number of
* cache entries may very well grow beyond the limit, if all entries stored remain pinned. */
while (hashmap_size(s->client_contexts) > limit) {
- ClientContext *c;
-
c = prioq_pop(s->client_contexts_lru);
if (!c)
break; /* All remaining entries are pinned, give up */
@@ -630,7 +682,7 @@ static int client_context_get_internal(
return 0;
}
- client_context_try_shrink_to(s, CACHE_MAX-1);
+ client_context_try_shrink_to(s, cache_max()-1);
r = client_context_new(s, pid, &c);
if (r < 0)
diff --git a/src/journal/journald-native.c b/src/journal/journald-native.c
index e86178ed77..221188db16 100644
--- a/src/journal/journald-native.c
+++ b/src/journal/journald-native.c
@@ -110,7 +110,7 @@ static int server_process_entry(
int priority = LOG_INFO;
pid_t object_pid = 0;
const char *p;
- int r = 0;
+ int r = 1;
p = buffer;
@@ -122,8 +122,7 @@ static int server_process_entry(
if (!e) {
/* Trailing noise, let's ignore it, and flush what we collected */
log_debug("Received message with trailing noise, ignoring.");
- r = 1; /* finish processing of the message */
- break;
+ break; /* finish processing of the message */
}
if (e == p) {
@@ -133,14 +132,17 @@ static int server_process_entry(
}
if (IN_SET(*p, '.', '#')) {
- /* Ignore control commands for now, and
- * comments too. */
+ /* Ignore control commands for now, and comments too. */
*remaining -= (e - p) + 1;
p = e + 1;
continue;
}
/* A property follows */
+ if (n > ENTRY_FIELD_COUNT_MAX) {
+ log_debug("Received an entry that has more than " STRINGIFY(ENTRY_FIELD_COUNT_MAX) " fields, ignoring entry.");
+ goto finish;
+ }
/* n existing properties, 1 new, +1 for _TRANSPORT */
if (!GREEDY_REALLOC(iovec, m,
@@ -148,7 +150,7 @@ static int server_process_entry(
N_IOVEC_META_FIELDS + N_IOVEC_OBJECT_FIELDS +
client_context_extra_fields_n_iovec(context))) {
r = log_oom();
- break;
+ goto finish;
}
q = memchr(p, '=', e - p);
@@ -157,6 +159,16 @@ static int server_process_entry(
size_t l;
l = e - p;
+ if (l > DATA_SIZE_MAX) {
+ log_debug("Received text block of %zu bytes is too large, ignoring entry.", l);
+ goto finish;
+ }
+
+ if (entry_size + l + n + 1 > ENTRY_SIZE_MAX) { /* data + separators + trailer */
+ log_debug("Entry is too big (%zu bytes after processing %zu entries), ignoring entry.",
+ entry_size + l, n + 1);
+ goto finish;
+ }
/* If the field name starts with an underscore, skip the variable, since that indicates
* a trusted field */
@@ -174,7 +186,7 @@ static int server_process_entry(
p = e + 1;
continue;
} else {
- uint64_t l;
+ uint64_t l, total;
char *k;
if (*remaining < e - p + 1 + sizeof(uint64_t) + 1) {
@@ -183,10 +195,16 @@ static int server_process_entry(
}
l = unaligned_read_le64(e + 1);
-
if (l > DATA_SIZE_MAX) {
- log_debug("Received binary data block of %"PRIu64" bytes is too large, ignoring.", l);
- break;
+ log_debug("Received binary data block of %"PRIu64" bytes is too large, ignoring entry.", l);
+ goto finish;
+ }
+
+ total = (e - p) + 1 + l;
+ if (entry_size + total + n + 1 > ENTRY_SIZE_MAX) { /* data + separators + trailer */
+ log_debug("Entry is too big (%"PRIu64"bytes after processing %zu fields), ignoring.",
+ entry_size + total, n + 1);
+ goto finish;
}
if ((uint64_t) *remaining < e - p + 1 + sizeof(uint64_t) + l + 1 ||
@@ -195,7 +213,7 @@ static int server_process_entry(
break;
}
- k = malloc((e - p) + 1 + l);
+ k = malloc(total);
if (!k) {
log_oom();
break;
@@ -223,15 +241,8 @@ static int server_process_entry(
}
}
- if (n <= 0) {
- r = 1;
+ if (n <= 0)
goto finish;
- }
-
- if (!client_context_test_priority(context, priority)) {
- r = 0;
- goto finish;
- }
tn = n++;
iovec[tn] = IOVEC_MAKE_STRING("_TRANSPORT=journal");
@@ -242,6 +253,11 @@ static int server_process_entry(
goto finish;
}
+ r = 0; /* Success, we read the message. */
+
+ if (!client_context_test_priority(context, priority))
+ goto finish;
+
if (message) {
if (s->forward_to_syslog)
server_forward_syslog(s, syslog_fixup_facility(priority), identifier, message, ucred, tv);
@@ -313,15 +329,13 @@ void server_process_native_file(
bool sealed;
int r;
- /* Data is in the passed fd, since it didn't fit in a
- * datagram. */
+ /* Data is in the passed fd, probably it didn't fit in a datagram. */
assert(s);
assert(fd >= 0);
/* If it's a memfd, check if it is sealed. If so, we can just
- * use map it and use it, and do not need to copy the data
- * out. */
+ * mmap it and use it, and do not need to copy the data out. */
sealed = memfd_get_sealed(fd) > 0;
if (!sealed && (!ucred || ucred->uid != 0)) {
@@ -362,8 +376,10 @@ void server_process_native_file(
if (st.st_size <= 0)
return;
- if (st.st_size > ENTRY_SIZE_MAX) {
- log_error("File passed too large. Ignoring.");
+ /* When !sealed, set a lower memory limit. We have to read the file,
+ * effectively doubling memory use. */
+ if (st.st_size > ENTRY_SIZE_MAX / (sealed ? 1 : 2)) {
+ log_error("File passed too large (%"PRIu64" bytes). Ignoring.", (uint64_t) st.st_size);
return;
}
@@ -388,7 +404,7 @@ void server_process_native_file(
ssize_t n;
if (fstatvfs(fd, &vfs) < 0) {
- log_error_errno(errno, "Failed to stat file system of passed file, ignoring: %m");
+ log_error_errno(errno, "Failed to stat file system of passed file, not processing it: %m");
return;
}
@@ -398,7 +414,7 @@ void server_process_native_file(
* https://github.com/systemd/systemd/issues/1822
*/
if (vfs.f_flag & ST_MANDLOCK) {
- log_error("Received file descriptor from file system with mandatory locking enabled, refusing.");
+ log_error("Received file descriptor from file system with mandatory locking enabled, not processing it.");
return;
}
@@ -411,13 +427,13 @@ void server_process_native_file(
* and so is SMB. */
r = fd_nonblock(fd, true);
if (r < 0) {
- log_error_errno(r, "Failed to make fd non-blocking, ignoring: %m");
+ log_error_errno(r, "Failed to make fd non-blocking, not processing it: %m");
return;
}
/* The file is not sealed, we can't map the file here, since
* clients might then truncate it and trigger a SIGBUS for
- * us. So let's stupidly read it */
+ * us. So let's stupidly read it. */
p = malloc(st.st_size);
if (!p) {
diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
index 434325c179..2a960ebb3e 100644
--- a/src/journal/journald-server.c
+++ b/src/journal/journald-server.c
@@ -905,6 +905,7 @@ static void dispatch_message_real(
pid_t object_pid) {
char source_time[sizeof("_SOURCE_REALTIME_TIMESTAMP=") + DECIMAL_STR_MAX(usec_t)];
+ _cleanup_free_ char *cmdline1 = NULL, *cmdline2 = NULL;
uid_t journal_uid;
ClientContext *o;
@@ -921,20 +922,23 @@ static void dispatch_message_real(
IOVEC_ADD_NUMERIC_FIELD(iovec, n, c->uid, uid_t, uid_is_valid, UID_FMT, "_UID");
IOVEC_ADD_NUMERIC_FIELD(iovec, n, c->gid, gid_t, gid_is_valid, GID_FMT, "_GID");
- IOVEC_ADD_STRING_FIELD(iovec, n, c->comm, "_COMM");
- IOVEC_ADD_STRING_FIELD(iovec, n, c->exe, "_EXE");
- IOVEC_ADD_STRING_FIELD(iovec, n, c->cmdline, "_CMDLINE");
- IOVEC_ADD_STRING_FIELD(iovec, n, c->capeff, "_CAP_EFFECTIVE");
+ IOVEC_ADD_STRING_FIELD(iovec, n, c->comm, "_COMM"); /* At most TASK_COMM_LENGTH (16 bytes) */
+ IOVEC_ADD_STRING_FIELD(iovec, n, c->exe, "_EXE"); /* A path, so at most PATH_MAX (4096 bytes) */
- IOVEC_ADD_SIZED_FIELD(iovec, n, c->label, c->label_size, "_SELINUX_CONTEXT");
+ if (c->cmdline)
+ /* At most _SC_ARG_MAX (2MB usually), which is too much to put on stack.
+ * Let's use a heap allocation for this one. */
+ cmdline1 = set_iovec_string_field(iovec, &n, "_CMDLINE=", c->cmdline);
+ IOVEC_ADD_STRING_FIELD(iovec, n, c->capeff, "_CAP_EFFECTIVE"); /* Read from /proc/.../status */
+ IOVEC_ADD_SIZED_FIELD(iovec, n, c->label, c->label_size, "_SELINUX_CONTEXT");
IOVEC_ADD_NUMERIC_FIELD(iovec, n, c->auditid, uint32_t, audit_session_is_valid, "%" PRIu32, "_AUDIT_SESSION");
IOVEC_ADD_NUMERIC_FIELD(iovec, n, c->loginuid, uid_t, uid_is_valid, UID_FMT, "_AUDIT_LOGINUID");
- IOVEC_ADD_STRING_FIELD(iovec, n, c->cgroup, "_SYSTEMD_CGROUP");
+ IOVEC_ADD_STRING_FIELD(iovec, n, c->cgroup, "_SYSTEMD_CGROUP"); /* A path */
IOVEC_ADD_STRING_FIELD(iovec, n, c->session, "_SYSTEMD_SESSION");
IOVEC_ADD_NUMERIC_FIELD(iovec, n, c->owner_uid, uid_t, uid_is_valid, UID_FMT, "_SYSTEMD_OWNER_UID");
- IOVEC_ADD_STRING_FIELD(iovec, n, c->unit, "_SYSTEMD_UNIT");
+ IOVEC_ADD_STRING_FIELD(iovec, n, c->unit, "_SYSTEMD_UNIT"); /* Unit names are bounded by UNIT_NAME_MAX */
IOVEC_ADD_STRING_FIELD(iovec, n, c->user_unit, "_SYSTEMD_USER_UNIT");
IOVEC_ADD_STRING_FIELD(iovec, n, c->slice, "_SYSTEMD_SLICE");
IOVEC_ADD_STRING_FIELD(iovec, n, c->user_slice, "_SYSTEMD_USER_SLICE");
@@ -955,13 +959,14 @@ static void dispatch_message_real(
IOVEC_ADD_NUMERIC_FIELD(iovec, n, o->uid, uid_t, uid_is_valid, UID_FMT, "OBJECT_UID");
IOVEC_ADD_NUMERIC_FIELD(iovec, n, o->gid, gid_t, gid_is_valid, GID_FMT, "OBJECT_GID");
+ /* See above for size limits, only ->cmdline may be large, so use a heap allocation for it. */
IOVEC_ADD_STRING_FIELD(iovec, n, o->comm, "OBJECT_COMM");
IOVEC_ADD_STRING_FIELD(iovec, n, o->exe, "OBJECT_EXE");
- IOVEC_ADD_STRING_FIELD(iovec, n, o->cmdline, "OBJECT_CMDLINE");
- IOVEC_ADD_STRING_FIELD(iovec, n, o->capeff, "OBJECT_CAP_EFFECTIVE");
+ if (o->cmdline)
+ cmdline2 = set_iovec_string_field(iovec, &n, "OBJECT_CMDLINE=", o->cmdline);
+ IOVEC_ADD_STRING_FIELD(iovec, n, o->capeff, "OBJECT_CAP_EFFECTIVE");
IOVEC_ADD_SIZED_FIELD(iovec, n, o->label, o->label_size, "OBJECT_SELINUX_CONTEXT");
-
IOVEC_ADD_NUMERIC_FIELD(iovec, n, o->auditid, uint32_t, audit_session_is_valid, "%" PRIu32, "OBJECT_AUDIT_SESSION");
IOVEC_ADD_NUMERIC_FIELD(iovec, n, o->loginuid, uid_t, uid_is_valid, UID_FMT, "OBJECT_AUDIT_LOGINUID");
@@ -1276,8 +1281,7 @@ int server_process_datagram(sd_event_source *es, int fd, uint32_t revents, void
return log_error_errno(errno, "recvmsg() failed: %m");
}
- CMSG_FOREACH(cmsg, &msghdr) {
-
+ CMSG_FOREACH(cmsg, &msghdr)
if (cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SCM_CREDENTIALS &&
cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred)))
@@ -1295,7 +1299,6 @@ int server_process_datagram(sd_event_source *es, int fd, uint32_t revents, void
fds = (int*) CMSG_DATA(cmsg);
n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
}
- }
/* And a trailing NUL, just in case */
s->buffer[n] = 0;
diff --git a/src/journal/journald-server.h b/src/journal/journald-server.h
index 6d4847b0cd..3f6b42ddd5 100644
--- a/src/journal/journald-server.h
+++ b/src/journal/journald-server.h
@@ -161,6 +161,8 @@ struct Server {
Hashmap *client_contexts;
Prioq *client_contexts_lru;
+ usec_t last_cache_pid_flush;
+
ClientContext *my_context; /* the context of journald itself */
ClientContext *pid1_context; /* the context of PID 1 */
};
diff --git a/src/journal/journald-wall.h b/src/journal/journald-wall.h
index d081c8254c..b73059af46 100644
--- a/src/journal/journald-wall.h
+++ b/src/journal/journald-wall.h
@@ -1,7 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-
#include "journald-server.h"
void server_forward_wall(Server *s, int priority, const char *identifier, const char *message, const struct ucred *ucred);
diff --git a/src/journal/mmap-cache.c b/src/journal/mmap-cache.c
index 90549f1c9f..0dc453e709 100644
--- a/src/journal/mmap-cache.c
+++ b/src/journal/mmap-cache.c
@@ -132,7 +132,7 @@ static void window_free(Window *w) {
free(w);
}
-_pure_ static inline bool window_matches(Window *w, int prot, uint64_t offset, size_t size) {
+_pure_ static bool window_matches(Window *w, int prot, uint64_t offset, size_t size) {
assert(w);
assert(size > 0);
diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c
index b5ff5b64f3..0f996283cd 100644
--- a/src/journal/sd-journal.c
+++ b/src/journal/sd-journal.c
@@ -36,7 +36,6 @@
#include "process-util.h"
#include "replace-var.h"
#include "stat-util.h"
-#include "stat-util.h"
#include "stdio-util.h"
#include "string-util.h"
#include "strv.h"
diff --git a/src/kernel-install/90-loaderentry.install b/src/kernel-install/90-loaderentry.install
index 39ec8a69c6..75dd5a1b7d 100644
--- a/src/kernel-install/90-loaderentry.install
+++ b/src/kernel-install/90-loaderentry.install
@@ -6,6 +6,7 @@ COMMAND="$1"
KERNEL_VERSION="$2"
BOOT_DIR_ABS="$3"
KERNEL_IMAGE="$4"
+INITRD_OPTIONS_START="5"
if ! [[ $KERNEL_INSTALL_MACHINE_ID ]]; then
exit 0
@@ -82,6 +83,24 @@ cp "$KERNEL_IMAGE" "$BOOT_DIR_ABS/linux" &&
exit 1
}
+INITRD_OPTIONS=( "${@:${INITRD_OPTIONS_START}}" )
+
+for initrd in "${INITRD_OPTIONS[@]}"; do
+ if [[ -f "${initrd}" ]]; then
+ initrd_basename="$(basename ${initrd})"
+ cp "${initrd}" "$BOOT_DIR_ABS/${initrd_basename}" &&
+ chown root:root "$BOOT_DIR_ABS/${initrd_basename}" &&
+ chmod 0644 "$BOOT_DIR_ABS/${initrd_basename}" || {
+ echo "Could not copy '${initrd}' to '$BOOT_DIR_ABS/${initrd_basename}'." >&2
+ exit 1
+ }
+ fi
+done
+
+# If no initrd option is supplied, fallback to "initrd" which is
+# the name used by dracut when generating it in its kernel-install hook
+[[ ${#INITRD_OPTIONS[@]} == 0 ]] && INITRD_OPTIONS=( initrd )
+
mkdir -p "${LOADER_ENTRY%/*}" || {
echo "Could not create loader entry directory '${LOADER_ENTRY%/*}'." >&2
exit 1
@@ -93,8 +112,10 @@ mkdir -p "${LOADER_ENTRY%/*}" || {
echo "machine-id $MACHINE_ID"
echo "options ${BOOT_OPTIONS[*]}"
echo "linux $BOOT_DIR/linux"
- [[ -f $BOOT_DIR_ABS/initrd ]] && \
- echo "initrd $BOOT_DIR/initrd"
+ for initrd in "${INITRD_OPTIONS[@]}"; do
+ [[ -f $BOOT_DIR_ABS/$(basename ${initrd}) ]] && \
+ echo "initrd $BOOT_DIR/$(basename ${initrd})"
+ done
:
} > "$LOADER_ENTRY" || {
echo "Could not create loader entry '$LOADER_ENTRY'." >&2
diff --git a/src/kernel-install/kernel-install b/src/kernel-install/kernel-install
index 732d584bbe..b85c7c557e 100644
--- a/src/kernel-install/kernel-install
+++ b/src/kernel-install/kernel-install
@@ -24,7 +24,7 @@ SKIP_REMAINING=77
usage()
{
echo "Usage:"
- echo " $0 add KERNEL-VERSION KERNEL-IMAGE"
+ echo " $0 add KERNEL-VERSION KERNEL-IMAGE [INITRD-FILE ...]"
echo " $0 remove KERNEL-VERSION"
}
@@ -65,9 +65,12 @@ done
if [[ "${0##*/}" == 'installkernel' ]]; then
COMMAND='add'
+ # make install doesn't pass any parameter wrt initrd handling
+ INITRD_OPTIONS=()
else
COMMAND="$1"
shift
+ INITRD_OPTIONS=( "${@:3}" )
fi
KERNEL_VERSION="$1"
@@ -123,7 +126,7 @@ case $COMMAND in
for f in "${PLUGINS[@]}"; do
if [[ -x $f ]]; then
- "$f" add "$KERNEL_VERSION" "$BOOT_DIR_ABS" "$KERNEL_IMAGE"
+ "$f" add "$KERNEL_VERSION" "$BOOT_DIR_ABS" "$KERNEL_IMAGE" "${INITRD_OPTIONS[@]}"
x=$?
if [[ $x == $SKIP_REMAINING ]]; then
ret=0
diff --git a/src/libsystemd-network/dhcp-identifier.c b/src/libsystemd-network/dhcp-identifier.c
index 07496adaa3..04bf64cce5 100644
--- a/src/libsystemd-network/dhcp-identifier.c
+++ b/src/libsystemd-network/dhcp-identifier.c
@@ -11,6 +11,7 @@
#include "network-internal.h"
#include "siphash24.h"
#include "sparse-endian.h"
+#include "stdio-util.h"
#include "virt.h"
#define SYSTEMD_PEN 43793
@@ -169,10 +170,10 @@ int dhcp_identifier_set_iaid(
if (detect_container() <= 0) {
/* not in a container, udev will be around */
- char ifindex_str[2 + DECIMAL_STR_MAX(int)];
+ char ifindex_str[1 + DECIMAL_STR_MAX(int)];
int r;
- sprintf(ifindex_str, "n%d", ifindex);
+ xsprintf(ifindex_str, "n%d", ifindex);
if (sd_device_new_from_device_id(&device, ifindex_str) >= 0) {
r = sd_device_get_is_initialized(device);
if (r < 0)
@@ -195,7 +196,7 @@ int dhcp_identifier_set_iaid(
if (legacy_unstable_byteorder)
/* for historical reasons (a bug), the bits were swapped and thus
- * the result was endianness dependant. Preserve that behavior. */
+ * the result was endianness dependent. Preserve that behavior. */
id32 = __bswap_32(id32);
else
/* the fixed behavior returns a stable byte order. Since LE is expected
diff --git a/src/libsystemd-network/lldp-neighbor.c b/src/libsystemd-network/lldp-neighbor.c
index 43fc8e03c0..f6db62594d 100644
--- a/src/libsystemd-network/lldp-neighbor.c
+++ b/src/libsystemd-network/lldp-neighbor.c
@@ -691,7 +691,7 @@ _public_ int sd_lldp_neighbor_tlv_is_type(sd_lldp_neighbor *n, uint8_t type) {
return type == k;
}
-_public_ int sd_lldp_neighbor_tlv_get_oui(sd_lldp_neighbor *n, uint8_t oui[3], uint8_t *subtype) {
+_public_ int sd_lldp_neighbor_tlv_get_oui(sd_lldp_neighbor *n, uint8_t oui[_SD_ARRAY_STATIC 3], uint8_t *subtype) {
const uint8_t *d;
size_t length;
int r;
@@ -720,7 +720,7 @@ _public_ int sd_lldp_neighbor_tlv_get_oui(sd_lldp_neighbor *n, uint8_t oui[3], u
return 0;
}
-_public_ int sd_lldp_neighbor_tlv_is_oui(sd_lldp_neighbor *n, const uint8_t oui[3], uint8_t subtype) {
+_public_ int sd_lldp_neighbor_tlv_is_oui(sd_lldp_neighbor *n, const uint8_t oui[_SD_ARRAY_STATIC 3], uint8_t subtype) {
uint8_t k[3], st;
int r;
diff --git a/src/libsystemd-network/network-internal.c b/src/libsystemd-network/network-internal.c
index b3b134d650..0348e7fa9d 100644
--- a/src/libsystemd-network/network-internal.c
+++ b/src/libsystemd-network/network-internal.c
@@ -52,7 +52,7 @@ int net_get_unique_predictable_data(sd_device *device, uint64_t *result) {
l = strlen(name);
sz = sizeof(sd_id128_t) + l;
- v = alloca(sz);
+ v = newa(uint8_t, sz);
/* fetch some persistent data unique to this machine */
r = sd_id128_get_machine((sd_id128_t*) v);
diff --git a/src/libsystemd-network/radv-internal.h b/src/libsystemd-network/radv-internal.h
index cd44352307..66f49ed44e 100644
--- a/src/libsystemd-network/radv-internal.h
+++ b/src/libsystemd-network/radv-internal.h
@@ -63,19 +63,34 @@ struct sd_radv {
struct sd_radv_opt_dns *dnssl;
};
+#define radv_prefix_opt__contents { \
+ uint8_t type; \
+ uint8_t length; \
+ uint8_t prefixlen; \
+ uint8_t flags; \
+ be32_t valid_lifetime; \
+ be32_t preferred_lifetime; \
+ uint32_t reserved; \
+ struct in6_addr in6_addr; \
+}
+
+struct radv_prefix_opt radv_prefix_opt__contents;
+
+/* We need the opt substructure to be packed, because we use it in send(). But
+ * if we use _packed_, this means that the structure cannot be used directly in
+ * normal code in general, because the fields might not be properly aligned.
+ * But in this particular case, the structure is defined in a way that gives
+ * proper alignment, even without the explicit _packed_ attribute. To appease
+ * the compiler we use the "unpacked" structure, but we also verify that
+ * structure contains no holes, so offsets are the same when _packed_ is used.
+ */
+struct radv_prefix_opt__packed radv_prefix_opt__contents _packed_;
+assert_cc(sizeof(struct radv_prefix_opt) == sizeof(struct radv_prefix_opt__packed));
+
struct sd_radv_prefix {
unsigned n_ref;
- struct {
- uint8_t type;
- uint8_t length;
- uint8_t prefixlen;
- uint8_t flags;
- be32_t valid_lifetime;
- be32_t preferred_lifetime;
- uint32_t reserved;
- struct in6_addr in6_addr;
- } _packed_ opt;
+ struct radv_prefix_opt opt;
LIST_FIELDS(struct sd_radv_prefix, prefix);
diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c
index 2d7ffd22ca..35fc88ef91 100644
--- a/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/libsystemd-network/sd-dhcp-client.c
@@ -118,19 +118,19 @@ static const uint8_t default_req_opts[] = {
*/
/* NOTE: using PRL options that Windows 10 RFC7844 implementation uses */
static const uint8_t default_req_opts_anonymize[] = {
- SD_DHCP_OPTION_SUBNET_MASK, /* 1 */
- SD_DHCP_OPTION_ROUTER, /* 3 */
- SD_DHCP_OPTION_DOMAIN_NAME_SERVER, /* 6 */
- SD_DHCP_OPTION_DOMAIN_NAME, /* 15 */
- SD_DHCP_OPTION_ROUTER_DISCOVER, /* 31 */
- SD_DHCP_OPTION_STATIC_ROUTE, /* 33 */
- SD_DHCP_OPTION_VENDOR_SPECIFIC, /* 43 */
- SD_DHCP_OPTION_NETBIOS_NAMESERVER, /* 44 */
- SD_DHCP_OPTION_NETBIOS_NODETYPE, /* 46 */
- SD_DHCP_OPTION_NETBIOS_SCOPE, /* 47 */
- SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE, /* 121 */
- SD_DHCP_OPTION_PRIVATE_CLASSLESS_STATIC_ROUTE, /* 249 */
- SD_DHCP_OPTION_PRIVATE_PROXY_AUTODISCOVERY, /* 252 */
+ SD_DHCP_OPTION_SUBNET_MASK, /* 1 */
+ SD_DHCP_OPTION_ROUTER, /* 3 */
+ SD_DHCP_OPTION_DOMAIN_NAME_SERVER, /* 6 */
+ SD_DHCP_OPTION_DOMAIN_NAME, /* 15 */
+ SD_DHCP_OPTION_ROUTER_DISCOVER, /* 31 */
+ SD_DHCP_OPTION_STATIC_ROUTE, /* 33 */
+ SD_DHCP_OPTION_VENDOR_SPECIFIC, /* 43 */
+ SD_DHCP_OPTION_NETBIOS_NAMESERVER, /* 44 */
+ SD_DHCP_OPTION_NETBIOS_NODETYPE, /* 46 */
+ SD_DHCP_OPTION_NETBIOS_SCOPE, /* 47 */
+ SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE, /* 121 */
+ SD_DHCP_OPTION_PRIVATE_CLASSLESS_STATIC_ROUTE, /* 249 */
+ SD_DHCP_OPTION_PRIVATE_PROXY_AUTODISCOVERY, /* 252 */
};
static int client_receive_message_raw(
@@ -353,9 +353,9 @@ static int dhcp_client_set_iaid_duid_internal(
size_t len;
assert_return(client, -EINVAL);
- assert_return(duid_len == 0 || duid != NULL, -EINVAL);
+ assert_return(duid_len == 0 || duid, -EINVAL);
- if (duid != NULL) {
+ if (duid) {
r = dhcp_validate_duid_len(duid_type, duid_len, true);
if (r < 0)
return r;
@@ -377,7 +377,7 @@ static int dhcp_client_set_iaid_duid_internal(
}
}
- if (duid != NULL) {
+ if (duid) {
client->client_id.ns.duid.type = htobe16(duid_type);
memcpy(&client->client_id.ns.duid.raw.data, duid, duid_len);
len = sizeof(client->client_id.ns.duid.type) + duid_len;
@@ -1795,7 +1795,7 @@ static int client_receive_message_raw(
} else if ((size_t)len < sizeof(DHCPPacket))
return 0;
- CMSG_FOREACH(cmsg, &msg) {
+ CMSG_FOREACH(cmsg, &msg)
if (cmsg->cmsg_level == SOL_PACKET &&
cmsg->cmsg_type == PACKET_AUXDATA &&
cmsg->cmsg_len == CMSG_LEN(sizeof(struct tpacket_auxdata))) {
@@ -1804,7 +1804,6 @@ static int client_receive_message_raw(
checksum = !(aux->tp_status & TP_STATUS_CSUMNOTREADY);
break;
}
- }
r = dhcp_packet_verify_headers(packet, len, checksum, client->port);
if (r < 0)
diff --git a/src/libsystemd-network/sd-ndisc.c b/src/libsystemd-network/sd-ndisc.c
index 79b2ea8bf2..32c20b1e4a 100644
--- a/src/libsystemd-network/sd-ndisc.c
+++ b/src/libsystemd-network/sd-ndisc.c
@@ -34,7 +34,6 @@ static void ndisc_callback(sd_ndisc *ndisc, sd_ndisc_event event, sd_ndisc_route
assert(ndisc);
assert(event >= 0 && event < _SD_NDISC_EVENT_MAX);
-
if (!ndisc->callback) {
log_ndisc("Received '%s' event.", ndisc_event_to_string(event));
return;
diff --git a/src/libsystemd-network/test-lldp.c b/src/libsystemd-network/test-lldp.c
index cb4545d901..b6c896f0a1 100644
--- a/src/libsystemd-network/test-lldp.c
+++ b/src/libsystemd-network/test-lldp.c
@@ -192,6 +192,8 @@ static void test_receive_oui_packet(sd_event *e) {
0x01, 0x02,
0xfe, 0x09, 0x00, 0x80, 0xc2, 0x07, /* Link aggregation: status 1, ID 0x00140012 */
0x01, 0x00, 0x14, 0x00, 0x12,
+ 0xfe, 0x07, 0x00, 0x12, 0x0f, 0x02, /* 802.3 Power via MDI: PSE, MDI enabled */
+ 0x07, 0x01, 0x00,
0x00, 0x00 /* End of LLDPDU */
};
@@ -220,6 +222,8 @@ static void test_receive_oui_packet(sd_event *e) {
assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0);
assert_se(sd_lldp_neighbor_tlv_is_oui(neighbors[0], SD_LLDP_OUI_802_1, SD_LLDP_OUI_802_1_SUBTYPE_LINK_AGGREGATION) > 0);
assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0);
+ assert_se(sd_lldp_neighbor_tlv_is_oui(neighbors[0], SD_LLDP_OUI_802_3, SD_LLDP_OUI_802_3_SUBTYPE_POWER_VIA_MDI) > 0);
+ assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0);
assert_se(sd_lldp_neighbor_tlv_is_type(neighbors[0], SD_LLDP_TYPE_END) > 0);
assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) == 0);
diff --git a/src/libsystemd/libsystemd.pc.in b/src/libsystemd/libsystemd.pc.in
index c861905b67..a010dea2e9 100644
--- a/src/libsystemd/libsystemd.pc.in
+++ b/src/libsystemd/libsystemd.pc.in
@@ -14,7 +14,7 @@ includedir=@includedir@
Name: systemd
Description: systemd Library
-URL: @PACKAGE_URL@
-Version: @PACKAGE_VERSION@
+URL: @PROJECT_URL@
+Version: @PROJECT_VERSION@
Libs: -L${libdir} -lsystemd
Cflags: -I${includedir}
diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym
index 96e6347795..a6748ceb20 100644
--- a/src/libsystemd/libsystemd.sym
+++ b/src/libsystemd/libsystemd.sym
@@ -671,3 +671,8 @@ global:
sd_event_source_get_floating;
sd_event_source_set_floating;
} LIBSYSTEMD_239;
+
+LIBSYSTEMD_241 {
+global:
+ sd_bus_close_unref;
+} LIBSYSTEMD_240;
diff --git a/src/libsystemd/meson.build b/src/libsystemd/meson.build
index 05d4ea0e7f..67add387e6 100644
--- a/src/libsystemd/meson.build
+++ b/src/libsystemd/meson.build
@@ -109,9 +109,8 @@ libsystemd_static = static_library(
libsystemd_sym = 'src/libsystemd/libsystemd.sym'
-libsystemd_pc = configure_file(
+configure_file(
input : 'libsystemd.pc.in',
output : 'libsystemd.pc',
- configuration : substs)
-install_data(libsystemd_pc,
- install_dir : pkgconfiglibdir)
+ configuration : substs,
+ install_dir : pkgconfiglibdir == 'no' ? '' : pkgconfiglibdir)
diff --git a/src/libsystemd/sd-bus/bus-dump.h b/src/libsystemd/sd-bus/bus-dump.h
index 373a86dd4f..a1b67c6b14 100644
--- a/src/libsystemd/sd-bus/bus-dump.h
+++ b/src/libsystemd/sd-bus/bus-dump.h
@@ -7,8 +7,8 @@
#include "sd-bus.h"
enum {
- BUS_MESSAGE_DUMP_WITH_HEADER = 1,
- BUS_MESSAGE_DUMP_SUBTREE_ONLY = 2,
+ BUS_MESSAGE_DUMP_WITH_HEADER = 1 << 0,
+ BUS_MESSAGE_DUMP_SUBTREE_ONLY = 1 << 1,
};
int bus_message_dump(sd_bus_message *m, FILE *f, unsigned flags);
diff --git a/src/libsystemd/sd-bus/bus-match.c b/src/libsystemd/sd-bus/bus-match.c
index ad135406f6..9642de10c3 100644
--- a/src/libsystemd/sd-bus/bus-match.c
+++ b/src/libsystemd/sd-bus/bus-match.c
@@ -49,11 +49,11 @@
* ` BUS_MATCH_LEAF: E
*/
-static inline bool BUS_MATCH_IS_COMPARE(enum bus_match_node_type t) {
+static bool BUS_MATCH_IS_COMPARE(enum bus_match_node_type t) {
return t >= BUS_MATCH_SENDER && t <= BUS_MATCH_ARG_HAS_LAST;
}
-static inline bool BUS_MATCH_CAN_HASH(enum bus_match_node_type t) {
+static bool BUS_MATCH_CAN_HASH(enum bus_match_node_type t) {
return (t >= BUS_MATCH_MESSAGE_TYPE && t <= BUS_MATCH_PATH) ||
(t >= BUS_MATCH_ARG && t <= BUS_MATCH_ARG_LAST) ||
(t >= BUS_MATCH_ARG_HAS && t <= BUS_MATCH_ARG_HAS_LAST);
diff --git a/src/libsystemd/sd-bus/bus-objects.c b/src/libsystemd/sd-bus/bus-objects.c
index d0538104ae..58329f3fe7 100644
--- a/src/libsystemd/sd-bus/bus-objects.c
+++ b/src/libsystemd/sd-bus/bus-objects.c
@@ -1149,7 +1149,7 @@ static int object_manager_serialize_path_and_fallbacks(
return 0;
/* Second, add fallback vtables registered for any of the prefixes */
- prefix = alloca(strlen(path) + 1);
+ prefix = newa(char, strlen(path) + 1);
OBJECT_PATH_FOREACH_PREFIX(prefix, path) {
r = object_manager_serialize_path(bus, reply, prefix, path, true, error);
if (r < 0)
@@ -1500,7 +1500,7 @@ static int bus_find_parent_object_manager(sd_bus *bus, struct node **out, const
if (!n) {
char *prefix;
- prefix = alloca(strlen(path) + 1);
+ prefix = newa(char, strlen(path) + 1);
OBJECT_PATH_FOREACH_PREFIX(prefix, path) {
n = hashmap_get(bus->nodes, prefix);
if (n)
@@ -2114,7 +2114,7 @@ _public_ int sd_bus_emit_properties_changed_strv(
if (bus->nodes_modified)
continue;
- prefix = alloca(strlen(path) + 1);
+ prefix = newa(char, strlen(path) + 1);
OBJECT_PATH_FOREACH_PREFIX(prefix, path) {
r = emit_properties_changed_on_interface(bus, prefix, path, interface, true, &found_interface, names);
if (r != 0)
@@ -2291,7 +2291,7 @@ static int object_added_append_all(sd_bus *bus, sd_bus_message *m, const char *p
if (bus->nodes_modified)
return 0;
- prefix = alloca(strlen(path) + 1);
+ prefix = newa(char, strlen(path) + 1);
OBJECT_PATH_FOREACH_PREFIX(prefix, path) {
r = object_added_append_all_prefix(bus, m, s, prefix, path, true);
if (r < 0)
@@ -2462,7 +2462,7 @@ static int object_removed_append_all(sd_bus *bus, sd_bus_message *m, const char
if (bus->nodes_modified)
return 0;
- prefix = alloca(strlen(path) + 1);
+ prefix = newa(char, strlen(path) + 1);
OBJECT_PATH_FOREACH_PREFIX(prefix, path) {
r = object_removed_append_all_prefix(bus, m, s, prefix, path, true);
if (r < 0)
@@ -2626,7 +2626,7 @@ static int interfaces_added_append_one(
if (bus->nodes_modified)
return 0;
- prefix = alloca(strlen(path) + 1);
+ prefix = newa(char, strlen(path) + 1);
OBJECT_PATH_FOREACH_PREFIX(prefix, path) {
r = interfaces_added_append_one_prefix(bus, m, prefix, path, interface, true);
if (r != 0)
diff --git a/src/libsystemd/sd-bus/bus-protocol.h b/src/libsystemd/sd-bus/bus-protocol.h
index a5f4724aa9..d01fd8e6a3 100644
--- a/src/libsystemd/sd-bus/bus-protocol.h
+++ b/src/libsystemd/sd-bus/bus-protocol.h
@@ -54,9 +54,9 @@ enum {
/* Flags */
enum {
- BUS_MESSAGE_NO_REPLY_EXPECTED = 1,
- BUS_MESSAGE_NO_AUTO_START = 2,
- BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION = 4,
+ BUS_MESSAGE_NO_REPLY_EXPECTED = 1 << 0,
+ BUS_MESSAGE_NO_AUTO_START = 1 << 1,
+ BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION = 1 << 2,
};
/* Header fields */
@@ -78,9 +78,9 @@ enum {
/* RequestName parameters */
enum {
- BUS_NAME_ALLOW_REPLACEMENT = 1,
- BUS_NAME_REPLACE_EXISTING = 2,
- BUS_NAME_DO_NOT_QUEUE = 4
+ BUS_NAME_ALLOW_REPLACEMENT = 1 << 0,
+ BUS_NAME_REPLACE_EXISTING = 1 << 1,
+ BUS_NAME_DO_NOT_QUEUE = 1 << 2,
};
/* RequestName returns */
diff --git a/src/libsystemd/sd-bus/bus-socket.c b/src/libsystemd/sd-bus/bus-socket.c
index ed185131b8..441b4a816f 100644
--- a/src/libsystemd/sd-bus/bus-socket.c
+++ b/src/libsystemd/sd-bus/bus-socket.c
@@ -981,7 +981,7 @@ int bus_socket_write_message(sd_bus *bus, sd_bus_message *m, size_t *idx) {
return r;
n = m->n_iovec * sizeof(struct iovec);
- iov = alloca(n);
+ iov = newa(struct iovec, n);
memcpy_safe(iov, m->iovec, n);
j = 0;
@@ -1072,7 +1072,7 @@ static int bus_socket_read_message_need(sd_bus *bus, size_t *need) {
}
static int bus_socket_make_message(sd_bus *bus, size_t size) {
- sd_bus_message *t;
+ sd_bus_message *t = NULL;
void *b;
int r;
@@ -1097,7 +1097,9 @@ static int bus_socket_make_message(sd_bus *bus, size_t size) {
bus->fds, bus->n_fds,
NULL,
&t);
- if (r < 0) {
+ if (r == -EBADMSG)
+ log_debug_errno(r, "Received invalid message from connection %s, dropping.", strna(bus->description));
+ else if (r < 0) {
free(b);
return r;
}
@@ -1108,7 +1110,8 @@ static int bus_socket_make_message(sd_bus *bus, size_t size) {
bus->fds = NULL;
bus->n_fds = 0;
- bus->rqueue[bus->rqueue_size++] = t;
+ if (t)
+ bus->rqueue[bus->rqueue_size++] = t;
return 1;
}
diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c
index 3b00bc8157..1ff858f32d 100644
--- a/src/libsystemd/sd-bus/sd-bus.c
+++ b/src/libsystemd/sd-bus/sd-bus.c
@@ -1556,17 +1556,24 @@ _public_ void sd_bus_close(sd_bus *bus) {
bus_close_inotify_fd(bus);
}
+_public_ sd_bus *sd_bus_close_unref(sd_bus *bus) {
+ if (!bus)
+ return NULL;
+
+ sd_bus_close(bus);
+
+ return sd_bus_unref(bus);
+}
+
_public_ sd_bus* sd_bus_flush_close_unref(sd_bus *bus) {
if (!bus)
return NULL;
/* Have to do this before flush() to prevent hang */
bus_kill_exec(bus);
-
sd_bus_flush(bus);
- sd_bus_close(bus);
- return sd_bus_unref(bus);
+ return sd_bus_close_unref(bus);
}
void bus_enter_closing(sd_bus *bus) {
diff --git a/src/libsystemd/sd-daemon/sd-daemon.c b/src/libsystemd/sd-daemon/sd-daemon.c
index 218210f234..9e8f0a73f5 100644
--- a/src/libsystemd/sd-daemon/sd-daemon.c
+++ b/src/libsystemd/sd-daemon/sd-daemon.c
@@ -604,7 +604,13 @@ _public_ int sd_booted(void) {
* created. This takes place in mount-setup.c, so is
* guaranteed to happen very early during boot. */
- return laccess("/run/systemd/system/", F_OK) >= 0;
+ if (laccess("/run/systemd/system/", F_OK) >= 0)
+ return true;
+
+ if (errno == ENOENT)
+ return false;
+
+ return -errno;
}
_public_ int sd_watchdog_enabled(int unset_environment, uint64_t *usec) {
diff --git a/src/libsystemd/sd-device/device-monitor.c b/src/libsystemd/sd-device/device-monitor.c
index b86932663e..27d0af5918 100644
--- a/src/libsystemd/sd-device/device-monitor.c
+++ b/src/libsystemd/sd-device/device-monitor.c
@@ -93,14 +93,8 @@ _public_ int sd_device_monitor_set_receive_buffer_size(sd_device_monitor *m, siz
assert_return(m, -EINVAL);
assert_return((size_t) n == size, -EINVAL);
- if (m->bound)
- return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
- "sd-device-monitor: Socket fd is already bound. "
- "It may be dangerous to change buffer size. "
- "Refusing to change buffer size.");
-
- if (setsockopt_int(m->sock, SOL_SOCKET, SO_RCVBUF, n) < 0) {
- r = setsockopt_int(m->sock, SOL_SOCKET, SO_RCVBUFFORCE, n);
+ if (setsockopt_int(m->sock, SOL_SOCKET, SO_RCVBUFFORCE, n) < 0) {
+ r = setsockopt_int(m->sock, SOL_SOCKET, SO_RCVBUF, n);
if (r < 0)
return r;
}
@@ -754,7 +748,7 @@ _public_ int sd_device_monitor_filter_remove(sd_device_monitor *m) {
m->subsystem_filter = hashmap_free_free_free(m->subsystem_filter);
m->tag_filter = set_free_free(m->tag_filter);
- if (setsockopt(m->sock, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter)) < 0)
+ if (setsockopt(m->sock, SOL_SOCKET, SO_DETACH_FILTER, &filter, sizeof(filter)) < 0)
return -errno;
m->filter_uptodate = true;
diff --git a/src/libsystemd/sd-device/device-private.c b/src/libsystemd/sd-device/device-private.c
index 01a5aa3d3f..76267a1e74 100644
--- a/src/libsystemd/sd-device/device-private.c
+++ b/src/libsystemd/sd-device/device-private.c
@@ -326,15 +326,6 @@ static int device_append(sd_device *device, char *key, const char **_major, cons
action = device_action_from_string(value);
if (action == _DEVICE_ACTION_INVALID)
return -EINVAL;
- /* FIXME: remove once we no longer flush previuos state for each action */
- if (action == DEVICE_ACTION_BIND || action == DEVICE_ACTION_UNBIND) {
- static bool warned;
- if (!warned) {
- log_device_debug(device, "sd-device: ignoring actions 'bind' and 'unbind'");
- warned = true;
- }
- return -EINVAL;
- }
} else if (streq(key, "SEQNUM")) {
r = safe_atou64(value, &seqnum);
if (r < 0)
@@ -711,13 +702,24 @@ int device_new_from_stat_rdev(sd_device **ret, const struct stat *st) {
int device_copy_properties(sd_device *device_dst, sd_device *device_src) {
const char *property, *value;
+ Iterator i;
int r;
assert(device_dst);
assert(device_src);
- FOREACH_DEVICE_PROPERTY(device_src, property, value) {
- r = device_add_property(device_dst, property, value);
+ r = device_properties_prepare(device_src);
+ if (r < 0)
+ return r;
+
+ ORDERED_HASHMAP_FOREACH_KEY(value, property, device_src->properties_db, i) {
+ r = device_add_property_aux(device_dst, property, value, true);
+ if (r < 0)
+ return r;
+ }
+
+ ORDERED_HASHMAP_FOREACH_KEY(value, property, device_src->properties, i) {
+ r = device_add_property_aux(device_dst, property, value, false);
if (r < 0)
return r;
}
diff --git a/src/libsystemd/sd-device/device-private.h b/src/libsystemd/sd-device/device-private.h
index 56558b38c6..062bfd651c 100644
--- a/src/libsystemd/sd-device/device-private.h
+++ b/src/libsystemd/sd-device/device-private.h
@@ -37,6 +37,7 @@ uint64_t device_get_properties_generation(sd_device *device);
uint64_t device_get_tags_generation(sd_device *device);
uint64_t device_get_devlinks_generation(sd_device *device);
+int device_properties_prepare(sd_device *device);
int device_get_properties_nulstr(sd_device *device, const uint8_t **nulstr, size_t *len);
int device_get_properties_strv(sd_device *device, char ***strv);
diff --git a/src/libsystemd/sd-device/sd-device.c b/src/libsystemd/sd-device/sd-device.c
index db58615df5..2a69f2e94b 100644
--- a/src/libsystemd/sd-device/sd-device.c
+++ b/src/libsystemd/sd-device/sd-device.c
@@ -29,7 +29,7 @@
#include "util.h"
int device_new_aux(sd_device **ret) {
- sd_device *device = NULL;
+ sd_device *device;
assert(ret);
@@ -205,9 +205,7 @@ int device_set_syspath(sd_device *device, const char *_syspath, bool verify) {
return r;
free_and_replace(device->syspath, syspath);
-
device->devpath = devpath;
-
return 0;
}
@@ -227,7 +225,6 @@ _public_ int sd_device_new_from_syspath(sd_device **ret, const char *syspath) {
return r;
*ret = TAKE_PTR(device);
-
return 0;
}
@@ -610,8 +607,8 @@ _public_ int sd_device_new_from_device_id(sd_device **ret, const char *id) {
return sd_device_new_from_devnum(ret, id[0], devt);
}
- case 'n':
- {
+
+ case 'n': {
_cleanup_(sd_device_unrefp) sd_device *device = NULL;
_cleanup_close_ int sk = -1;
struct ifreq ifr = {};
@@ -642,11 +639,10 @@ _public_ int sd_device_new_from_device_id(sd_device **ret, const char *id) {
return -ENODEV;
*ret = TAKE_PTR(device);
-
return 0;
}
- case '+':
- {
+
+ case '+': {
char subsys[PATH_MAX];
char *sysname;
@@ -660,6 +656,7 @@ _public_ int sd_device_new_from_device_id(sd_device **ret, const char *id) {
return sd_device_new_from_subsystem_sysname(ret, subsys, sysname);
}
+
default:
return -EINVAL;
}
@@ -727,7 +724,6 @@ _public_ int sd_device_get_parent(sd_device *child, sd_device **ret) {
return -ENOENT;
*ret = child->parent;
-
return 0;
}
@@ -746,11 +742,8 @@ int device_set_subsystem(sd_device *device, const char *_subsystem) {
if (r < 0)
return r;
- free_and_replace(device->subsystem, subsystem);
-
device->subsystem_set = true;
-
- return 0;
+ return free_and_replace(device->subsystem, subsystem);
}
static int device_set_drivers_subsystem(sd_device *device, const char *_subsystem) {
@@ -769,9 +762,7 @@ static int device_set_drivers_subsystem(sd_device *device, const char *_subsyste
if (r < 0)
return r;
- free_and_replace(device->driver_subsystem, subsystem);
-
- return 0;
+ return free_and_replace(device->driver_subsystem, subsystem);
}
_public_ int sd_device_get_subsystem(sd_device *device, const char **ret) {
@@ -836,7 +827,6 @@ _public_ int sd_device_get_subsystem(sd_device *device, const char **ret) {
return -ENOENT;
*ret = device->subsystem;
-
return 0;
}
@@ -886,7 +876,6 @@ _public_ int sd_device_get_parent_with_subsystem_devtype(sd_device *child, const
return r;
*ret = parent;
-
return 0;
}
@@ -923,11 +912,8 @@ int device_set_driver(sd_device *device, const char *_driver) {
if (r < 0)
return r;
- free_and_replace(device->driver, driver);
-
device->driver_set = true;
-
- return 0;
+ return free_and_replace(device->driver, driver);
}
_public_ int sd_device_get_driver(sd_device *device, const char **ret) {
@@ -960,7 +946,6 @@ _public_ int sd_device_get_driver(sd_device *device, const char **ret) {
return -ENOENT;
*ret = device->driver;
-
return 0;
}
@@ -972,7 +957,6 @@ _public_ int sd_device_get_devpath(sd_device *device, const char **devpath) {
assert(device->devpath[0] == '/');
*devpath = device->devpath;
-
return 0;
}
@@ -992,7 +976,6 @@ _public_ int sd_device_get_devname(sd_device *device, const char **devname) {
assert(path_startswith(device->devname, "/dev/"));
*devname = device->devname;
-
return 0;
}
@@ -1002,6 +985,9 @@ static int device_set_sysname(sd_device *device) {
const char *pos;
size_t len = 0;
+ if (!device->devpath)
+ return -EINVAL;
+
pos = strrchr(device->devpath, '/');
if (!pos)
return -EINVAL;
@@ -1030,13 +1016,9 @@ static int device_set_sysname(sd_device *device) {
if (len == 0)
sysnum = NULL;
- free_and_replace(device->sysname, sysname);
-
- device->sysnum = sysnum;
-
device->sysname_set = true;
-
- return 0;
+ device->sysnum = sysnum;
+ return free_and_replace(device->sysname, sysname);
}
_public_ int sd_device_get_sysname(sd_device *device, const char **ret) {
@@ -1054,7 +1036,6 @@ _public_ int sd_device_get_sysname(sd_device *device, const char **ret) {
assert_return(device->sysname, -ENOENT);
*ret = device->sysname;
-
return 0;
}
@@ -1074,7 +1055,6 @@ _public_ int sd_device_get_sysnum(sd_device *device, const char **ret) {
return -ENOENT;
*ret = device->sysnum;
-
return 0;
}
@@ -1283,7 +1263,6 @@ int device_get_id_filename(sd_device *device, const char **ret) {
}
*ret = device->id_filename;
-
return 0;
}
@@ -1415,7 +1394,6 @@ _public_ int sd_device_get_usec_since_initialized(sd_device *device, uint64_t *u
return -EIO;
*usec = now_ts - device->usec_initialized;
-
return 0;
}
@@ -1475,7 +1453,7 @@ _public_ const char *sd_device_get_devlink_next(sd_device *device) {
return v;
}
-static int device_properties_prepare(sd_device *device) {
+int device_properties_prepare(sd_device *device) {
int r;
assert(device);
@@ -1558,7 +1536,6 @@ _public_ const char *sd_device_get_property_first(sd_device *device, const char
if (_value)
*_value = value;
-
return key;
}
@@ -1580,7 +1557,6 @@ _public_ const char *sd_device_get_property_next(sd_device *device, const char *
if (_value)
*_value = value;
-
return key;
}
@@ -1691,7 +1667,6 @@ _public_ int sd_device_get_property_value(sd_device *device, const char *key, co
if (_value)
*_value = value;
-
return 0;
}
@@ -1718,8 +1693,7 @@ static int device_add_sysattr_value(sd_device *device, const char *_key, char *v
r = hashmap_put(device->sysattr_values, key, value);
if (r < 0)
return r;
-
- key = NULL;
+ TAKE_PTR(key);
return 0;
}
@@ -1736,7 +1710,6 @@ static int device_get_sysattr_value(sd_device *device, const char *_key, const c
if (_value)
*_value = value;
-
return 0;
}
@@ -1820,14 +1793,11 @@ _public_ int sd_device_get_sysattr_value(sd_device *device, const char *sysattr,
static void device_remove_sysattr_value(sd_device *device, const char *_key) {
_cleanup_free_ char *key = NULL;
- _cleanup_free_ char *value = NULL;
assert(device);
assert(_key);
- value = hashmap_remove2(device->sysattr_values, _key, (void **) &key);
-
- return;
+ free(hashmap_remove2(device->sysattr_values, _key, (void **) &key));
}
/* set the attribute and save it in the cache. If a NULL value is passed the
@@ -1843,7 +1813,6 @@ _public_ int sd_device_set_sysattr_value(sd_device *device, const char *sysattr,
if (!_value) {
device_remove_sysattr_value(device, sysattr);
-
return 0;
}
@@ -1874,23 +1843,22 @@ _public_ int sd_device_set_sysattr_value(sd_device *device, const char *sysattr,
if (r == -EISDIR)
return r;
- free(value);
- value = strdup("");
- if (!value)
- return -ENOMEM;
+ r = free_and_strdup(&value, "");
+ if (r < 0)
+ return r;
r = device_add_sysattr_value(device, sysattr, value);
if (r < 0)
return r;
+ TAKE_PTR(value);
- value = NULL;
return -ENXIO;
}
r = device_add_sysattr_value(device, sysattr, value);
if (r < 0)
return r;
+ TAKE_PTR(value);
- value = NULL;
return 0;
}
diff --git a/src/libsystemd/sd-device/test-sd-device-monitor.c b/src/libsystemd/sd-device/test-sd-device-monitor.c
index 9e5ca11fe9..aa1edaaf3c 100644
--- a/src/libsystemd/sd-device/test-sd-device-monitor.c
+++ b/src/libsystemd/sd-device/test-sd-device-monitor.c
@@ -21,14 +21,46 @@ static int monitor_handler(sd_device_monitor *m, sd_device *d, void *userdata) {
assert_se(sd_device_get_syspath(d, &s) >= 0);
assert_se(streq(s, syspath));
- return sd_event_exit(sd_device_monitor_get_event(m), 0);
+ return sd_event_exit(sd_device_monitor_get_event(m), 100);
}
-static int test_send_receive_one(sd_device *device, bool subsystem_filter, bool tag_filter, bool use_bpf) {
+static int test_receive_device_fail(void) {
_cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor_server = NULL, *monitor_client = NULL;
- const char *syspath, *subsystem, *tag, *devtype = NULL;
+ _cleanup_(sd_device_unrefp) sd_device *loopback = NULL;
+ const char *syspath;
int r;
+ log_info("/* %s */", __func__);
+
+ /* Try to send device with invalid action and without seqnum. */
+ assert_se(sd_device_new_from_syspath(&loopback, "/sys/class/net/lo") >= 0);
+ assert_se(device_add_property(loopback, "ACTION", "hoge") >= 0);
+
+ assert_se(sd_device_get_syspath(loopback, &syspath) >= 0);
+
+ assert_se(device_monitor_new_full(&monitor_server, MONITOR_GROUP_NONE, -1) >= 0);
+ assert_se(sd_device_monitor_start(monitor_server, NULL, NULL) >= 0);
+ assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_server), "sender") >= 0);
+
+ assert_se(device_monitor_new_full(&monitor_client, MONITOR_GROUP_NONE, -1) >= 0);
+ assert_se(device_monitor_allow_unicast_sender(monitor_client, monitor_server) >= 0);
+ assert_se(sd_device_monitor_start(monitor_client, monitor_handler, (void *) syspath) >= 0);
+ assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_client), "receiver") >= 0);
+
+ /* Do not use assert_se() here. */
+ r = device_monitor_send_device(monitor_server, monitor_client, loopback);
+ if (r < 0)
+ return log_error_errno(r, "Failed to send loopback device: %m");
+
+ assert_se(sd_event_run(sd_device_monitor_get_event(monitor_client), 0) >= 0);
+
+ return 0;
+}
+
+static void test_send_receive_one(sd_device *device, bool subsystem_filter, bool tag_filter, bool use_bpf) {
+ _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor_server = NULL, *monitor_client = NULL;
+ const char *syspath, *subsystem, *tag, *devtype = NULL;
+
log_device_info(device, "/* %s(subsystem_filter=%s, tag_filter=%s, use_bpf=%s) */", __func__,
true_false(subsystem_filter), true_false(tag_filter), true_false(use_bpf));
@@ -56,14 +88,8 @@ static int test_send_receive_one(sd_device *device, bool subsystem_filter, bool
if ((subsystem_filter || tag_filter) && use_bpf)
assert_se(sd_device_monitor_filter_update(monitor_client) >= 0);
- /* Do not use assert_se() here. */
- r = device_monitor_send_device(monitor_server, monitor_client, device);
- if (r < 0)
- return log_error_errno(r, "Failed to send loopback device: %m");
-
- assert_se(sd_event_loop(sd_device_monitor_get_event(monitor_client)) == 0);
-
- return 0;
+ assert_se(device_monitor_send_device(monitor_server, monitor_client, device) >= 0);
+ assert_se(sd_event_loop(sd_device_monitor_get_event(monitor_client)) == 100);
}
static void test_subsystem_filter(sd_device *device) {
@@ -99,7 +125,45 @@ static void test_subsystem_filter(sd_device *device) {
log_info("Sending device subsystem:%s syspath:%s", subsystem, syspath);
assert_se(device_monitor_send_device(monitor_server, monitor_client, device) >= 0);
- assert_se(sd_event_loop(sd_device_monitor_get_event(monitor_client)) == 0);
+ assert_se(sd_event_loop(sd_device_monitor_get_event(monitor_client)) == 100);
+}
+
+static void test_sd_device_monitor_filter_remove(sd_device *device) {
+ _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor_server = NULL, *monitor_client = NULL;
+ const char *syspath;
+
+ log_device_info(device, "/* %s */", __func__);
+
+ assert_se(sd_device_get_syspath(device, &syspath) >= 0);
+
+ assert_se(device_monitor_new_full(&monitor_server, MONITOR_GROUP_NONE, -1) >= 0);
+ assert_se(sd_device_monitor_start(monitor_server, NULL, NULL) >= 0);
+ assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_server), "sender") >= 0);
+
+ assert_se(device_monitor_new_full(&monitor_client, MONITOR_GROUP_NONE, -1) >= 0);
+ assert_se(device_monitor_allow_unicast_sender(monitor_client, monitor_server) >= 0);
+ assert_se(sd_device_monitor_start(monitor_client, monitor_handler, (void *) syspath) >= 0);
+ assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_client), "receiver") >= 0);
+
+ assert_se(sd_device_monitor_filter_add_match_subsystem_devtype(monitor_client, "hoge", NULL) >= 0);
+ assert_se(sd_device_monitor_filter_update(monitor_client) >= 0);
+
+ assert_se(device_monitor_send_device(monitor_server, monitor_client, device) >= 0);
+ assert_se(sd_event_run(sd_device_monitor_get_event(monitor_client), 0) >= 0);
+
+ assert_se(sd_device_monitor_filter_remove(monitor_client) >= 0);
+
+ assert_se(device_monitor_send_device(monitor_server, monitor_client, device) >= 0);
+ assert_se(sd_event_loop(sd_device_monitor_get_event(monitor_client)) == 100);
+}
+
+static void test_device_copy_properties(sd_device *device) {
+ _cleanup_(sd_device_unrefp) sd_device *copy = NULL;
+
+ assert_se(device_shallow_clone(device, &copy) >= 0);
+ assert_se(device_copy_properties(copy, device) >= 0);
+
+ test_send_receive_one(copy, false, false, false);
}
int main(int argc, char *argv[]) {
@@ -111,24 +175,27 @@ int main(int argc, char *argv[]) {
if (getuid() != 0)
return log_tests_skipped("not root");
- assert_se(sd_device_new_from_syspath(&loopback, "/sys/class/net/lo") >= 0);
- assert_se(device_add_property(loopback, "ACTION", "add") >= 0);
- assert_se(device_add_property(loopback, "SEQNUM", "10") >= 0);
-
- r = test_send_receive_one(loopback, false, false, false);
+ r = test_receive_device_fail();
if (r < 0) {
assert_se(r == -EPERM && detect_container() > 0);
return log_tests_skipped("Running in container? Skipping remaining tests");
}
- assert_se(test_send_receive_one(loopback, true, false, false) >= 0);
- assert_se(test_send_receive_one(loopback, false, true, false) >= 0);
- assert_se(test_send_receive_one(loopback, true, true, false) >= 0);
- assert_se(test_send_receive_one(loopback, true, false, true) >= 0);
- assert_se(test_send_receive_one(loopback, false, true, true) >= 0);
- assert_se(test_send_receive_one(loopback, true, true, true) >= 0);
+ assert_se(sd_device_new_from_syspath(&loopback, "/sys/class/net/lo") >= 0);
+ assert_se(device_add_property(loopback, "ACTION", "add") >= 0);
+ assert_se(device_add_property(loopback, "SEQNUM", "10") >= 0);
+
+ test_send_receive_one(loopback, false, false, false);
+ test_send_receive_one(loopback, true, false, false);
+ test_send_receive_one(loopback, false, true, false);
+ test_send_receive_one(loopback, true, true, false);
+ test_send_receive_one(loopback, true, false, true);
+ test_send_receive_one(loopback, false, true, true);
+ test_send_receive_one(loopback, true, true, true);
test_subsystem_filter(loopback);
+ test_sd_device_monitor_filter_remove(loopback);
+ test_device_copy_properties(loopback);
r = sd_device_new_from_subsystem_sysname(&sda, "block", "sda");
if (r < 0) {
@@ -139,13 +206,13 @@ int main(int argc, char *argv[]) {
assert_se(device_add_property(sda, "ACTION", "change") >= 0);
assert_se(device_add_property(sda, "SEQNUM", "11") >= 0);
- assert_se(test_send_receive_one(sda, false, false, false) >= 0);
- assert_se(test_send_receive_one(sda, true, false, false) >= 0);
- assert_se(test_send_receive_one(sda, false, true, false) >= 0);
- assert_se(test_send_receive_one(sda, true, true, false) >= 0);
- assert_se(test_send_receive_one(sda, true, false, true) >= 0);
- assert_se(test_send_receive_one(sda, false, true, true) >= 0);
- assert_se(test_send_receive_one(sda, true, true, true) >= 0);
+ test_send_receive_one(sda, false, false, false);
+ test_send_receive_one(sda, true, false, false);
+ test_send_receive_one(sda, false, true, false);
+ test_send_receive_one(sda, true, true, false);
+ test_send_receive_one(sda, true, false, true);
+ test_send_receive_one(sda, false, true, true);
+ test_send_receive_one(sda, true, true, true);
return 0;
}
diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c
index 0030ea5dbe..04ba7e2574 100644
--- a/src/libsystemd/sd-event/sd-event.c
+++ b/src/libsystemd/sd-event/sd-event.c
@@ -470,6 +470,17 @@ static struct clock_data* event_get_clock_data(sd_event *e, EventSourceType t) {
}
}
+static void event_free_signal_data(sd_event *e, struct signal_data *d) {
+ assert(e);
+
+ if (!d)
+ return;
+
+ hashmap_remove(e->signal_data, &d->priority);
+ safe_close(d->fd);
+ free(d);
+}
+
static int event_make_signal_data(
sd_event *e,
int sig,
@@ -559,11 +570,8 @@ static int event_make_signal_data(
return 0;
fail:
- if (added) {
- d->fd = safe_close(d->fd);
- hashmap_remove(e->signal_data, &d->priority);
- free(d);
- }
+ if (added)
+ event_free_signal_data(e, d);
return r;
}
@@ -582,11 +590,8 @@ static void event_unmask_signal_data(sd_event *e, struct signal_data *d, int sig
assert_se(sigdelset(&d->sigset, sig) >= 0);
if (sigisemptyset(&d->sigset)) {
-
/* If all the mask is all-zero we can get rid of the structure */
- hashmap_remove(e->signal_data, &d->priority);
- safe_close(d->fd);
- free(d);
+ event_free_signal_data(e, d);
return;
}
diff --git a/src/libsystemd/sd-hwdb/hwdb-util.c b/src/libsystemd/sd-hwdb/hwdb-util.c
index c5c329f2ac..f8529670b3 100644
--- a/src/libsystemd/sd-hwdb/hwdb-util.c
+++ b/src/libsystemd/sd-hwdb/hwdb-util.c
@@ -367,7 +367,7 @@ static int trie_store(struct trie *trie, const char *filename, bool compat) {
int64_t size;
struct trie_header_f h = {
.signature = HWDB_SIG,
- .tool_version = htole64(atoi(PACKAGE_VERSION)),
+ .tool_version = htole64(PROJECT_VERSION),
.header_size = htole64(sizeof(struct trie_header_f)),
.node_size = htole64(sizeof(struct trie_node_f)),
.child_entry_size = htole64(sizeof(struct trie_child_entry_f)),
diff --git a/src/libsystemd/sd-hwdb/sd-hwdb.c b/src/libsystemd/sd-hwdb/sd-hwdb.c
index b81786a64d..233944c078 100644
--- a/src/libsystemd/sd-hwdb/sd-hwdb.c
+++ b/src/libsystemd/sd-hwdb/sd-hwdb.c
@@ -240,7 +240,7 @@ static int trie_search_f(sd_hwdb *hwdb, const char *search) {
size_t p = 0;
if (node->prefix_off) {
- uint8_t c;
+ char c;
for (; (c = trie_string(hwdb, node->prefix_off)[p]); p++) {
if (IN_SET(c, '*', '?', '['))
diff --git a/src/libsystemd/sd-id128/sd-id128.c b/src/libsystemd/sd-id128/sd-id128.c
index 3593a71c02..e72af1593c 100644
--- a/src/libsystemd/sd-id128/sd-id128.c
+++ b/src/libsystemd/sd-id128/sd-id128.c
@@ -18,7 +18,7 @@
#include "user-util.h"
#include "util.h"
-_public_ char *sd_id128_to_string(sd_id128_t id, char s[SD_ID128_STRING_MAX]) {
+_public_ char *sd_id128_to_string(sd_id128_t id, char s[_SD_ARRAY_STATIC SD_ID128_STRING_MAX]) {
unsigned n;
assert_return(s, NULL);
diff --git a/src/libsystemd/sd-login/sd-login.c b/src/libsystemd/sd-login/sd-login.c
index a904c6b544..07f21e84de 100644
--- a/src/libsystemd/sd-login/sd-login.c
+++ b/src/libsystemd/sd-login/sd-login.c
@@ -945,11 +945,11 @@ _public_ int sd_machine_get_ifindices(const char *machine, int **ifindices) {
return nr;
}
-static inline int MONITOR_TO_FD(sd_login_monitor *m) {
+static int MONITOR_TO_FD(sd_login_monitor *m) {
return (int) (unsigned long) m - 1;
}
-static inline sd_login_monitor* FD_TO_MONITOR(int fd) {
+static sd_login_monitor* FD_TO_MONITOR(int fd) {
return (sd_login_monitor*) (unsigned long) (fd + 1);
}
diff --git a/src/libsystemd/sd-netlink/netlink-message.c b/src/libsystemd/sd-netlink/netlink-message.c
index b0b25639f4..5e9bc45139 100644
--- a/src/libsystemd/sd-netlink/netlink-message.c
+++ b/src/libsystemd/sd-netlink/netlink-message.c
@@ -370,6 +370,42 @@ int sd_netlink_message_append_in6_addr(sd_netlink_message *m, unsigned short typ
return 0;
}
+int sd_netlink_message_append_sockaddr_in(sd_netlink_message *m, unsigned short type, const struct sockaddr_in *data) {
+ int r;
+
+ assert_return(m, -EINVAL);
+ assert_return(!m->sealed, -EPERM);
+ assert_return(data, -EINVAL);
+
+ r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_SOCKADDR);
+ if (r < 0)
+ return r;
+
+ r = add_rtattr(m, type, data, sizeof(struct sockaddr_in));
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
+int sd_netlink_message_append_sockaddr_in6(sd_netlink_message *m, unsigned short type, const struct sockaddr_in6 *data) {
+ int r;
+
+ assert_return(m, -EINVAL);
+ assert_return(!m->sealed, -EPERM);
+ assert_return(data, -EINVAL);
+
+ r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_SOCKADDR);
+ if (r < 0)
+ return r;
+
+ r = add_rtattr(m, type, data, sizeof(struct sockaddr_in6));
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
int sd_netlink_message_append_ether_addr(sd_netlink_message *m, unsigned short type, const struct ether_addr *data) {
int r;
diff --git a/src/libsystemd/sd-netlink/netlink-types.c b/src/libsystemd/sd-netlink/netlink-types.c
index cd5cdcc6e5..9dcd3f2ac8 100644
--- a/src/libsystemd/sd-netlink/netlink-types.c
+++ b/src/libsystemd/sd-netlink/netlink-types.c
@@ -721,7 +721,7 @@ static const NLType genl_wireguard_peer_types[] = {
[WGPEER_A_FLAGS] = { .type = NETLINK_TYPE_U32 },
[WGPEER_A_PRESHARED_KEY] = { .size = WG_KEY_LEN },
[WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL] = { .type = NETLINK_TYPE_U16 },
- [WGPEER_A_ENDPOINT] = { /* either size of sockaddr_in or sockaddr_in6 depending on address family */ },
+ [WGPEER_A_ENDPOINT] = { .type = NETLINK_TYPE_SOCKADDR },
[WGPEER_A_ALLOWEDIPS] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_wireguard_allowedip_type_system },
};
@@ -732,7 +732,7 @@ static const NLTypeSystem genl_wireguard_peer_type_system = {
static const NLType genl_wireguard_set_device_types[] = {
[WGDEVICE_A_IFINDEX] = { .type = NETLINK_TYPE_U32 },
- [WGDEVICE_A_IFNAME] = { .type = NETLINK_TYPE_STRING },
+ [WGDEVICE_A_IFNAME] = { .type = NETLINK_TYPE_STRING, .size = IFNAMSIZ-1 },
[WGDEVICE_A_FLAGS] = { .type = NETLINK_TYPE_U32 },
[WGDEVICE_A_PRIVATE_KEY] = { .size = WG_KEY_LEN },
[WGDEVICE_A_LISTEN_PORT] = { .type = NETLINK_TYPE_U16 },
diff --git a/src/libsystemd/sd-netlink/netlink-types.h b/src/libsystemd/sd-netlink/netlink-types.h
index 3133e4863d..b84fa4762b 100644
--- a/src/libsystemd/sd-netlink/netlink-types.h
+++ b/src/libsystemd/sd-netlink/netlink-types.h
@@ -16,6 +16,7 @@ enum {
NETLINK_TYPE_CACHE_INFO,
NETLINK_TYPE_NESTED, /* NLA_NESTED */
NETLINK_TYPE_UNION,
+ NETLINK_TYPE_SOCKADDR,
};
typedef enum NLMatchType {
diff --git a/src/libsystemd/sd-network/sd-network.c b/src/libsystemd/sd-network/sd-network.c
index d4b5e248cc..812826fe3d 100644
--- a/src/libsystemd/sd-network/sd-network.c
+++ b/src/libsystemd/sd-network/sd-network.c
@@ -276,11 +276,11 @@ _public_ int sd_network_link_get_carrier_bound_by(int ifindex, int **ret) {
return network_link_get_ifindexes(ifindex, "CARRIER_BOUND_BY", ret);
}
-static inline int MONITOR_TO_FD(sd_network_monitor *m) {
+static int MONITOR_TO_FD(sd_network_monitor *m) {
return (int) (unsigned long) m - 1;
}
-static inline sd_network_monitor* FD_TO_MONITOR(int fd) {
+static sd_network_monitor* FD_TO_MONITOR(int fd) {
return (sd_network_monitor*) (unsigned long) (fd + 1);
}
diff --git a/src/libsystemd/sd-resolve/sd-resolve.c b/src/libsystemd/sd-resolve/sd-resolve.c
index 21d783b8f0..36b9c8d019 100644
--- a/src/libsystemd/sd-resolve/sd-resolve.c
+++ b/src/libsystemd/sd-resolve/sd-resolve.c
@@ -912,7 +912,6 @@ static int alloc_query(sd_resolve *resolve, bool floating, sd_resolve_query **_q
return 0;
}
-
int resolve_getaddrinfo_with_destroy_callback(
sd_resolve *resolve,
sd_resolve_query **ret_query,
diff --git a/src/libudev/libudev-list.c b/src/libudev/libudev-list.c
index 5f6726c2d8..2737326187 100644
--- a/src/libudev/libudev-list.c
+++ b/src/libudev/libudev-list.c
@@ -61,7 +61,7 @@ static void udev_list_node_remove(struct udev_list_node *entry) {
}
/* return list entry which embeds this node */
-static inline struct udev_list_entry *list_node_to_entry(struct udev_list_node *node) {
+static struct udev_list_entry *list_node_to_entry(struct udev_list_node *node) {
return container_of(node, struct udev_list_entry, node);
}
diff --git a/src/libudev/libudev-util.c b/src/libudev/libudev-util.c
index f67ab40354..7e21719fbf 100644
--- a/src/libudev/libudev-util.c
+++ b/src/libudev/libudev-util.c
@@ -122,19 +122,20 @@ size_t util_path_encode(const char *src, char *dest, size_t size) {
*
* Note this may be called with 'str' == 'to', i.e. to replace whitespace
* in-place in a buffer. This function can handle that situation.
+ *
+ * Note that only 'len' characters are read from 'str'.
*/
size_t util_replace_whitespace(const char *str, char *to, size_t len) {
bool is_space = false;
- const char *p = str;
- size_t j;
+ size_t i, j;
assert(str);
assert(to);
- p += strspn(p, WHITESPACE);
+ i = strspn(str, WHITESPACE);
- for (j = 0; j < len && *p != '\0'; p++) {
- if (isspace(*p)) {
+ for (j = 0; j < len && i < len && str[i] != '\0'; i++) {
+ if (isspace(str[i])) {
is_space = true;
continue;
}
@@ -146,7 +147,7 @@ size_t util_replace_whitespace(const char *str, char *to, size_t len) {
to[j++] = '_';
is_space = false;
}
- to[j++] = *p;
+ to[j++] = str[i];
}
to[j] = '\0';
diff --git a/src/libudev/libudev.pc.in b/src/libudev/libudev.pc.in
index 69f5c6463e..40b340362e 100644
--- a/src/libudev/libudev.pc.in
+++ b/src/libudev/libudev.pc.in
@@ -14,6 +14,6 @@ includedir=@includedir@
Name: libudev
Description: Library to access udev device information
-Version: @PACKAGE_VERSION@
+Version: @PROJECT_VERSION@
Libs: -L${libdir} -ludev
Cflags: -I${includedir}
diff --git a/src/libudev/meson.build b/src/libudev/meson.build
index 8d86c34189..88189748d3 100644
--- a/src/libudev/meson.build
+++ b/src/libudev/meson.build
@@ -22,9 +22,8 @@ libudev_sym_path = meson.current_source_dir() + '/libudev.sym'
install_headers('libudev.h')
libudev_h_path = '@0@/libudev.h'.format(meson.current_source_dir())
-libudev_pc = configure_file(
+configure_file(
input : 'libudev.pc.in',
output : 'libudev.pc',
- configuration : substs)
-install_data(libudev_pc,
- install_dir : pkgconfiglibdir)
+ configuration : substs,
+ install_dir : pkgconfiglibdir == 'no' ? '' : pkgconfiglibdir)
diff --git a/src/login/logind-action.c b/src/login/logind-action.c
index e4e6c90191..6c9366761d 100644
--- a/src/login/logind-action.c
+++ b/src/login/logind-action.c
@@ -121,7 +121,7 @@ int manager_handle_action(
return -EOPNOTSUPP;
}
- if (m->action_what) {
+ if (m->action_what > 0) {
log_debug("Action already in progress, ignoring.");
return -EALREADY;
}
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index bd9f5ac4d6..8ab498fdc2 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -1474,23 +1474,15 @@ int manager_set_lid_switch_ignore(Manager *m, usec_t until) {
}
static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) {
-
- static const char * const signal_name[_INHIBIT_WHAT_MAX] = {
- [INHIBIT_SHUTDOWN] = "PrepareForShutdown",
- [INHIBIT_SLEEP] = "PrepareForSleep"
- };
-
int active = _active;
assert(m);
- assert(w >= 0);
- assert(w < _INHIBIT_WHAT_MAX);
- assert(signal_name[w]);
+ assert(IN_SET(w, INHIBIT_SHUTDOWN, INHIBIT_SLEEP));
return sd_bus_emit_signal(m->bus,
"/org/freedesktop/login1",
"org.freedesktop.login1.Manager",
- signal_name[w],
+ w == INHIBIT_SHUTDOWN ? "PrepareForShutdown" : "PrepareForSleep",
"b",
active);
}
@@ -1502,7 +1494,6 @@ static int execute_shutdown_or_sleep(
sd_bus_error *error) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- char *c = NULL;
const char *p;
int r;
@@ -1530,15 +1521,11 @@ static int execute_shutdown_or_sleep(
if (r < 0)
goto error;
- c = strdup(p);
- if (!c) {
- r = -ENOMEM;
+ r = free_and_strdup(&m->action_job, p);
+ if (r < 0)
goto error;
- }
m->action_unit = unit_name;
- free(m->action_job);
- m->action_job = c;
m->action_what = w;
/* Make sure the lid switch is ignored for a while */
@@ -1656,7 +1643,7 @@ int bus_manager_shutdown_or_sleep_now_or_later(
assert(m);
assert(unit_name);
assert(w > 0);
- assert(w <= _INHIBIT_WHAT_MAX);
+ assert(w < _INHIBIT_WHAT_MAX);
assert(!m->action_job);
r = unit_load_state(m->bus, unit_name, &load_state);
@@ -1773,7 +1760,7 @@ static int method_do_shutdown_or_sleep(
return r;
/* Don't allow multiple jobs being executed at the same time */
- if (m->action_what)
+ if (m->action_what > 0)
return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "There's already a shutdown or sleep operation in progress");
if (sleep_verb) {
@@ -2012,7 +1999,7 @@ static int manager_scheduled_shutdown_handler(
assert_not_reached("unexpected shutdown type");
/* Don't allow multiple jobs being executed at the same time */
- if (m->action_what) {
+ if (m->action_what > 0) {
r = -EALREADY;
log_error("Scheduled shutdown to %s failed: shutdown or sleep operation already in progress", target);
goto error;
diff --git a/src/login/logind-inhibit.h b/src/login/logind-inhibit.h
index d358a48559..650587106d 100644
--- a/src/login/logind-inhibit.h
+++ b/src/login/logind-inhibit.h
@@ -4,15 +4,15 @@
typedef struct Inhibitor Inhibitor;
typedef enum InhibitWhat {
- INHIBIT_SHUTDOWN = 1,
- INHIBIT_SLEEP = 2,
- INHIBIT_IDLE = 4,
- INHIBIT_HANDLE_POWER_KEY = 8,
- INHIBIT_HANDLE_SUSPEND_KEY = 16,
- INHIBIT_HANDLE_HIBERNATE_KEY = 32,
- INHIBIT_HANDLE_LID_SWITCH = 64,
- _INHIBIT_WHAT_MAX = 128,
- _INHIBIT_WHAT_INVALID = -1
+ INHIBIT_SHUTDOWN = 1 << 0,
+ INHIBIT_SLEEP = 1 << 1,
+ INHIBIT_IDLE = 1 << 2,
+ INHIBIT_HANDLE_POWER_KEY = 1 << 3,
+ INHIBIT_HANDLE_SUSPEND_KEY = 1 << 4,
+ INHIBIT_HANDLE_HIBERNATE_KEY = 1 << 5,
+ INHIBIT_HANDLE_LID_SWITCH = 1 << 6,
+ _INHIBIT_WHAT_MAX = 1 << 7,
+ _INHIBIT_WHAT_INVALID = -1
} InhibitWhat;
typedef enum InhibitMode {
diff --git a/src/login/logind-seat.c b/src/login/logind-seat.c
index c758ffd5fa..a6d88f8e7b 100644
--- a/src/login/logind-seat.c
+++ b/src/login/logind-seat.c
@@ -376,7 +376,7 @@ int seat_read_active_vt(Seat *s) {
k = read(s->manager->console_active_fd, t, sizeof(t)-1);
if (k <= 0) {
- log_error("Failed to read current console: %s", k < 0 ? strerror(-errno) : "EOF");
+ log_error("Failed to read current console: %s", k < 0 ? strerror(errno) : "EOF");
return k < 0 ? -errno : -EIO;
}
diff --git a/src/login/logind-session.c b/src/login/logind-session.c
index 4b4dd4c060..90a9108566 100644
--- a/src/login/logind-session.c
+++ b/src/login/logind-session.c
@@ -1227,54 +1227,26 @@ error:
}
static void session_restore_vt(Session *s) {
- pid_t pid;
- int r;
-
- if (s->vtnr < 1)
- return;
+ int r, vt, old_fd;
- if (s->vtfd < 0)
- return;
-
- /* The virtual terminal can potentially be entering in hung-up state at any time
- * depending on when the controlling process exits.
- *
- * If the controlling process exits while we're restoring the virtual terminal,
- * the VT will enter in hung-up state and we'll fail at restoring it. To prevent
- * this case, we kick off the current controlling process (if any) in a child
- * process so logind doesn't play around with tty ownership.
- *
- * If the controlling process already exited, getting a fresh handle to the
- * virtual terminal reset the hung-up state. */
- r = safe_fork("(logind)", FORK_REOPEN_LOG|FORK_CLOSE_ALL_FDS|FORK_RESET_SIGNALS|FORK_WAIT|FORK_LOG, &pid);
- if (r == 0) {
- char path[sizeof("/dev/tty") + DECIMAL_STR_MAX(s->vtnr)];
- int vt;
-
- /* We must be a session leader in order to become the controlling process. */
- pid = setsid();
- if (pid < 0) {
- log_error_errno(errno, "Failed to become session leader: %m");
- _exit(EXIT_FAILURE);
- }
+ /* We need to get a fresh handle to the virtual terminal,
+ * since the old file-descriptor is potentially in a hung-up
+ * state after the controlling process exited; we do a
+ * little dance to avoid having the terminal be available
+ * for reuse before we've cleaned it up.
+ */
+ old_fd = TAKE_FD(s->vtfd);
- sprintf(path, "/dev/tty%u", s->vtnr);
- vt = acquire_terminal(path, ACQUIRE_TERMINAL_FORCE, USEC_INFINITY);
- if (vt < 0) {
- log_error_errno(vt, "Cannot acquire VT %s of session %s: %m", path, s->id);
- _exit(EXIT_FAILURE);
- }
+ vt = session_open_vt(s);
+ safe_close(old_fd);
- r = vt_restore(vt);
- if (r < 0)
- log_warning_errno(r, "Failed to restore VT, ignoring: %m");
+ if (vt < 0)
+ return;
- /* Give up and release the controlling terminal. */
- safe_close(vt);
- _exit(EXIT_SUCCESS);
- }
+ r = vt_restore(vt);
+ if (r < 0)
+ log_warning_errno(r, "Failed to restore VT, ignoring: %m");
- /* Close the fd in any cases. */
s->vtfd = safe_close(s->vtfd);
}
diff --git a/src/login/logind.c b/src/login/logind.c
index 8d85de9b43..95ec0a57c6 100644
--- a/src/login/logind.c
+++ b/src/login/logind.c
@@ -146,7 +146,7 @@ static Manager* manager_unref(Manager *m) {
bus_verify_polkit_async_registry_free(m->polkit_registry);
- sd_bus_unref(m->bus);
+ sd_bus_flush_close_unref(m->bus);
sd_event_unref(m->event);
safe_close(m->reserve_vt_fd);
diff --git a/src/login/pam_systemd.c b/src/login/pam_systemd.c
index c7d9dcf4e2..997b74eb88 100644
--- a/src/login/pam_systemd.c
+++ b/src/login/pam_systemd.c
@@ -28,6 +28,7 @@
#include "path-util.h"
#include "process-util.h"
#include "socket-util.h"
+#include "stdio-util.h"
#include "strv.h"
#include "terminal-util.h"
#include "util.h"
@@ -190,6 +191,45 @@ static int get_seat_from_display(const char *display, const char **seat, uint32_
return 0;
}
+static int export_legacy_dbus_address(
+ pam_handle_t *handle,
+ uid_t uid,
+ const char *runtime) {
+
+ const char *s;
+ _cleanup_free_ char *t = NULL;
+ int r = PAM_BUF_ERR;
+
+ /* We need to export $DBUS_SESSION_BUS_ADDRESS because various applications will not connect
+ * correctly to the bus without it. This setting matches what dbus.socket does for the user
+ * session using 'systemctl --user set-environment'. We want to have the same configuration
+ * in processes started from the PAM session.
+ *
+ * The setting of the address is guarded by the access() check because it is also possible to compile
+ * dbus without --enable-user-session, in which case this socket is not used, and
+ * $DBUS_SESSION_BUS_ADDRESS should not be set. An alternative approach would to not do the access()
+ * check here, and let applications try on their own, by using "unix:path=%s/bus;autolaunch:". But we
+ * expect the socket to be present by the time we do this check, so we can just as well check once
+ * here. */
+
+ s = strjoina(runtime, "/bus");
+ if (access(s, F_OK) < 0)
+ return PAM_SUCCESS;
+
+ if (asprintf(&t, DEFAULT_USER_BUS_ADDRESS_FMT, runtime) < 0)
+ goto error;
+
+ r = pam_misc_setenv(handle, "DBUS_SESSION_BUS_ADDRESS", t, 0);
+ if (r != PAM_SUCCESS)
+ goto error;
+
+ return PAM_SUCCESS;
+
+error:
+ pam_syslog(handle, LOG_ERR, "Failed to set bus variable.");
+ return r;
+}
+
static int append_session_memory_max(pam_handle_t *handle, sd_bus_message *m, const char *limit) {
uint64_t val;
int r;
@@ -392,11 +432,9 @@ _public_ PAM_EXTERN int pam_sm_open_session(
pam_get_item(handle, PAM_SERVICE, (const void**) &service);
if (streq_ptr(service, "systemd-user")) {
- _cleanup_free_ char *rt = NULL;
-
- if (asprintf(&rt, "/run/user/"UID_FMT, pw->pw_uid) < 0)
- return PAM_BUF_ERR;
+ char rt[STRLEN("/run/user/") + DECIMAL_STR_MAX(uid_t)];
+ xsprintf(rt, "/run/user/"UID_FMT, pw->pw_uid);
if (validate_runtime_directory(handle, rt, pw->pw_uid)) {
r = pam_misc_setenv(handle, "XDG_RUNTIME_DIR", rt, 0);
if (r != PAM_SUCCESS) {
@@ -405,6 +443,10 @@ _public_ PAM_EXTERN int pam_sm_open_session(
}
}
+ r = export_legacy_dbus_address(handle, pw->pw_uid, rt);
+ if (r != PAM_SUCCESS)
+ return r;
+
return PAM_SUCCESS;
}
@@ -569,7 +611,7 @@ _public_ PAM_EXTERN int pam_sm_open_session(
if (r < 0) {
if (sd_bus_error_has_name(&error, BUS_ERROR_SESSION_BUSY)) {
if (debug)
- pam_syslog(handle, LOG_DEBUG, "Cannot create session: %s", bus_error_message(&error, r));
+ pam_syslog(handle, LOG_DEBUG, "Not creating session: %s", bus_error_message(&error, r));
return PAM_SUCCESS;
} else {
pam_syslog(handle, LOG_ERR, "Failed to create session: %s", bus_error_message(&error, r));
@@ -613,6 +655,10 @@ _public_ PAM_EXTERN int pam_sm_open_session(
if (r != PAM_SUCCESS)
return r;
}
+
+ r = export_legacy_dbus_address(handle, pw->pw_uid, runtime_path);
+ if (r != PAM_SUCCESS)
+ return r;
}
/* Most likely we got the session/type/class from environment variables, but might have gotten the data
diff --git a/src/login/user-runtime-dir.c b/src/login/user-runtime-dir.c
index 5e58e4baad..eb66e18de1 100644
--- a/src/login/user-runtime-dir.c
+++ b/src/login/user-runtime-dir.c
@@ -22,7 +22,7 @@
static int acquire_runtime_dir_size(uint64_t *ret) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
int r;
r = sd_bus_default_system(&bus);
diff --git a/src/machine/machine-dbus.c b/src/machine/machine-dbus.c
index 48270b3709..7a558df898 100644
--- a/src/machine/machine-dbus.c
+++ b/src/machine/machine-dbus.c
@@ -454,7 +454,7 @@ static int container_bus_new(Machine *m, sd_bus_error *error, sd_bus **ret) {
break;
case MACHINE_CONTAINER: {
- _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
+ _cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL;
char *address;
r = sd_bus_new(&bus);
diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c
index 44e6c76035..30f2e26a1e 100644
--- a/src/machine/machinectl.c
+++ b/src/machine/machinectl.c
@@ -1309,7 +1309,7 @@ static int on_machine_removed(sd_bus_message *m, void *userdata, sd_bus_error *r
static int process_forward(sd_event *event, PTYForward **forward, int master, PTYForwardFlags flags, const char *name) {
char last_char = 0;
bool machine_died;
- int ret = 0, r;
+ int r;
assert(event);
assert(master >= 0);
@@ -1355,8 +1355,7 @@ static int process_forward(sd_event *event, PTYForward **forward, int master, PT
log_info("Connection to machine %s terminated.", name);
}
- sd_event_get_exit_code(event, &ret);
- return ret;
+ return 0;
}
static int parse_machine_uid(const char *spec, const char **machine, char **uid) {
@@ -1740,7 +1739,7 @@ static int start_machine(int argc, char *argv[], void *userdata) {
if (r < 0)
return r;
if (r == 0) {
- log_error("Machine image '%s' does not exist.", argv[1]);
+ log_error("Machine image '%s' does not exist.", argv[i]);
return -ENXIO;
}
@@ -1812,7 +1811,7 @@ static int enable_machine(int argc, char *argv[], void *userdata) {
if (r < 0)
return r;
if (r == 0) {
- log_error("Machine image '%s' does not exist.", argv[1]);
+ log_error("Machine image '%s' does not exist.", argv[i]);
return -ENXIO;
}
diff --git a/src/machine/machined.c b/src/machine/machined.c
index 9f23e369a4..0b92b1c6ee 100644
--- a/src/machine/machined.c
+++ b/src/machine/machined.c
@@ -81,7 +81,7 @@ static Manager* manager_unref(Manager *m) {
bus_verify_polkit_async_registry_free(m->polkit_registry);
- sd_bus_unref(m->bus);
+ sd_bus_flush_close_unref(m->bus);
sd_event_unref(m->event);
return mfree(m);
diff --git a/src/network/netdev/bridge.c b/src/network/netdev/bridge.c
index 0c804adb2e..aadb3ab905 100644
--- a/src/network/netdev/bridge.c
+++ b/src/network/netdev/bridge.c
@@ -47,7 +47,7 @@ static int netdev_bridge_post_create(NetDev *netdev, Link *link, sd_netlink_mess
r = sd_netlink_message_open_container(req, IFLA_LINKINFO);
if (r < 0)
- return log_netdev_error_errno(netdev, r, "Could not append IFLA_PROTINFO attribute: %m");
+ return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINKINFO attribute: %m");
r = sd_netlink_message_open_container_union(req, IFLA_INFO_DATA, netdev_kind_to_string(netdev->kind));
if (r < 0)
diff --git a/src/network/netdev/netdev.c b/src/network/netdev/netdev.c
index f0e9d00246..0263917468 100644
--- a/src/network/netdev/netdev.c
+++ b/src/network/netdev/netdev.c
@@ -148,11 +148,16 @@ static void netdev_callbacks_clear(NetDev *netdev) {
}
}
+bool netdev_is_managed(NetDev *netdev) {
+ if (!netdev || !netdev->manager || !netdev->ifname)
+ return false;
+
+ return hashmap_get(netdev->manager->netdevs, netdev->ifname) == netdev;
+}
+
static void netdev_detach_from_manager(NetDev *netdev) {
if (netdev->ifname && netdev->manager)
hashmap_remove(netdev->manager->netdevs, netdev->ifname);
-
- netdev->manager = NULL;
}
static NetDev *netdev_free(NetDev *netdev) {
@@ -476,7 +481,7 @@ int netdev_get_mac(const char *ifname, struct ether_addr **ret) {
l = strlen(ifname);
sz = sizeof(sd_id128_t) + l;
- v = alloca(sz);
+ v = newa(uint8_t, sz);
/* fetch some persistent data unique to the machine */
r = sd_id128_get_machine((sd_id128_t*) v);
diff --git a/src/network/netdev/netdev.h b/src/network/netdev/netdev.h
index bfe1094181..d6524da0f3 100644
--- a/src/network/netdev/netdev.h
+++ b/src/network/netdev/netdev.h
@@ -156,6 +156,7 @@ NetDev *netdev_ref(NetDev *netdev);
DEFINE_TRIVIAL_DESTRUCTOR(netdev_destroy_callback, NetDev, netdev_unref);
DEFINE_TRIVIAL_CLEANUP_FUNC(NetDev*, netdev_unref);
+bool netdev_is_managed(NetDev *netdev);
int netdev_get(Manager *manager, const char *name, NetDev **ret);
int netdev_set_ifindex(NetDev *netdev, sd_netlink_message *newlink);
int netdev_get_mac(const char *ifname, struct ether_addr **ret);
diff --git a/src/network/netdev/wireguard.c b/src/network/netdev/wireguard.c
index 167cf65046..0c0b16d1da 100644
--- a/src/network/netdev/wireguard.c
+++ b/src/network/netdev/wireguard.c
@@ -45,22 +45,137 @@ static WireguardPeer *wireguard_peer_new(Wireguard *w, unsigned section) {
return peer;
}
-static int set_wireguard_interface(NetDev *netdev) {
+static int wireguard_set_ipmask_one(NetDev *netdev, sd_netlink_message *message, const WireguardIPmask *mask, uint16_t index) {
int r;
- unsigned i, j;
- WireguardPeer *peer, *peer_start;
- WireguardIPmask *mask, *mask_start = NULL;
+
+ assert(message);
+ assert(mask);
+ assert(index > 0);
+
+ /* This returns 1 on success, 0 on recoverable error, and negative errno on failure. */
+
+ r = sd_netlink_message_open_array(message, index);
+ if (r < 0)
+ return 0;
+
+ r = sd_netlink_message_append_u16(message, WGALLOWEDIP_A_FAMILY, mask->family);
+ if (r < 0)
+ goto cancel;
+
+ if (mask->family == AF_INET)
+ r = sd_netlink_message_append_in_addr(message, WGALLOWEDIP_A_IPADDR, &mask->ip.in);
+ else if (mask->family == AF_INET6)
+ r = sd_netlink_message_append_in6_addr(message, WGALLOWEDIP_A_IPADDR, &mask->ip.in6);
+ if (r < 0)
+ goto cancel;
+
+ r = sd_netlink_message_append_u8(message, WGALLOWEDIP_A_CIDR_MASK, mask->cidr);
+ if (r < 0)
+ goto cancel;
+
+ r = sd_netlink_message_close_container(message);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Could not add wireguard allowed ip: %m");
+
+ return 1;
+
+cancel:
+ r = sd_netlink_message_cancel_array(message);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Could not cancel wireguard allowed ip message attribute: %m");
+
+ return 0;
+}
+
+static int wireguard_set_peer_one(NetDev *netdev, sd_netlink_message *message, const WireguardPeer *peer, uint16_t index, WireguardIPmask **mask_start) {
+ WireguardIPmask *mask, *start;
+ uint16_t j = 0;
+ int r;
+
+ assert(message);
+ assert(peer);
+ assert(index > 0);
+ assert(mask_start);
+
+ /* This returns 1 on success, 0 on recoverable error, and negative errno on failure. */
+
+ start = *mask_start ?: peer->ipmasks;
+
+ r = sd_netlink_message_open_array(message, index);
+ if (r < 0)
+ return 0;
+
+ r = sd_netlink_message_append_data(message, WGPEER_A_PUBLIC_KEY, &peer->public_key, sizeof(peer->public_key));
+ if (r < 0)
+ goto cancel;
+
+ if (!*mask_start) {
+ r = sd_netlink_message_append_data(message, WGPEER_A_PRESHARED_KEY, &peer->preshared_key, WG_KEY_LEN);
+ if (r < 0)
+ goto cancel;
+
+ r = sd_netlink_message_append_u32(message, WGPEER_A_FLAGS, peer->flags);
+ if (r < 0)
+ goto cancel;
+
+ r = sd_netlink_message_append_u16(message, WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, peer->persistent_keepalive_interval);
+ if (r < 0)
+ goto cancel;
+
+ if (peer->endpoint.sa.sa_family == AF_INET)
+ r = sd_netlink_message_append_sockaddr_in(message, WGPEER_A_ENDPOINT, &peer->endpoint.in);
+ else if (peer->endpoint.sa.sa_family == AF_INET6)
+ r = sd_netlink_message_append_sockaddr_in6(message, WGPEER_A_ENDPOINT, &peer->endpoint.in6);
+ if (r < 0)
+ goto cancel;
+ }
+
+ r = sd_netlink_message_open_container(message, WGPEER_A_ALLOWEDIPS);
+ if (r < 0)
+ goto cancel;
+
+ LIST_FOREACH(ipmasks, mask, start) {
+ r = wireguard_set_ipmask_one(netdev, message, mask, ++j);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ break;
+ }
+
+ r = sd_netlink_message_close_container(message);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Could not add wireguard allowed ip: %m");
+
+ r = sd_netlink_message_close_container(message);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Could not add wireguard peer: %m");
+
+ *mask_start = mask; /* Start next cycle from this mask. */
+ return !mask;
+
+cancel:
+ r = sd_netlink_message_cancel_array(message);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Could not cancel wireguard peers: %m");
+
+ return 0;
+}
+
+static int wireguard_set_interface(NetDev *netdev) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL;
- Wireguard *w;
+ WireguardIPmask *mask_start = NULL;
+ WireguardPeer *peer, *peer_start;
uint32_t serial;
+ Wireguard *w;
+ int r;
assert(netdev);
w = WIREGUARD(netdev);
assert(w);
- peer_start = w->peers;
+ for (peer_start = w->peers; peer_start; ) {
+ uint16_t i = 0;
- do {
message = sd_netlink_message_unref(message);
r = sd_genl_message_new(netdev->manager->genl, SD_GENL_WIREGUARD, WG_CMD_SET_DEVICE, &message);
@@ -93,97 +208,14 @@ static int set_wireguard_interface(NetDev *netdev) {
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append wireguard peer attributes: %m");
- i = 0;
-
LIST_FOREACH(peers, peer, peer_start) {
- r = sd_netlink_message_open_array(message, ++i);
- if (r < 0)
- break;
-
- r = sd_netlink_message_append_data(message, WGPEER_A_PUBLIC_KEY, &peer->public_key, sizeof(peer->public_key));
+ r = wireguard_set_peer_one(netdev, message, peer, ++i, &mask_start);
if (r < 0)
+ return r;
+ if (r == 0)
break;
-
- if (!mask_start) {
- r = sd_netlink_message_append_data(message, WGPEER_A_PRESHARED_KEY, &peer->preshared_key, WG_KEY_LEN);
- if (r < 0)
- break;
-
- r = sd_netlink_message_append_u32(message, WGPEER_A_FLAGS, peer->flags);
- if (r < 0)
- break;
-
- r = sd_netlink_message_append_u16(message, WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, peer->persistent_keepalive_interval);
- if (r < 0)
- break;
-
- if (peer->endpoint.sa.sa_family == AF_INET) {
- r = sd_netlink_message_append_data(message, WGPEER_A_ENDPOINT, &peer->endpoint.in, sizeof(peer->endpoint.in));
- if (r < 0)
- break;
- } else if (peer->endpoint.sa.sa_family == AF_INET6) {
- r = sd_netlink_message_append_data(message, WGPEER_A_ENDPOINT, &peer->endpoint.in6, sizeof(peer->endpoint.in6));
- if (r < 0)
- break;
- }
-
- mask_start = peer->ipmasks;
- }
-
- r = sd_netlink_message_open_container(message, WGPEER_A_ALLOWEDIPS);
- if (r < 0) {
- mask_start = NULL;
- break;
- }
- j = 0;
- LIST_FOREACH(ipmasks, mask, mask_start) {
- r = sd_netlink_message_open_array(message, ++j);
- if (r < 0)
- break;
-
- r = sd_netlink_message_append_u16(message, WGALLOWEDIP_A_FAMILY, mask->family);
- if (r < 0)
- break;
-
- if (mask->family == AF_INET) {
- r = sd_netlink_message_append_in_addr(message, WGALLOWEDIP_A_IPADDR, &mask->ip.in);
- if (r < 0)
- break;
- } else if (mask->family == AF_INET6) {
- r = sd_netlink_message_append_in6_addr(message, WGALLOWEDIP_A_IPADDR, &mask->ip.in6);
- if (r < 0)
- break;
- }
-
- r = sd_netlink_message_append_u8(message, WGALLOWEDIP_A_CIDR_MASK, mask->cidr);
- if (r < 0)
- break;
-
- r = sd_netlink_message_close_container(message);
- if (r < 0)
- return log_netdev_error_errno(netdev, r, "Could not add wireguard allowed ip: %m");
- }
- mask_start = mask;
- if (mask_start) {
- r = sd_netlink_message_cancel_array(message);
- if (r < 0)
- return log_netdev_error_errno(netdev, r, "Could not cancel wireguard allowed ip message attribute: %m");
- }
- r = sd_netlink_message_close_container(message);
- if (r < 0)
- return log_netdev_error_errno(netdev, r, "Could not add wireguard allowed ip: %m");
-
- r = sd_netlink_message_close_container(message);
- if (r < 0)
- return log_netdev_error_errno(netdev, r, "Could not add wireguard peer: %m");
- }
-
- peer_start = peer;
- if (peer_start && !mask_start) {
- r = sd_netlink_message_cancel_array(message);
- if (r < 0)
- return log_netdev_error_errno(netdev, r, "Could not cancel wireguard peers: %m");
}
+ peer_start = peer; /* Start next cycle from this peer. */
r = sd_netlink_message_close_container(message);
if (r < 0)
@@ -192,8 +224,7 @@ static int set_wireguard_interface(NetDev *netdev) {
r = sd_netlink_send(netdev->manager->genl, message, &serial);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not set wireguard device: %m");
-
- } while (peer || mask_start);
+ }
return 0;
}
@@ -224,8 +255,7 @@ static int on_resolve_retry(sd_event_source *s, usec_t usec, void *userdata) {
w = WIREGUARD(netdev);
assert(w);
- if (!netdev->manager)
- /* The netdev is detached. */
+ if (!netdev_is_managed(netdev))
return 0;
assert(!w->unresolved_endpoints);
@@ -260,8 +290,7 @@ static int wireguard_resolve_handler(sd_resolve_query *q,
w = WIREGUARD(netdev);
assert(w);
- if (!netdev->manager)
- /* The netdev is detached. */
+ if (!netdev_is_managed(netdev))
return 0;
if (ret != 0) {
@@ -280,7 +309,7 @@ static int wireguard_resolve_handler(sd_resolve_query *q,
return 0;
}
- set_wireguard_interface(netdev);
+ (void) wireguard_set_interface(netdev);
if (w->failed_endpoints) {
_cleanup_(sd_event_source_unrefp) sd_event_source *s = NULL;
@@ -355,7 +384,7 @@ static int netdev_wireguard_post_create(NetDev *netdev, Link *link, sd_netlink_m
w = WIREGUARD(netdev);
assert(w);
- set_wireguard_interface(netdev);
+ (void) wireguard_set_interface(netdev);
resolve_endpoints(netdev);
return 0;
}
diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c
index 9f0a22b827..3cdbd9e37e 100644
--- a/src/network/networkd-address.c
+++ b/src/network/networkd-address.c
@@ -5,6 +5,7 @@
#include "alloc-util.h"
#include "conf-parser.h"
#include "firewall-util.h"
+#include "missing_network.h"
#include "netlink-util.h"
#include "networkd-address.h"
#include "networkd-manager.h"
@@ -351,18 +352,17 @@ int address_update(
address->cinfo = *cinfo;
link_update_operstate(address->link);
+ link_check_ready(address->link);
- if (!ready && address_is_ready(address)) {
- link_check_ready(address->link);
+ if (!ready &&
+ address_is_ready(address) &&
+ address->family == AF_INET6 &&
+ in_addr_is_link_local(AF_INET6, &address->in_addr) > 0 &&
+ in_addr_is_null(AF_INET6, (const union in_addr_union*) &address->link->ipv6ll_address) > 0) {
- if (address->family == AF_INET6 &&
- in_addr_is_link_local(AF_INET6, &address->in_addr) > 0 &&
- in_addr_is_null(AF_INET6, (const union in_addr_union*) &address->link->ipv6ll_address) > 0) {
-
- r = link_ipv6ll_gained(address->link, &address->in_addr.in6);
- if (r < 0)
- return r;
- }
+ r = link_ipv6ll_gained(address->link, &address->in_addr.in6);
+ if (r < 0)
+ return r;
}
return 0;
@@ -632,14 +632,10 @@ int address_configure(
r = sd_netlink_message_append_in6_addr(req, IFA_ADDRESS, &address->in_addr_peer.in6);
if (r < 0)
return log_error_errno(r, "Could not append IFA_ADDRESS attribute: %m");
- } else {
- if (address->family == AF_INET) {
- if (address->prefixlen <= 30) {
- r = sd_netlink_message_append_in_addr(req, IFA_BROADCAST, &address->broadcast);
- if (r < 0)
- return log_error_errno(r, "Could not append IFA_BROADCAST attribute: %m");
- }
- }
+ } else if (address->family == AF_INET && address->prefixlen <= 30) {
+ r = sd_netlink_message_append_in_addr(req, IFA_BROADCAST, &address->broadcast);
+ if (r < 0)
+ return log_error_errno(r, "Could not append IFA_BROADCAST attribute: %m");
}
if (address->label) {
@@ -648,8 +644,7 @@ int address_configure(
return log_error_errno(r, "Could not append IFA_LABEL attribute: %m");
}
- r = sd_netlink_message_append_cache_info(req, IFA_CACHEINFO,
- &address->cinfo);
+ r = sd_netlink_message_append_cache_info(req, IFA_CACHEINFO, &address->cinfo);
if (r < 0)
return log_error_errno(r, "Could not append IFA_CACHEINFO attribute: %m");
@@ -657,8 +652,7 @@ int address_configure(
if (r < 0)
return r;
- r = netlink_call_async(link->manager->rtnl, NULL, req, callback,
- link_netlink_destroy_callback, link);
+ r = netlink_call_async(link->manager->rtnl, NULL, req, callback, link_netlink_destroy_callback, link);
if (r < 0) {
address_release(address);
return log_error_errno(r, "Could not send rtnetlink message: %m");
@@ -666,7 +660,10 @@ int address_configure(
link_ref(link);
- r = address_add(link, address->family, &address->in_addr, address->prefixlen, NULL);
+ if (address->family == AF_INET6 && !in_addr_is_null(address->family, &address->in_addr_peer))
+ r = address_add(link, address->family, &address->in_addr_peer, address->prefixlen, NULL);
+ else
+ r = address_add(link, address->family, &address->in_addr, address->prefixlen, NULL);
if (r < 0) {
address_release(address);
return log_error_errno(r, "Could not add address: %m");
@@ -752,7 +749,15 @@ int config_parse_address(const char *unit,
return r;
/* Address=address/prefixlen */
- r = in_addr_default_prefix_from_string_auto(rvalue, &f, &buffer, &prefixlen);
+ r = in_addr_prefix_from_string_auto_internal(rvalue, PREFIXLEN_REFUSE, &f, &buffer, &prefixlen);
+ if (r == -ENOANO) {
+ log_syntax(unit, LOG_ERR, filename, line, r,
+ "An address '%s' is specified without prefix length. "
+ "The behavior of parsing addresses without prefix length will be changed in the future release. "
+ "Please specify prefix length explicitly.", rvalue);
+
+ r = in_addr_prefix_from_string_auto_internal(rvalue, PREFIXLEN_LEGACY, &f, &buffer, &prefixlen);
+ }
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, "Invalid address '%s', ignoring assignment: %m", rvalue);
return 0;
diff --git a/src/network/networkd-brvlan.c b/src/network/networkd-brvlan.c
index 1d18e29b7c..8377623da4 100644
--- a/src/network/networkd-brvlan.c
+++ b/src/network/networkd-brvlan.c
@@ -9,6 +9,7 @@
#include "alloc-util.h"
#include "conf-parser.h"
+#include "missing_if_bridge.h"
#include "netlink-util.h"
#include "networkd-brvlan.h"
#include "networkd-link.h"
@@ -22,7 +23,7 @@ static bool is_bit_set(unsigned bit, uint32_t scope) {
return scope & (1 << bit);
}
-static inline void set_bit(unsigned nr, uint32_t *addr) {
+static void set_bit(unsigned nr, uint32_t *addr) {
if (nr < BRIDGE_VLAN_BITMAP_MAX)
addr[nr / 32] |= (((uint32_t) 1) << (nr % 32));
}
diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c
index 980d49e4ff..d8ac4552f4 100644
--- a/src/network/networkd-dhcp4.c
+++ b/src/network/networkd-dhcp4.c
@@ -690,7 +690,7 @@ int dhcp4_set_client_identifier(Link *link) {
if (duid->type == DUID_TYPE_LLT && duid->raw_data_len == 0)
r = sd_dhcp_client_set_duid_llt(link->dhcp_client,
- duid->llt_time);
+ duid->llt_time);
else
r = sd_dhcp_client_set_duid(link->dhcp_client,
duid->type,
diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c
index ed6b9df72b..c1fba03f9f 100644
--- a/src/network/networkd-dhcp6.c
+++ b/src/network/networkd-dhcp6.c
@@ -11,6 +11,7 @@
#include "hashmap.h"
#include "hostname-util.h"
+#include "missing_network.h"
#include "network-internal.h"
#include "networkd-link.h"
#include "networkd-manager.h"
@@ -254,7 +255,6 @@ static int dhcp6_route_handler(sd_netlink *nl, sd_netlink_message *m, Link *link
return 1;
}
-
static int dhcp6_lease_pd_prefix_acquired(sd_dhcp6_client *client, Link *link) {
int r;
sd_dhcp6_lease *lease;
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index e2851df31a..22392d70bc 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -517,8 +517,6 @@ static void link_detach_from_manager(Link *link) {
hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex));
set_remove(link->manager->links_requesting_uuid, link);
link_clean(link);
-
- link->manager = NULL;
}
static Link *link_free(Link *link) {
@@ -730,70 +728,16 @@ static void link_enter_configured(Link *link) {
link_dirty(link);
}
-void link_check_ready(Link *link) {
- Address *a;
- Iterator i;
-
- assert(link);
-
- if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
- return;
-
- if (!link->network)
- return;
-
- if (!link->addresses_configured)
- return;
-
- if (!link->neighbors_configured)
- return;
-
- if (!link->static_routes_configured)
- return;
-
- if (!link->routing_policy_rules_configured)
- return;
-
- if (link_ipv4ll_enabled(link))
- if (!link->ipv4ll_address ||
- !link->ipv4ll_route)
- return;
-
- if (!link->network->bridge) {
-
- if (link_ipv6ll_enabled(link))
- if (in_addr_is_null(AF_INET6, (const union in_addr_union*) &link->ipv6ll_address) > 0)
- return;
-
- if ((link_dhcp4_enabled(link) && !link_dhcp6_enabled(link) &&
- !link->dhcp4_configured) ||
- (link_dhcp6_enabled(link) && !link_dhcp4_enabled(link) &&
- !link->dhcp6_configured) ||
- (link_dhcp4_enabled(link) && link_dhcp6_enabled(link) &&
- !link->dhcp4_configured && !link->dhcp6_configured))
- return;
-
- if (link_ipv6_accept_ra_enabled(link) && !link->ndisc_configured)
- return;
- }
-
- SET_FOREACH(a, link->addresses, i)
- if (!address_is_ready(a))
- return;
-
- if (link->state != LINK_STATE_CONFIGURED)
- link_enter_configured(link);
-
- return;
-}
-
-static int link_set_routing_policy_rule(Link *link) {
+static int link_request_set_routing_policy_rule(Link *link) {
RoutingPolicyRule *rule, *rrule = NULL;
int r;
assert(link);
assert(link->network);
+ link_set_state(link, LINK_STATE_CONFIGURING);
+ link->routing_policy_rules_configured = false;
+
LIST_FOREACH(rules, rule, link->network->rules) {
r = routing_policy_rule_get(link->manager, rule->family, &rule->from, rule->from_prefixlen, &rule->to,
rule->to_prefixlen, rule->tos, rule->fwmark, rule->table, rule->iif, rule->oif,
@@ -865,8 +809,11 @@ static int link_request_set_routes(Link *link) {
assert(link->state != _LINK_STATE_INVALID);
link_set_state(link, LINK_STATE_CONFIGURING);
+ link->static_routes_configured = false;
- (void) link_set_routing_policy_rule(link);
+ r = link_request_set_routing_policy_rule(link);
+ if (r < 0)
+ return r;
/* First add the routes that enable us to talk to gateways, then add in the others that need a gateway. */
for (phase = 0; phase < _PHASE_MAX; phase++)
@@ -894,6 +841,68 @@ static int link_request_set_routes(Link *link) {
return 0;
}
+void link_check_ready(Link *link) {
+ Address *a;
+ Iterator i;
+
+ assert(link);
+
+ if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
+ return;
+
+ if (!link->network)
+ return;
+
+ if (!link->addresses_configured)
+ return;
+
+ if (!link->neighbors_configured)
+ return;
+
+ SET_FOREACH(a, link->addresses, i)
+ if (!address_is_ready(a))
+ return;
+
+ if (!link->addresses_ready) {
+ link->addresses_ready = true;
+ link_request_set_routes(link);
+ }
+
+ if (!link->static_routes_configured)
+ return;
+
+ if (!link->routing_policy_rules_configured)
+ return;
+
+ if (link_ipv4ll_enabled(link))
+ if (!link->ipv4ll_address ||
+ !link->ipv4ll_route)
+ return;
+
+ if (!link->network->bridge) {
+
+ if (link_ipv6ll_enabled(link))
+ if (in_addr_is_null(AF_INET6, (const union in_addr_union*) &link->ipv6ll_address) > 0)
+ return;
+
+ if ((link_dhcp4_enabled(link) && !link_dhcp6_enabled(link) &&
+ !link->dhcp4_configured) ||
+ (link_dhcp6_enabled(link) && !link_dhcp4_enabled(link) &&
+ !link->dhcp6_configured) ||
+ (link_dhcp4_enabled(link) && link_dhcp6_enabled(link) &&
+ !link->dhcp4_configured && !link->dhcp6_configured))
+ return;
+
+ if (link_ipv6_accept_ra_enabled(link) && !link->ndisc_configured)
+ return;
+ }
+
+ if (link->state != LINK_STATE_CONFIGURED)
+ link_enter_configured(link);
+
+ return;
+}
+
static int link_request_set_neighbors(Link *link) {
Neighbor *neighbor;
int r;
@@ -903,6 +912,7 @@ static int link_request_set_neighbors(Link *link) {
assert(link->state != _LINK_STATE_INVALID);
link_set_state(link, LINK_STATE_CONFIGURING);
+ link->neighbors_configured = false;
LIST_FOREACH(neighbors, neighbor, link->network->neighbors) {
r = neighbor_configure(neighbor, link, NULL);
@@ -947,7 +957,7 @@ static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link)
if (link->address_messages == 0) {
log_link_debug(link, "Addresses set");
link->addresses_configured = true;
- link_request_set_routes(link);
+ link_check_ready(link);
}
return 1;
@@ -1073,16 +1083,29 @@ static int link_request_set_addresses(Link *link) {
assert(link->network);
assert(link->state != _LINK_STATE_INVALID);
+ link_set_state(link, LINK_STATE_CONFIGURING);
+
+ /* Reset all *_configured flags we are configuring. */
+ link->addresses_configured = false;
+ link->addresses_ready = false;
+ link->neighbors_configured = false;
+ link->static_routes_configured = false;
+ link->routing_policy_rules_configured = false;
+
r = link_set_bridge_fdb(link);
if (r < 0)
return r;
- link_set_state(link, LINK_STATE_CONFIGURING);
-
- link_request_set_neighbors(link);
+ r = link_request_set_neighbors(link);
+ if (r < 0)
+ return r;
LIST_FOREACH(addresses, ad, link->network->static_addresses) {
- r = address_configure(ad, link, address_handler, false);
+ bool update;
+
+ update = address_get(link, ad->family, &ad->in_addr, ad->prefixlen, NULL) > 0;
+
+ r = address_configure(ad, link, address_handler, update);
if (r < 0) {
log_link_warning_errno(link, r, "Could not set addresses: %m");
link_enter_failed(link);
@@ -1207,14 +1230,15 @@ static int link_request_set_addresses(Link *link) {
return r;
}
}
+ if (!sd_dhcp_server_is_running(link->dhcp_server)) {
+ r = sd_dhcp_server_start(link->dhcp_server);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "Could not start DHCPv4 server instance: %m");
- r = sd_dhcp_server_start(link->dhcp_server);
- if (r < 0) {
- log_link_warning_errno(link, r, "Could not start DHCPv4 server instance: %m");
-
- link_enter_failed(link);
+ link_enter_failed(link);
- return 0;
+ return 0;
+ }
}
log_link_debug(link, "Offering DHCPv4 leases");
@@ -1222,7 +1246,7 @@ static int link_request_set_addresses(Link *link) {
if (link->address_messages == 0) {
link->addresses_configured = true;
- link_request_set_routes(link);
+ link_check_ready(link);
} else
log_link_debug(link, "Setting addresses");
@@ -1739,6 +1763,84 @@ bool link_has_carrier(Link *link) {
return false;
}
+static int link_address_genmode_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+ int r;
+
+ assert(link);
+
+ if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
+ return 1;
+
+ r = sd_netlink_message_get_errno(m);
+ if (r < 0)
+ log_link_warning_errno(link, r, "Could not set address genmode for interface: %m");
+
+ return 1;
+}
+
+static int link_configure_addrgen_mode(Link *link) {
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
+ uint8_t ipv6ll_mode;
+ int r;
+
+ assert(link);
+ assert(link->network);
+ assert(link->manager);
+ assert(link->manager->rtnl);
+
+ log_link_debug(link, "Setting address genmode for link");
+
+ r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
+
+ r = sd_netlink_message_open_container(req, IFLA_AF_SPEC);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not open IFLA_AF_SPEC container: %m");
+
+ r = sd_netlink_message_open_container(req, AF_INET6);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not open AF_INET6 container: %m");
+
+ if (!link_ipv6ll_enabled(link))
+ ipv6ll_mode = IN6_ADDR_GEN_MODE_NONE;
+ else {
+ const char *p = NULL;
+ _cleanup_free_ char *stable_secret = NULL;
+
+ p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/stable_secret");
+
+ /* The file may not exist. And event if it exists, when stable_secret is unset,
+ * then reading the file fails and EIO is returned. */
+ r = read_one_line_file(p, &stable_secret);
+ if (r < 0)
+ ipv6ll_mode = IN6_ADDR_GEN_MODE_EUI64;
+ else
+ ipv6ll_mode = IN6_ADDR_GEN_MODE_STABLE_PRIVACY;
+ }
+
+ r = sd_netlink_message_append_u8(req, IFLA_INET6_ADDR_GEN_MODE, ipv6ll_mode);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append IFLA_INET6_ADDR_GEN_MODE: %m");
+
+ r = sd_netlink_message_close_container(req);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not close AF_INET6 container: %m");
+
+ r = sd_netlink_message_close_container(req);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not close IFLA_AF_SPEC container: %m");
+
+ r = netlink_call_async(link->manager->rtnl, NULL, req, link_address_genmode_handler,
+ link_netlink_destroy_callback, link);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
+
+ link_ref(link);
+
+ return 0;
+}
+
static int link_up_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
int r;
@@ -1755,9 +1857,8 @@ static int link_up_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link)
return 1;
}
-int link_up(Link *link) {
+static int link_up(Link *link) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
- uint8_t ipv6ll_mode;
int r;
assert(link);
@@ -1788,34 +1889,16 @@ int link_up(Link *link) {
return log_link_error_errno(link, r, "Could not set MAC address: %m");
}
- r = sd_netlink_message_open_container(req, IFLA_AF_SPEC);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not open IFLA_AF_SPEC container: %m");
-
if (link_ipv6_enabled(link)) {
+ r = sd_netlink_message_open_container(req, IFLA_AF_SPEC);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not open IFLA_AF_SPEC container: %m");
+
/* if the kernel lacks ipv6 support setting IFF_UP fails if any ipv6 options are passed */
r = sd_netlink_message_open_container(req, AF_INET6);
if (r < 0)
return log_link_error_errno(link, r, "Could not open AF_INET6 container: %m");
- if (!link_ipv6ll_enabled(link))
- ipv6ll_mode = IN6_ADDR_GEN_MODE_NONE;
- else {
- const char *p = NULL;
- _cleanup_free_ char *stable_secret = NULL;
-
- p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/stable_secret");
- r = read_one_line_file(p, &stable_secret);
-
- if (r < 0)
- ipv6ll_mode = IN6_ADDR_GEN_MODE_EUI64;
- else
- ipv6ll_mode = IN6_ADDR_GEN_MODE_STABLE_PRIVACY;
- }
- r = sd_netlink_message_append_u8(req, IFLA_INET6_ADDR_GEN_MODE, ipv6ll_mode);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not append IFLA_INET6_ADDR_GEN_MODE: %m");
-
if (!in_addr_is_null(AF_INET6, &link->network->ipv6_token)) {
r = sd_netlink_message_append_in6_addr(req, IFLA_INET6_TOKEN, &link->network->ipv6_token.in6);
if (r < 0)
@@ -1825,11 +1908,11 @@ int link_up(Link *link) {
r = sd_netlink_message_close_container(req);
if (r < 0)
return log_link_error_errno(link, r, "Could not close AF_INET6 container: %m");
- }
- r = sd_netlink_message_close_container(req);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not close IFLA_AF_SPEC container: %m");
+ r = sd_netlink_message_close_container(req);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not close IFLA_AF_SPEC container: %m");
+ }
r = netlink_call_async(link->manager->rtnl, NULL, req, link_up_handler,
link_netlink_destroy_callback, link);
@@ -2918,6 +3001,12 @@ static int link_configure(Link *link) {
return r;
}
+ if (socket_ipv6_is_supported()) {
+ r = link_configure_addrgen_mode(link);
+ if (r < 0)
+ return r;
+ }
+
return link_configure_after_setting_mtu(link);
}
diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h
index 00e68fdfaa..dcb1ea68dd 100644
--- a/src/network/networkd-link.h
+++ b/src/network/networkd-link.h
@@ -82,6 +82,7 @@ typedef struct Link {
Set *routes_foreign;
bool addresses_configured;
+ bool addresses_ready;
sd_dhcp_client *dhcp_client;
sd_dhcp_lease *dhcp_lease;
@@ -142,7 +143,6 @@ int link_get(Manager *m, int ifindex, Link **ret);
int link_add(Manager *manager, sd_netlink_message *message, Link **ret);
void link_drop(Link *link);
-int link_up(Link *link);
int link_down(Link *link);
void link_enter_failed(Link *link);
diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c
index 81c81f18af..c8d369e2a0 100644
--- a/src/network/networkd-manager.c
+++ b/src/network/networkd-manager.c
@@ -1456,7 +1456,7 @@ void manager_free(Manager *m) {
sd_device_monitor_unref(m->device_monitor);
- sd_bus_unref(m->bus);
+ sd_bus_flush_close_unref(m->bus);
free(m->dynamic_timezone);
free(m->dynamic_hostname);
diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c
index 80bfd2cba1..e5b8d11555 100644
--- a/src/network/networkd-ndisc.c
+++ b/src/network/networkd-ndisc.c
@@ -8,6 +8,7 @@
#include "sd-ndisc.h"
+#include "missing_network.h"
#include "networkd-ndisc.h"
#include "networkd-route.h"
#include "strv.h"
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index ccc1c3ce89..12344ec695 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -98,12 +98,13 @@ void network_apply_anonymize_if_set(Network *network) {
}
int network_load_one(Manager *manager, const char *filename) {
+ _cleanup_free_ char *fname = NULL, *name = NULL;
_cleanup_(network_freep) Network *network = NULL;
_cleanup_fclose_ FILE *file = NULL;
- char *d;
const char *dropin_dirname;
- Route *route;
Address *address;
+ Route *route;
+ char *d;
int r;
assert(manager);
@@ -122,12 +123,30 @@ int network_load_one(Manager *manager, const char *filename) {
return 0;
}
+ fname = strdup(filename);
+ if (!fname)
+ return log_oom();
+
+ name = strdup(basename(filename));
+ if (!name)
+ return log_oom();
+
+ d = strrchr(name, '.');
+ if (!d)
+ return -EINVAL;
+
+ *d = '\0';
+
+ dropin_dirname = strjoina(name, ".network.d");
+
network = new(Network, 1);
if (!network)
return log_oom();
*network = (Network) {
.manager = manager,
+ .filename = TAKE_PTR(fname),
+ .name = TAKE_PTR(name),
.required_for_online = true,
.dhcp = ADDRESS_FAMILY_NO,
@@ -190,22 +209,6 @@ int network_load_one(Manager *manager, const char *filename) {
.ipv6_accept_ra_route_table = RT_TABLE_MAIN,
};
- network->filename = strdup(filename);
- if (!network->filename)
- return log_oom();
-
- network->name = strdup(basename(filename));
- if (!network->name)
- return log_oom();
-
- d = strrchr(network->name, '.');
- if (!d)
- return -EINVAL;
-
- *d = '\0';
-
- dropin_dirname = strjoina(network->name, ".network.d");
-
r = config_parse_many(filename, network_dirs, dropin_dirname,
"Match\0"
"Link\0"
@@ -228,8 +231,11 @@ int network_load_one(Manager *manager, const char *filename) {
"CAN\0",
config_item_perf_lookup, network_network_gperf_lookup,
CONFIG_PARSE_WARN, network);
- if (r < 0)
+ if (r < 0) {
+ /* Unset manager here. Otherwise, LIST_REMOVE() in network_free() fails. */
+ network->manager = NULL;
return r;
+ }
network_apply_anonymize_if_set(network);
@@ -253,21 +259,19 @@ int network_load_one(Manager *manager, const char *filename) {
if (r < 0)
return r;
- LIST_FOREACH(routes, route, network->static_routes) {
+ LIST_FOREACH(routes, route, network->static_routes)
if (!route->family) {
log_warning("Route section without Gateway field configured in %s. "
"Ignoring", filename);
return 0;
}
- }
- LIST_FOREACH(addresses, address, network->static_addresses) {
+ LIST_FOREACH(addresses, address, network->static_addresses)
if (!address->family) {
log_warning("Address section without Address field configured in %s. "
"Ignoring", filename);
return 0;
}
- }
network = NULL;
diff --git a/src/network/wait-online/manager.c b/src/network/wait-online/manager.c
index e1ccc9ff67..67218b6db3 100644
--- a/src/network/wait-online/manager.c
+++ b/src/network/wait-online/manager.c
@@ -89,16 +89,25 @@ static int manager_process_link(sd_netlink *rtnl, sd_netlink_message *mm, void *
assert(mm);
r = sd_netlink_message_get_type(mm, &type);
- if (r < 0)
- goto fail;
+ if (r < 0) {
+ log_warning_errno(r, "rtnl: Could not get message type, ignoring: %m");
+ return 0;
+ }
r = sd_rtnl_message_link_get_ifindex(mm, &ifindex);
- if (r < 0)
- goto fail;
+ if (r < 0) {
+ log_warning_errno(r, "rtnl: Could not get ifindex from link, ignoring: %m");
+ return 0;
+ } else if (ifindex <= 0) {
+ log_warning("rtnl: received link message with invalid ifindex %d, ignoring", ifindex);
+ return 0;
+ }
r = sd_netlink_message_read_string(mm, IFLA_IFNAME, &ifname);
- if (r < 0)
- goto fail;
+ if (r < 0) {
+ log_warning_errno(r, "rtnl: Received link message without ifname, ignoring: %m");
+ return 0;
+ }
l = hashmap_get(m->links, INT_TO_PTR(ifindex));
@@ -110,16 +119,16 @@ static int manager_process_link(sd_netlink *rtnl, sd_netlink_message *mm, void *
r = link_new(m, &l, ifindex, ifname);
if (r < 0)
- goto fail;
+ return log_error_errno(r, "Failed to create link object: %m");
r = link_update_monitor(l);
if (r < 0)
- goto fail;
+ return log_error_errno(r, "Failed to initialize link object: %m");
}
r = link_update_rtnl(l, mm);
if (r < 0)
- goto fail;
+ return log_warning_errno(r, "Failed to process RTNL link message: %m");;
break;
@@ -133,10 +142,6 @@ static int manager_process_link(sd_netlink *rtnl, sd_netlink_message *mm, void *
}
return 0;
-
-fail:
- log_warning_errno(r, "Failed to process RTNL link message: %m");
- return 0;
}
static int on_rtnl_event(sd_netlink *rtnl, sd_netlink_message *mm, void *userdata) {
diff --git a/src/nspawn/nspawn-network.c b/src/nspawn/nspawn-network.c
index 9d0f8a9956..c028b5755a 100644
--- a/src/nspawn/nspawn-network.c
+++ b/src/nspawn/nspawn-network.c
@@ -67,7 +67,7 @@ static int generate_mac(
if (idx > 0)
sz += sizeof(idx);
- v = alloca(sz);
+ v = newa(uint8_t, sz);
/* fetch some persistent data unique to the host */
r = sd_id128_get_machine((sd_id128_t*) v);
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index 91c97b60a7..e0c2d711e6 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -1964,11 +1964,11 @@ static int setup_hostname(void) {
}
static int setup_journal(const char *directory) {
- sd_id128_t this_id;
_cleanup_free_ char *d = NULL;
- const char *p, *q;
+ const char *dirname, *p, *q;
+ sd_id128_t this_id;
+ char id[33];
bool try;
- char id[33], *dirname;
int r;
/* Don't link journals in ephemeral mode */
@@ -4230,6 +4230,11 @@ int main(int argc, char *argv[]) {
if (r < 0)
goto finish;
+ /* Ignore SIGPIPE here, because we use splice() on the ptyfwd stuff and that will generate SIGPIPE if
+ * the result is closed. Note that the container payload child will reset signal mask+handler anyway,
+ * so just turning this off here means we only turn it off in nspawn itself, not any children. */
+ (void) ignore_signals(SIGPIPE, -1);
+
n_fd_passed = sd_listen_fds(false);
if (n_fd_passed > 0) {
r = fdset_new_listen_fds(&fds, false);
diff --git a/src/nss-myhostname/nss-myhostname.c b/src/nss-myhostname/nss-myhostname.c
index 5abc0c91bf..e491351dee 100644
--- a/src/nss-myhostname/nss-myhostname.c
+++ b/src/nss-myhostname/nss-myhostname.c
@@ -74,6 +74,7 @@ enum nss_status _nss_myhostname_gethostbyname4_r(
} else {
hn = gethostname_malloc();
if (!hn) {
+ UNPROTECT_ERRNO;
*errnop = ENOMEM;
*h_errnop = NO_RECOVERY;
return NSS_STATUS_TRYAGAIN;
@@ -96,6 +97,7 @@ enum nss_status _nss_myhostname_gethostbyname4_r(
l = strlen(canonical);
ms = ALIGN(l+1) + ALIGN(sizeof(struct gaih_addrtuple)) * (n_addresses > 0 ? n_addresses : 2);
if (buflen < ms) {
+ UNPROTECT_ERRNO;
*errnop = ERANGE;
*h_errnop = NETDB_INTERNAL;
return NSS_STATUS_TRYAGAIN;
@@ -186,6 +188,8 @@ static enum nss_status fill_in_hostent(
assert(errnop);
assert(h_errnop);
+ PROTECT_ERRNO;
+
alen = FAMILY_ADDRESS_SIZE(af);
for (a = addresses, n = 0, c = 0; n < n_addresses; a++, n++)
@@ -202,6 +206,7 @@ static enum nss_status fill_in_hostent(
(c > 0 ? c+1 : 2) * sizeof(char*);
if (buflen < ms) {
+ UNPROTECT_ERRNO;
*errnop = ERANGE;
*h_errnop = NETDB_INTERNAL;
return NSS_STATUS_TRYAGAIN;
@@ -321,6 +326,7 @@ enum nss_status _nss_myhostname_gethostbyname3_r(
af = AF_INET;
if (!IN_SET(af, AF_INET, AF_INET6)) {
+ UNPROTECT_ERRNO;
*errnop = EAFNOSUPPORT;
*h_errnop = NO_DATA;
return NSS_STATUS_UNAVAIL;
@@ -343,6 +349,7 @@ enum nss_status _nss_myhostname_gethostbyname3_r(
} else {
hn = gethostname_malloc();
if (!hn) {
+ UNPROTECT_ERRNO;
*errnop = ENOMEM;
*h_errnop = NO_RECOVERY;
return NSS_STATUS_TRYAGAIN;
@@ -362,6 +369,8 @@ enum nss_status _nss_myhostname_gethostbyname3_r(
local_address_ipv4 = LOCALADDRESS_IPV4;
}
+ UNPROTECT_ERRNO;
+
return fill_in_hostent(
canonical, additional,
af,
@@ -401,12 +410,14 @@ enum nss_status _nss_myhostname_gethostbyaddr2_r(
assert(h_errnop);
if (!IN_SET(af, AF_INET, AF_INET6)) {
+ UNPROTECT_ERRNO;
*errnop = EAFNOSUPPORT;
*h_errnop = NO_DATA;
return NSS_STATUS_UNAVAIL;
}
if (len != FAMILY_ADDRESS_SIZE(af)) {
+ UNPROTECT_ERRNO;
*errnop = EINVAL;
*h_errnop = NO_RECOVERY;
return NSS_STATUS_UNAVAIL;
@@ -461,6 +472,7 @@ found:
if (!canonical || additional_from_hostname) {
hn = gethostname_malloc();
if (!hn) {
+ UNPROTECT_ERRNO;
*errnop = ENOMEM;
*h_errnop = NO_RECOVERY;
return NSS_STATUS_TRYAGAIN;
@@ -472,6 +484,7 @@ found:
additional = hn;
}
+ UNPROTECT_ERRNO;
return fill_in_hostent(
canonical, additional,
af,
diff --git a/src/nss-mymachines/nss-mymachines.c b/src/nss-mymachines/nss-mymachines.c
index 3d1fc28353..486a658958 100644
--- a/src/nss-mymachines/nss-mymachines.c
+++ b/src/nss-mymachines/nss-mymachines.c
@@ -153,6 +153,7 @@ enum nss_status _nss_mymachines_gethostbyname4_r(
l = strlen(name);
ms = ALIGN(l+1) + ALIGN(sizeof(struct gaih_addrtuple)) * c;
if (buflen < ms) {
+ UNPROTECT_ERRNO;
*errnop = ERANGE;
*h_errnop = NETDB_INTERNAL;
return NSS_STATUS_TRYAGAIN;
@@ -227,6 +228,7 @@ enum nss_status _nss_mymachines_gethostbyname4_r(
return NSS_STATUS_SUCCESS;
fail:
+ UNPROTECT_ERRNO;
*errnop = -r;
*h_errnop = NO_DATA;
return NSS_STATUS_UNAVAIL;
@@ -313,6 +315,7 @@ enum nss_status _nss_mymachines_gethostbyname3_r(
ms = ALIGN(l+1) + c * ALIGN(alen) + (c+2) * sizeof(char*);
if (buflen < ms) {
+ UNPROTECT_ERRNO;
*errnop = ERANGE;
*h_errnop = NETDB_INTERNAL;
return NSS_STATUS_TRYAGAIN;
@@ -396,6 +399,7 @@ enum nss_status _nss_mymachines_gethostbyname3_r(
return NSS_STATUS_SUCCESS;
fail:
+ UNPROTECT_ERRNO;
*errnop = -r;
*h_errnop = NO_DATA;
return NSS_STATUS_UNAVAIL;
@@ -484,6 +488,7 @@ enum nss_status _nss_mymachines_getpwnam_r(
l = strlen(name);
if (buflen < l+1) {
+ UNPROTECT_ERRNO;
*errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
@@ -501,6 +506,7 @@ enum nss_status _nss_mymachines_getpwnam_r(
return NSS_STATUS_SUCCESS;
fail:
+ UNPROTECT_ERRNO;
*errnop = -r;
return NSS_STATUS_UNAVAIL;
}
@@ -564,6 +570,7 @@ enum nss_status _nss_mymachines_getpwuid_r(
return NSS_STATUS_NOTFOUND;
if (snprintf(buffer, buflen, "vu-%s-" UID_FMT, machine, (uid_t) mapped) >= (int) buflen) {
+ UNPROTECT_ERRNO;
*errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
@@ -579,6 +586,7 @@ enum nss_status _nss_mymachines_getpwuid_r(
return NSS_STATUS_SUCCESS;
fail:
+ UNPROTECT_ERRNO;
*errnop = -r;
return NSS_STATUS_UNAVAIL;
}
@@ -662,6 +670,7 @@ enum nss_status _nss_mymachines_getgrnam_r(
l = sizeof(char*) + strlen(name) + 1;
if (buflen < l) {
+ UNPROTECT_ERRNO;
*errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
@@ -677,6 +686,7 @@ enum nss_status _nss_mymachines_getgrnam_r(
return NSS_STATUS_SUCCESS;
fail:
+ UNPROTECT_ERRNO;
*errnop = -r;
return NSS_STATUS_UNAVAIL;
}
@@ -740,12 +750,14 @@ enum nss_status _nss_mymachines_getgrgid_r(
return NSS_STATUS_NOTFOUND;
if (buflen < sizeof(char*) + 1) {
+ UNPROTECT_ERRNO;
*errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
memzero(buffer, sizeof(char*));
if (snprintf(buffer + sizeof(char*), buflen - sizeof(char*), "vg-%s-" GID_FMT, machine, (gid_t) mapped) >= (int) buflen) {
+ UNPROTECT_ERRNO;
*errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
@@ -758,6 +770,7 @@ enum nss_status _nss_mymachines_getgrgid_r(
return NSS_STATUS_SUCCESS;
fail:
+ UNPROTECT_ERRNO;
*errnop = -r;
return NSS_STATUS_UNAVAIL;
}
diff --git a/src/nss-resolve/nss-resolve.c b/src/nss-resolve/nss-resolve.c
index a28b5d8ba8..8370fed076 100644
--- a/src/nss-resolve/nss-resolve.c
+++ b/src/nss-resolve/nss-resolve.c
@@ -186,6 +186,7 @@ enum nss_status _nss_resolve_gethostbyname4_r(
l = strlen(canonical);
ms = ALIGN(l+1) + ALIGN(sizeof(struct gaih_addrtuple)) * c;
if (buflen < ms) {
+ UNPROTECT_ERRNO;
*errnop = ERANGE;
*h_errnop = NETDB_INTERNAL;
return NSS_STATUS_TRYAGAIN;
@@ -267,6 +268,7 @@ enum nss_status _nss_resolve_gethostbyname4_r(
return NSS_STATUS_SUCCESS;
fail:
+ UNPROTECT_ERRNO;
*errnop = -r;
*h_errnop = NO_RECOVERY;
return ret;
@@ -364,6 +366,7 @@ enum nss_status _nss_resolve_gethostbyname3_r(
ms = ALIGN(l+1) + c * ALIGN(alen) + (c+2) * sizeof(char*);
if (buflen < ms) {
+ UNPROTECT_ERRNO;
*errnop = ERANGE;
*h_errnop = NETDB_INTERNAL;
return NSS_STATUS_TRYAGAIN;
@@ -455,6 +458,7 @@ enum nss_status _nss_resolve_gethostbyname3_r(
return NSS_STATUS_SUCCESS;
fail:
+ UNPROTECT_ERRNO;
*errnop = -r;
*h_errnop = NO_RECOVERY;
return ret;
@@ -492,12 +496,14 @@ enum nss_status _nss_resolve_gethostbyaddr2_r(
assert(h_errnop);
if (!IN_SET(af, AF_INET, AF_INET6)) {
+ UNPROTECT_ERRNO;
*errnop = EAFNOSUPPORT;
*h_errnop = NO_DATA;
return NSS_STATUS_UNAVAIL;
}
if (len != FAMILY_ADDRESS_SIZE(af)) {
+ UNPROTECT_ERRNO;
*errnop = EINVAL;
*h_errnop = NO_RECOVERY;
return NSS_STATUS_UNAVAIL;
@@ -576,6 +582,7 @@ enum nss_status _nss_resolve_gethostbyaddr2_r(
c * sizeof(char*); /* pointers to aliases, plus trailing NULL */
if (buflen < ms) {
+ UNPROTECT_ERRNO;
*errnop = ERANGE;
*h_errnop = NETDB_INTERNAL;
return NSS_STATUS_TRYAGAIN;
@@ -636,6 +643,7 @@ enum nss_status _nss_resolve_gethostbyaddr2_r(
return NSS_STATUS_SUCCESS;
fail:
+ UNPROTECT_ERRNO;
*errnop = -r;
*h_errnop = NO_RECOVERY;
return ret;
diff --git a/src/nss-systemd/nss-systemd.c b/src/nss-systemd/nss-systemd.c
index f554828d49..f8db27ae27 100644
--- a/src/nss-systemd/nss-systemd.c
+++ b/src/nss-systemd/nss-systemd.c
@@ -210,6 +210,7 @@ enum nss_status _nss_systemd_getpwnam_r(
l = strlen(name);
if (buflen < l+1) {
+ UNPROTECT_ERRNO;
*errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
@@ -227,6 +228,7 @@ enum nss_status _nss_systemd_getpwnam_r(
return NSS_STATUS_SUCCESS;
fail:
+ UNPROTECT_ERRNO;
*errnop = -r;
return NSS_STATUS_UNAVAIL;
}
@@ -310,6 +312,7 @@ enum nss_status _nss_systemd_getpwuid_r(
l = strlen(translated) + 1;
if (buflen < l) {
+ UNPROTECT_ERRNO;
*errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
@@ -327,6 +330,7 @@ enum nss_status _nss_systemd_getpwuid_r(
return NSS_STATUS_SUCCESS;
fail:
+ UNPROTECT_ERRNO;
*errnop = -r;
return NSS_STATUS_UNAVAIL;
}
@@ -408,6 +412,7 @@ enum nss_status _nss_systemd_getgrnam_r(
l = sizeof(char*) + strlen(name) + 1;
if (buflen < l) {
+ UNPROTECT_ERRNO;
*errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
@@ -423,6 +428,7 @@ enum nss_status _nss_systemd_getgrnam_r(
return NSS_STATUS_SUCCESS;
fail:
+ UNPROTECT_ERRNO;
*errnop = -r;
return NSS_STATUS_UNAVAIL;
}
@@ -506,6 +512,7 @@ enum nss_status _nss_systemd_getgrgid_r(
l = sizeof(char*) + strlen(translated) + 1;
if (buflen < l) {
+ UNPROTECT_ERRNO;
*errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
@@ -521,6 +528,7 @@ enum nss_status _nss_systemd_getgrgid_r(
return NSS_STATUS_SUCCESS;
fail:
+ UNPROTECT_ERRNO;
*errnop = -r;
return NSS_STATUS_UNAVAIL;
}
@@ -740,6 +748,7 @@ enum nss_status _nss_systemd_getpwent_r(struct passwd *result, char *buffer, siz
LIST_FOREACH(entries, p, getpwent_data.position) {
len = strlen(p->name) + 1;
if (buflen < len) {
+ UNPROTECT_ERRNO;
*errnop = ERANGE;
ret = NSS_STATUS_TRYAGAIN;
goto finalize;
@@ -791,6 +800,7 @@ enum nss_status _nss_systemd_getgrent_r(struct group *result, char *buffer, size
LIST_FOREACH(entries, p, getgrent_data.position) {
len = sizeof(char*) + strlen(p->name) + 1;
if (buflen < len) {
+ UNPROTECT_ERRNO;
*errnop = ERANGE;
ret = NSS_STATUS_TRYAGAIN;
goto finalize;
diff --git a/src/portable/portabled.c b/src/portable/portabled.c
index 63fc340469..49a359fd31 100644
--- a/src/portable/portabled.c
+++ b/src/portable/portabled.c
@@ -53,7 +53,7 @@ static Manager* manager_unref(Manager *m) {
bus_verify_polkit_async_registry_free(m->polkit_registry);
- sd_bus_unref(m->bus);
+ sd_bus_flush_close_unref(m->bus);
sd_event_unref(m->event);
return mfree(m);
diff --git a/src/resolve/resolved-dns-answer.h b/src/resolve/resolved-dns-answer.h
index 97514c3408..47fc80e2b0 100644
--- a/src/resolve/resolved-dns-answer.h
+++ b/src/resolve/resolved-dns-answer.h
@@ -15,11 +15,11 @@ typedef struct DnsAnswerItem DnsAnswerItem;
* Note that we usually encode the empty DnsAnswer object as a simple NULL. */
typedef enum DnsAnswerFlags {
- DNS_ANSWER_AUTHENTICATED = 1, /* Item has been authenticated */
- DNS_ANSWER_CACHEABLE = 2, /* Item is subject to caching */
- DNS_ANSWER_SHARED_OWNER = 4, /* For mDNS: RRset may be owner by multiple peers */
- DNS_ANSWER_CACHE_FLUSH = 8, /* For mDNS: sets cache-flush bit in the rrclass of response records */
- DNS_ANSWER_GOODBYE = 16, /* For mDNS: item is subject to disappear */
+ DNS_ANSWER_AUTHENTICATED = 1 << 0, /* Item has been authenticated */
+ DNS_ANSWER_CACHEABLE = 1 << 1, /* Item is subject to caching */
+ DNS_ANSWER_SHARED_OWNER = 1 << 2, /* For mDNS: RRset may be owner by multiple peers */
+ DNS_ANSWER_CACHE_FLUSH = 1 << 3, /* For mDNS: sets cache-flush bit in the rrclass of response records */
+ DNS_ANSWER_GOODBYE = 1 << 4, /* For mDNS: item is subject to disappear */
} DnsAnswerFlags;
struct DnsAnswerItem {
diff --git a/src/resolve/resolved-dns-dnssec.c b/src/resolve/resolved-dns-dnssec.c
index 335fd47780..14acc4e77d 100644
--- a/src/resolve/resolved-dns-dnssec.c
+++ b/src/resolve/resolved-dns-dnssec.c
@@ -402,7 +402,7 @@ static int dnssec_ecdsa_verify(
if (rrsig->rrsig.signature_size != key_size * 2)
return -EINVAL;
- q = alloca(key_size*2 + 1);
+ q = newa(uint8_t, key_size*2 + 1);
q[0] = 0x04; /* Prepend 0x04 to indicate an uncompressed key */
memcpy(q+1, dnskey->dnskey.key, key_size*2);
diff --git a/src/resolve/resolved-dns-query.c b/src/resolve/resolved-dns-query.c
index 7a4f97754b..535ef4e776 100644
--- a/src/resolve/resolved-dns-query.c
+++ b/src/resolve/resolved-dns-query.c
@@ -719,7 +719,7 @@ int dns_query_go(DnsQuery *q) {
match = dns_scope_good_domain(s, q->ifindex, q->flags, name);
if (match < 0) {
- log_debug("Couldn't check if '%s' matches agains scope, ignoring.", name);
+ log_debug("Couldn't check if '%s' matches against scope, ignoring.", name);
continue;
}
diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c
index 972e661d72..66dd2b1b5a 100644
--- a/src/resolve/resolved-dns-scope.c
+++ b/src/resolve/resolved-dns-scope.c
@@ -527,6 +527,7 @@ DnsScopeMatch dns_scope_good_domain(
switch (s->protocol) {
case DNS_PROTOCOL_DNS: {
+ bool has_search_domains = false;
int n_best = -1;
/* Never route things to scopes that lack DNS servers */
@@ -536,7 +537,11 @@ DnsScopeMatch dns_scope_good_domain(
/* Always honour search domains for routing queries, except if this scope lacks DNS servers. Note that
* we return DNS_SCOPE_YES here, rather than just DNS_SCOPE_MAYBE, which means other wildcard scopes
* won't be considered anymore. */
- LIST_FOREACH(domains, d, dns_scope_get_search_domains(s))
+ LIST_FOREACH(domains, d, dns_scope_get_search_domains(s)) {
+
+ if (!d->route_only && !dns_name_is_root(d->name))
+ has_search_domains = true;
+
if (dns_name_endswith(domain, d->name) > 0) {
int c;
@@ -547,6 +552,13 @@ DnsScopeMatch dns_scope_good_domain(
if (c > n_best)
n_best = c;
}
+ }
+
+ /* If there's a true search domain defined for this scope, and the query is single-label,
+ * then let's resolve things here, prefereably. Note that LLMNR considers itself
+ * authoritative for single-label names too, at the same preference, see below. */
+ if (has_search_domains && dns_name_is_single_label(domain))
+ return DNS_SCOPE_YES_BASE + 1;
/* Let's return the number of labels in the best matching result */
if (n_best >= 0) {
@@ -606,12 +618,16 @@ DnsScopeMatch dns_scope_good_domain(
if ((dns_name_is_single_label(domain) && /* only resolve single label names via LLMNR */
!is_gateway_hostname(domain) && /* don't resolve "gateway" with LLMNR, let nss-myhostname handle this */
manager_is_own_hostname(s->manager, domain) <= 0)) /* never resolve the local hostname via LLMNR */
- return DNS_SCOPE_YES_BASE + 1; /* Return +1, as we consider ourselves authoritative for
- * single-label names, i.e. one label. This is particular
- * relevant as it means a "." route on some other scope won't
- * pull all traffic away from us. (If people actually want to
- * pull traffic away from us they should turn off LLMNR on the
- * link) */
+ return DNS_SCOPE_YES_BASE + 1; /* Return +1, as we consider ourselves authoritative
+ * for single-label names, i.e. one label. This is
+ * particular relevant as it means a "." route on some
+ * other scope won't pull all traffic away from
+ * us. (If people actually want to pull traffic away
+ * from us they should turn off LLMNR on the
+ * link). Note that unicast DNS scopes with search
+ * domains also consider themselves authoritative for
+ * single-label domains, at the same preference (see
+ * above). */
return DNS_SCOPE_NO;
}
diff --git a/src/resolve/resolved-etc-hosts.c b/src/resolve/resolved-etc-hosts.c
index 01cde4acf7..ee21222e50 100644
--- a/src/resolve/resolved-etc-hosts.c
+++ b/src/resolve/resolved-etc-hosts.c
@@ -12,12 +12,12 @@
/* Recheck /etc/hosts at most once every 2s */
#define ETC_HOSTS_RECHECK_USEC (2*USEC_PER_SEC)
-static inline void etc_hosts_item_free(EtcHostsItem *item) {
+static void etc_hosts_item_free(EtcHostsItem *item) {
strv_free(item->names);
free(item);
}
-static inline void etc_hosts_item_by_name_free(EtcHostsItemByName *item) {
+static void etc_hosts_item_by_name_free(EtcHostsItemByName *item) {
free(item->name);
free(item->addresses);
free(item);
diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c
index b7dc09ae37..b3d35c8341 100644
--- a/src/resolve/resolved-manager.c
+++ b/src/resolve/resolved-manager.c
@@ -689,7 +689,7 @@ Manager *manager_free(Manager *m) {
manager_mdns_stop(m);
manager_dns_stub_stop(m);
- sd_bus_unref(m->bus);
+ sd_bus_flush_close_unref(m->bus);
sd_event_source_unref(m->sigusr1_event_source);
sd_event_source_unref(m->sigusr2_event_source);
diff --git a/src/resolve/resolved.c b/src/resolve/resolved.c
index f4efddf8e5..0845b2c1ae 100644
--- a/src/resolve/resolved.c
+++ b/src/resolve/resolved.c
@@ -81,9 +81,7 @@ static int run(int argc, char *argv[]) {
if (r < 0)
return log_error_errno(r, "Event loop failed: %m");
- (void) sd_event_get_exit_code(m->event, &r);
-
- return r;
+ return 0;
}
DEFINE_MAIN_FUNCTION(run);
diff --git a/src/shared/acl-util.c b/src/shared/acl-util.c
index 6f0657174c..9633514513 100644
--- a/src/shared/acl-util.c
+++ b/src/shared/acl-util.c
@@ -220,10 +220,10 @@ int parse_acl(const char *text, acl_t *acl_access, acl_t *acl_default, bool want
char *p;
p = STARTSWITH_SET(*entry, "default:", "d:");
- if (!p)
- p = *entry;
-
- r = strv_push(&d, p);
+ if (p)
+ r = strv_push(&d, p);
+ else
+ r = strv_push(&a, *entry);
if (r < 0)
return r;
}
diff --git a/src/shared/ask-password-api.c b/src/shared/ask-password-api.c
index 246e27a135..072bf72c56 100644
--- a/src/shared/ask-password-api.c
+++ b/src/shared/ask-password-api.c
@@ -156,7 +156,7 @@ static int add_to_keyring_and_log(const char *keyname, AskPasswordFlags flags, c
return 0;
}
-int ask_password_keyring(const char *keyname, AskPasswordFlags flags, char ***ret) {
+static int ask_password_keyring(const char *keyname, AskPasswordFlags flags, char ***ret) {
key_serial_t serial;
int r;
@@ -341,7 +341,7 @@ int ask_password_tty(
goto finish;
}
- if (notify >= 0 && pollfd[POLL_INOTIFY].revents != 0) {
+ if (notify >= 0 && pollfd[POLL_INOTIFY].revents != 0 && keyname) {
(void) flush_fd(notify);
r = ask_password_keyring(keyname, flags, ret);
diff --git a/src/shared/ask-password-api.h b/src/shared/ask-password-api.h
index 2d84ba6b04..15762b9cde 100644
--- a/src/shared/ask-password-api.h
+++ b/src/shared/ask-password-api.h
@@ -17,5 +17,4 @@ typedef enum AskPasswordFlags {
int ask_password_tty(int tty_fd, const char *message, const char *keyname, usec_t until, AskPasswordFlags flags, const char *flag_file, char ***ret);
int ask_password_agent(const char *message, const char *icon, const char *id, const char *keyname, usec_t until, AskPasswordFlags flag, char ***ret);
-int ask_password_keyring(const char *keyname, AskPasswordFlags flags, char ***ret);
int ask_password_auto(const char *message, const char *icon, const char *id, const char *keyname, usec_t until, AskPasswordFlags flag, char ***ret);
diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c
index dce8646f37..9a8051d063 100644
--- a/src/shared/bus-unit-util.c
+++ b/src/shared/bus-unit-util.c
@@ -118,7 +118,7 @@ DEFINE_BUS_APPEND_PARSE_PTR("u", uint32_t, mode_t, parse_mode);
DEFINE_BUS_APPEND_PARSE_PTR("u", uint32_t, unsigned, safe_atou);
DEFINE_BUS_APPEND_PARSE_PTR("x", int64_t, int64_t, safe_atoi64);
-static inline int bus_append_string(sd_bus_message *m, const char *field, const char *eq) {
+static int bus_append_string(sd_bus_message *m, const char *field, const char *eq) {
int r;
r = sd_bus_message_append(m, "(sv)", field, "s", eq);
diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c
index 976643e4ce..cbcf698e96 100644
--- a/src/shared/bus-util.c
+++ b/src/shared/bus-util.c
@@ -559,7 +559,7 @@ int bus_check_peercred(sd_bus *c) {
}
int bus_connect_system_systemd(sd_bus **_bus) {
- _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
+ _cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL;
int r;
assert(_bus);
@@ -592,7 +592,7 @@ int bus_connect_system_systemd(sd_bus **_bus) {
}
int bus_connect_user_systemd(sd_bus **_bus) {
- _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
+ _cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL;
_cleanup_free_ char *ee = NULL;
const char *e;
int r;
@@ -1279,7 +1279,7 @@ int bus_map_all_properties(
}
int bus_connect_transport(BusTransport transport, const char *host, bool user, sd_bus **ret) {
- _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
+ _cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL;
int r;
assert(transport >= 0);
@@ -1666,7 +1666,7 @@ int bus_track_add_name_many(sd_bus_track *t, char **l) {
}
int bus_open_system_watch_bind_with_description(sd_bus **ret, const char *description) {
- _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
+ _cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL;
const char *e;
int r;
diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c
index 8fe177990a..b80c147807 100644
--- a/src/shared/conf-parser.c
+++ b/src/shared/conf-parser.c
@@ -137,7 +137,7 @@ static int next_assignment(
/* Warn about unknown non-extension fields. */
if (!(flags & CONFIG_PARSE_RELAXED) && !startswith(lvalue, "X-"))
- log_syntax(unit, LOG_WARNING, filename, line, 0, "Unknown lvalue '%s' in section '%s'", lvalue, section);
+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Unknown lvalue '%s' in section '%s', ignoring", lvalue, section);
return 0;
}
@@ -321,7 +321,7 @@ int config_parse(const char *unit,
return r;
}
- if (strchr(COMMENTS, *buf))
+ if (strchr(COMMENTS, *skip_leading_chars(buf, WHITESPACE)))
continue;
l = buf;
diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c
index 3a46faf769..d340487025 100644
--- a/src/shared/dissect-image.c
+++ b/src/shared/dissect-image.c
@@ -1178,7 +1178,6 @@ int dissected_image_decrypt_interactively(
#if HAVE_LIBCRYPTSETUP
static int deferred_remove(DecryptedPartition *p) {
-
struct dm_ioctl dm = {
.version = {
DM_VERSION_MAJOR,
@@ -1199,6 +1198,9 @@ static int deferred_remove(DecryptedPartition *p) {
if (fd < 0)
return -errno;
+ if (strlen(p->name) > sizeof(dm.name))
+ return -ENAMETOOLONG;
+
strncpy(dm.name, p->name, sizeof(dm.name));
if (ioctl(fd, DM_DEV_REMOVE, &dm))
diff --git a/src/shared/efivars.c b/src/shared/efivars.c
index cb9e13c15f..26f905bfaa 100644
--- a/src/shared/efivars.c
+++ b/src/shared/efivars.c
@@ -40,11 +40,17 @@
#define END_ENTIRE_DEVICE_PATH_SUBTYPE 0xff
#define EFI_OS_INDICATIONS_BOOT_TO_FW_UI 0x0000000000000001
-struct boot_option {
- uint32_t attr;
- uint16_t path_len;
- uint16_t title[];
-} _packed_;
+#define boot_option__contents { \
+ uint32_t attr; \
+ uint16_t path_len; \
+ uint16_t title[]; \
+ }
+
+struct boot_option boot_option__contents;
+struct boot_option__packed boot_option__contents _packed_;
+assert_cc(offsetof(struct boot_option, title) == offsetof(struct boot_option__packed, title));
+/* sizeof(struct boot_option) != sizeof(struct boot_option__packed), so
+ * the *size* of the structure should not be used anywhere below. */
struct drive_path {
uint32_t part_nr;
@@ -55,15 +61,19 @@ struct drive_path {
uint8_t signature_type;
} _packed_;
-struct device_path {
- uint8_t type;
- uint8_t sub_type;
- uint16_t length;
- union {
- uint16_t path[0];
- struct drive_path drive;
- };
-} _packed_;
+#define device_path__contents { \
+ uint8_t type; \
+ uint8_t sub_type; \
+ uint16_t length; \
+ union { \
+ uint16_t path[0]; \
+ struct drive_path drive; \
+ }; \
+ }
+
+struct device_path device_path__contents;
+struct device_path__packed device_path__contents _packed_;
+assert_cc(sizeof(struct device_path) == sizeof(struct device_path__packed));
bool is_efi_boot(void) {
if (detect_container() > 0)
@@ -354,32 +364,46 @@ int efi_set_variable_string(sd_id128_t vendor, const char *name, const char *v)
return efi_set_variable(vendor, name, u16, (char16_strlen(u16) + 1) * sizeof(char16_t));
}
-static size_t utf16_size(const uint16_t *s) {
+static ssize_t utf16_size(const uint16_t *s, size_t buf_len_bytes) {
size_t l = 0;
- while (s[l] > 0)
+ /* Returns the size of the string in bytes without the terminating two zero bytes */
+
+ if (buf_len_bytes % sizeof(uint16_t) != 0)
+ return -EINVAL;
+
+ while (l < buf_len_bytes / sizeof(uint16_t)) {
+ if (s[l] == 0)
+ return (l + 1) * sizeof(uint16_t);
l++;
+ }
- return (l+1) * sizeof(uint16_t);
+ return -EINVAL; /* The terminator was not found */
}
+struct guid {
+ uint32_t u1;
+ uint16_t u2;
+ uint16_t u3;
+ uint8_t u4[8];
+} _packed_;
+
static void efi_guid_to_id128(const void *guid, sd_id128_t *id128) {
- struct uuid {
- uint32_t u1;
- uint16_t u2;
- uint16_t u3;
- uint8_t u4[8];
- } _packed_;
- const struct uuid *uuid = guid;
-
- id128->bytes[0] = (uuid->u1 >> 24) & 0xff;
- id128->bytes[1] = (uuid->u1 >> 16) & 0xff;
- id128->bytes[2] = (uuid->u1 >> 8) & 0xff;
- id128->bytes[3] = (uuid->u1) & 0xff;
- id128->bytes[4] = (uuid->u2 >> 8) & 0xff;
- id128->bytes[5] = (uuid->u2) & 0xff;
- id128->bytes[6] = (uuid->u3 >> 8) & 0xff;
- id128->bytes[7] = (uuid->u3) & 0xff;
+ uint32_t u1;
+ uint16_t u2, u3;
+ const struct guid *uuid = guid;
+
+ memcpy(&u1, &uuid->u1, sizeof(uint32_t));
+ id128->bytes[0] = (u1 >> 24) & 0xff;
+ id128->bytes[1] = (u1 >> 16) & 0xff;
+ id128->bytes[2] = (u1 >> 8) & 0xff;
+ id128->bytes[3] = u1 & 0xff;
+ memcpy(&u2, &uuid->u2, sizeof(uint16_t));
+ id128->bytes[4] = (u2 >> 8) & 0xff;
+ id128->bytes[5] = u2 & 0xff;
+ memcpy(&u3, &uuid->u3, sizeof(uint16_t));
+ id128->bytes[6] = (u3 >> 8) & 0xff;
+ id128->bytes[7] = u3 & 0xff;
memcpy(&id128->bytes[8], uuid->u4, sizeof(uuid->u4));
}
@@ -394,7 +418,7 @@ int efi_get_boot_option(
_cleanup_free_ uint8_t *buf = NULL;
size_t l;
struct boot_option *header;
- size_t title_size;
+ ssize_t title_size;
_cleanup_free_ char *s = NULL, *p = NULL;
sd_id128_t p_uuid = SD_ID128_NULL;
int r;
@@ -406,13 +430,13 @@ int efi_get_boot_option(
r = efi_get_variable(EFI_VENDOR_GLOBAL, boot_id, NULL, (void **)&buf, &l);
if (r < 0)
return r;
- if (l < sizeof(struct boot_option))
+ if (l < offsetof(struct boot_option, title))
return -ENOENT;
header = (struct boot_option *)buf;
- title_size = utf16_size(header->title);
- if (title_size > l - offsetof(struct boot_option, title))
- return -EINVAL;
+ title_size = utf16_size(header->title, l - offsetof(struct boot_option, title));
+ if (title_size < 0)
+ return title_size;
if (title) {
s = utf16_to_utf8(header->title, title_size);
@@ -494,20 +518,14 @@ static void to_utf16(uint16_t *dest, const char *src) {
dest[i] = '\0';
}
-struct guid {
- uint32_t u1;
- uint16_t u2;
- uint16_t u3;
- uint8_t u4[8];
-} _packed_;
-
static void id128_to_efi_guid(sd_id128_t id, void *guid) {
- struct guid *uuid = guid;
-
- uuid->u1 = id.bytes[0] << 24 | id.bytes[1] << 16 | id.bytes[2] << 8 | id.bytes[3];
- uuid->u2 = id.bytes[4] << 8 | id.bytes[5];
- uuid->u3 = id.bytes[6] << 8 | id.bytes[7];
- memcpy(uuid->u4, id.bytes+8, sizeof(uuid->u4));
+ struct guid uuid = {
+ .u1 = id.bytes[0] << 24 | id.bytes[1] << 16 | id.bytes[2] << 8 | id.bytes[3],
+ .u2 = id.bytes[4] << 8 | id.bytes[5],
+ .u3 = id.bytes[6] << 8 | id.bytes[7],
+ };
+ memcpy(uuid.u4, id.bytes+8, sizeof(uuid.u4));
+ memcpy(guid, &uuid, sizeof(uuid));
}
static uint16_t *tilt_slashes(uint16_t *s) {
@@ -541,7 +559,7 @@ int efi_add_boot_option(
title_len = (strlen(title)+1) * 2;
path_len = (strlen(path)+1) * 2;
- buf = malloc0(sizeof(struct boot_option) + title_len +
+ buf = malloc0(offsetof(struct boot_option, title) + title_len +
sizeof(struct drive_path) +
sizeof(struct device_path) + path_len);
if (!buf)
@@ -561,12 +579,12 @@ int efi_add_boot_option(
devicep->type = MEDIA_DEVICE_PATH;
devicep->sub_type = MEDIA_HARDDRIVE_DP;
devicep->length = offsetof(struct device_path, drive) + sizeof(struct drive_path);
- devicep->drive.part_nr = part;
- devicep->drive.part_start = pstart;
- devicep->drive.part_size = psize;
- devicep->drive.signature_type = SIGNATURE_TYPE_GUID;
- devicep->drive.mbr_type = MBR_TYPE_EFI_PARTITION_TABLE_HEADER;
+ memcpy(&devicep->drive.part_nr, &part, sizeof(uint32_t));
+ memcpy(&devicep->drive.part_start, &pstart, sizeof(uint64_t));
+ memcpy(&devicep->drive.part_size, &psize, sizeof(uint64_t));
id128_to_efi_guid(part_uuid, devicep->drive.signature);
+ devicep->drive.mbr_type = MBR_TYPE_EFI_PARTITION_TABLE_HEADER;
+ devicep->drive.signature_type = SIGNATURE_TYPE_GUID;
size += devicep->length;
/* path to loader */
@@ -630,7 +648,7 @@ int efi_set_boot_order(uint16_t *order, size_t n) {
return efi_set_variable(EFI_VENDOR_GLOBAL, "BootOrder", order, n * sizeof(uint16_t));
}
-static int boot_id_hex(const char s[4]) {
+static int boot_id_hex(const char s[static 4]) {
int id = 0, i;
for (i = 0; i < 4; i++)
diff --git a/src/shared/install.c b/src/shared/install.c
index 3104043af6..8629304cef 100644
--- a/src/shared/install.c
+++ b/src/shared/install.c
@@ -68,7 +68,7 @@ typedef struct {
size_t n_rules;
} Presets;
-static inline bool unit_file_install_info_has_rules(const UnitFileInstallInfo *i) {
+static bool unit_file_install_info_has_rules(const UnitFileInstallInfo *i) {
assert(i);
return !strv_isempty(i->aliases) ||
@@ -76,13 +76,13 @@ static inline bool unit_file_install_info_has_rules(const UnitFileInstallInfo *i
!strv_isempty(i->required_by);
}
-static inline bool unit_file_install_info_has_also(const UnitFileInstallInfo *i) {
+static bool unit_file_install_info_has_also(const UnitFileInstallInfo *i) {
assert(i);
return !strv_isempty(i->also);
}
-static inline void presets_freep(Presets *p) {
+static void presets_freep(Presets *p) {
size_t i;
if (!p)
diff --git a/src/shared/journal-importer.c b/src/shared/journal-importer.c
index b0e619205d..8638cd3cc9 100644
--- a/src/shared/journal-importer.c
+++ b/src/shared/journal-importer.c
@@ -23,6 +23,9 @@ enum {
};
static int iovw_put(struct iovec_wrapper *iovw, void* data, size_t len) {
+ if (iovw->count >= ENTRY_FIELD_COUNT_MAX)
+ return -E2BIG;
+
if (!GREEDY_REALLOC(iovw->iovec, iovw->size_bytes, iovw->count + 1))
return log_oom();
@@ -97,7 +100,7 @@ static int get_line(JournalImporter *imp, char **line, size_t *size) {
imp->scanned = imp->filled;
if (imp->scanned >= DATA_SIZE_MAX)
- return log_error_errno(SYNTHETIC_ERRNO(E2BIG),
+ return log_error_errno(SYNTHETIC_ERRNO(ENOBUFS),
"Entry is bigger than %u bytes.",
DATA_SIZE_MAX);
diff --git a/src/shared/journal-importer.h b/src/shared/journal-importer.h
index 53354b7c78..7914c0cf5f 100644
--- a/src/shared/journal-importer.h
+++ b/src/shared/journal-importer.h
@@ -21,6 +21,9 @@
#endif
#define LINE_CHUNK 8*1024u
+/* The maximum number of fields in an entry */
+#define ENTRY_FIELD_COUNT_MAX 1024
+
struct iovec_wrapper {
struct iovec *iovec;
size_t size_bytes;
diff --git a/src/shared/json.c b/src/shared/json.c
index 59c4617592..3786ff12b8 100644
--- a/src/shared/json.c
+++ b/src/shared/json.c
@@ -979,6 +979,8 @@ bool json_variant_has_type(JsonVariant *v, JsonVariantType type) {
JsonVariantType rt;
v = json_variant_dereference(v);
+ if (!v)
+ return false;
rt = json_variant_type(v);
if (rt == type)
@@ -3140,10 +3142,7 @@ int json_log_internal(
va_list ap;
int r;
- if (error < 0)
- error = -error;
-
- errno = error;
+ errno = ERRNO_VALUE(error);
va_start(ap, format);
(void) vsnprintf(buffer, sizeof buffer, format, ap);
diff --git a/src/shared/json.h b/src/shared/json.h
index 4eba91c272..f8e035cda1 100644
--- a/src/shared/json.h
+++ b/src/shared/json.h
@@ -1,5 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-
#pragma once
#include <stdbool.h>
@@ -154,7 +153,7 @@ typedef enum JsonFormatFlags {
JSON_FORMAT_NEWLINE = 1 << 0, /* suffix with newline */
JSON_FORMAT_PRETTY = 1 << 1, /* add internal whitespace to appeal to human readers */
JSON_FORMAT_COLOR = 1 << 2, /* insert ANSI color sequences */
- JSON_FORMAT_COLOR_AUTO = 1 << 3, /* insetr ANSI color sequences if colors_enabled() says so */
+ JSON_FORMAT_COLOR_AUTO = 1 << 3, /* insert ANSI color sequences if colors_enabled() says so */
JSON_FORMAT_SOURCE = 1 << 4, /* prefix with source filename/line/column */
JSON_FORMAT_SSE = 1 << 5, /* prefix/suffix with W3C server-sent events */
JSON_FORMAT_SEQ = 1 << 6, /* prefix/suffix with RFC 7464 application/json-seq */
diff --git a/src/shared/lockfile-util.c b/src/shared/lockfile-util.c
index 4bae23b243..260c2088d5 100644
--- a/src/shared/lockfile-util.c
+++ b/src/shared/lockfile-util.c
@@ -12,6 +12,7 @@
#include "fs-util.h"
#include "lockfile-util.h"
#include "macro.h"
+#include "missing_fcntl.h"
#include "path-util.h"
int make_lock_file(const char *p, int operation, LockFile *ret) {
diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c
index 525a948f36..15ef0f19ff 100644
--- a/src/shared/logs-show.c
+++ b/src/shared/logs-show.c
@@ -724,7 +724,7 @@ void json_escape(
fputs(" ]", f);
} else {
- fputc('\"', f);
+ fputc('"', f);
while (l > 0) {
if (IN_SET(*p, '"', '\\')) {
@@ -741,7 +741,7 @@ void json_escape(
l--;
}
- fputc('\"', f);
+ fputc('"', f);
}
}
diff --git a/src/shared/loop-util.c b/src/shared/loop-util.c
index 872c25c3dc..bf426eb8bc 100644
--- a/src/shared/loop-util.c
+++ b/src/shared/loop-util.c
@@ -45,11 +45,11 @@ int loop_device_make(int fd, int open_flags, LoopDevice **ret) {
*d = (LoopDevice) {
.fd = copy,
.nr = -1,
+ .relinquished = true, /* It's not allocated by us, don't destroy it when this object is freed */
};
*ret = d;
-
- return 0;
+ return d->fd;
}
r = stat_verify_regular(&st);
@@ -88,8 +88,7 @@ int loop_device_make(int fd, int open_flags, LoopDevice **ret) {
};
*ret = d;
-
- return (*ret)->fd;
+ return d->fd;
}
int loop_device_make_by_path(const char *path, int open_flags, LoopDevice **ret) {
diff --git a/src/shared/pager.c b/src/shared/pager.c
index ce4ca9bdb2..bf2597e65a 100644
--- a/src/shared/pager.c
+++ b/src/shared/pager.c
@@ -173,7 +173,7 @@ int pager_open(PagerFlags flags) {
execvp(pager_args[0], pager_args);
log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, errno,
- "Failed execute %s, using fallback pagers: %m", pager_args[0]);
+ "Failed to execute '%s', using fallback pagers: %m", pager_args[0]);
}
/* Debian's alternatives command for pagers is
@@ -190,7 +190,7 @@ int pager_open(PagerFlags flags) {
}
execlp(exe, exe, NULL);
log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, errno,
- "Failed execute %s, using next fallback pager: %m", exe);
+ "Failed to execute '%s', using next fallback pager: %m", exe);
}
r = loop_write(exe_name_pipe[1], "(built-in)", strlen("(built-in") + 1, false);
diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c
index 42d6dd2a94..cc58b3c078 100644
--- a/src/shared/seccomp-util.c
+++ b/src/shared/seccomp-util.c
@@ -793,7 +793,6 @@ const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = {
"ioprio_get\0"
"kcmp\0"
"madvise\0"
- "mincore\0"
"mprotect\0"
"mremap\0"
"name_to_handle_at\0"
diff --git a/src/shared/switch-root.c b/src/shared/switch-root.c
index ee31c448fc..dbb4622312 100644
--- a/src/shared/switch-root.c
+++ b/src/shared/switch-root.c
@@ -83,7 +83,7 @@ int switch_root(const char *new_root,
(void) mkdir_p_label(chased, 0755);
if (mount(i, chased, NULL, mount_flags, NULL) < 0)
- return log_error_errno(r, "Failed to mount %s to %s: %m", i, chased);
+ return log_error_errno(errno, "Failed to mount %s to %s: %m", i, chased);
}
/* Do not fail if base_filesystem_create() fails. Not all switch roots are like base_filesystem_create() wants
diff --git a/src/shared/xml.c b/src/shared/xml.c
index cb34d870c1..2709076264 100644
--- a/src/shared/xml.c
+++ b/src/shared/xml.c
@@ -191,7 +191,7 @@ int xml_tokenize(const char **p, char **name, void **state, unsigned *line) {
if (*c == '=') {
c++;
- if (IN_SET(*c, '\'', '\"')) {
+ if (IN_SET(*c, '\'', '"')) {
/* Tag with a quoted value */
e = strchr(c+1, *c);
diff --git a/src/sleep/sleep.conf b/src/sleep/sleep.conf
new file mode 100644
index 0000000000..dc2ed37f70
--- /dev/null
+++ b/src/sleep/sleep.conf
@@ -0,0 +1,25 @@
+# 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.
+#
+# Entries in this file show the compile time defaults.
+# You can change settings by editing this file.
+# Defaults can be restored by simply deleting this file.
+#
+# See systemd-sleep.conf(5) for details
+
+[Sleep]
+#AllowSuspend=yes
+#AllowHibernation=yes
+#AllowSuspendThenHibernate=yes
+#AllowHybridSleep=yes
+#SuspendMode=
+#SuspendState=mem standby freeze
+#HibernateMode=platform shutdown
+#HibernateState=disk
+#HybridSleepMode=suspend platform shutdown
+#HybridSleepState=disk
+#HibernateDelaySec=180min
diff --git a/src/socket-proxy/socket-proxyd.c b/src/socket-proxy/socket-proxyd.c
index f882a665a8..bac5c164d4 100644
--- a/src/socket-proxy/socket-proxyd.c
+++ b/src/socket-proxy/socket-proxyd.c
@@ -86,7 +86,7 @@ static void context_clear(Context *context) {
sd_resolve_unref(context->resolve);
}
-static int connection_create_pipes(Connection *c, int buffer[2], size_t *sz) {
+static int connection_create_pipes(Connection *c, int buffer[static 2], size_t *sz) {
int r;
assert(c);
diff --git a/src/stdio-bridge/stdio-bridge.c b/src/stdio-bridge/stdio-bridge.c
index 3a21aa4aed..7060897ab7 100644
--- a/src/stdio-bridge/stdio-bridge.c
+++ b/src/stdio-bridge/stdio-bridge.c
@@ -91,7 +91,7 @@ static int parse_argv(int argc, char *argv[]) {
}
static int run(int argc, char *argv[]) {
- _cleanup_(sd_bus_unrefp) sd_bus *a = NULL, *b = NULL;
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *a = NULL, *b = NULL;
sd_id128_t server_id;
bool is_unix;
int r, in_fd, out_fd;
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 629f9cb505..63dae2c872 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -6933,9 +6933,9 @@ static int run_editor(char **paths) {
if (r < 0)
return r;
if (r == 0) {
- char **editor_args = NULL, **tmp_path, **original_path, *p;
+ char **editor_args = NULL, **tmp_path, **original_path;
size_t n_editor_args = 0, i = 1, argc;
- const char **args, *editor;
+ const char **args, *editor, *p;
argc = strv_length(paths)/2 + 1;
diff --git a/src/systemd/_sd-common.h b/src/systemd/_sd-common.h
index 05c38008cf..b3ee7bbc24 100644
--- a/src/systemd/_sd-common.h
+++ b/src/systemd/_sd-common.h
@@ -72,6 +72,14 @@ typedef void (*_sd_destroy_t)(void *userdata);
# endif
#endif
+#ifndef _SD_ARRAY_STATIC
+# if __STDC_VERSION__ >= 199901L
+# define _SD_ARRAY_STATIC static
+# else
+# define _SD_ARRAY_STATIC
+# endif
+#endif
+
#define _SD_DEFINE_POINTER_CLEANUP_FUNC(type, func) \
static __inline__ void func##p(type **p) { \
if (*p) \
diff --git a/src/systemd/meson.build b/src/systemd/meson.build
index e0c967efc5..75c48b07a5 100644
--- a/src/systemd/meson.build
+++ b/src/systemd/meson.build
@@ -52,8 +52,7 @@ if cc.has_argument('-std=iso9899:2017')
opts += [['c', '-std=iso9899:2017']]
endif
-cxx = find_program('c++', required : false)
-if cxx.found()
+if add_languages('cpp', required : false)
opts += [['c++'],
['c++', '-std=c++98'],
['c++', '-std=c++11']]
diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h
index 4c1acab9f3..129cc93328 100644
--- a/src/systemd/sd-bus.h
+++ b/src/systemd/sd-bus.h
@@ -170,6 +170,7 @@ void sd_bus_close(sd_bus *bus);
sd_bus *sd_bus_ref(sd_bus *bus);
sd_bus *sd_bus_unref(sd_bus *bus);
+sd_bus *sd_bus_close_unref(sd_bus *bus);
sd_bus *sd_bus_flush_close_unref(sd_bus *bus);
void sd_bus_default_flush_close(void);
@@ -493,6 +494,7 @@ int sd_bus_track_get_destroy_callback(sd_bus_track *s, sd_bus_destroy_t *ret);
/* Define helpers so that __attribute__((cleanup(sd_bus_unrefp))) and similar may be used. */
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_bus, sd_bus_unref);
+_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_bus, sd_bus_close_unref);
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_bus, sd_bus_flush_close_unref);
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_bus_slot, sd_bus_slot_unref);
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_bus_message, sd_bus_message_unref);
diff --git a/src/systemd/sd-id128.h b/src/systemd/sd-id128.h
index f4c05a3683..bdf88ed53f 100644
--- a/src/systemd/sd-id128.h
+++ b/src/systemd/sd-id128.h
@@ -35,7 +35,7 @@ union sd_id128 {
#define SD_ID128_STRING_MAX 33
-char *sd_id128_to_string(sd_id128_t id, char s[SD_ID128_STRING_MAX]);
+char *sd_id128_to_string(sd_id128_t id, char s[_SD_ARRAY_STATIC SD_ID128_STRING_MAX]);
int sd_id128_from_string(const char *s, sd_id128_t *ret);
int sd_id128_randomize(sd_id128_t *ret);
diff --git a/src/systemd/sd-lldp.h b/src/systemd/sd-lldp.h
index a3e5cd6be6..bf3afadcec 100644
--- a/src/systemd/sd-lldp.h
+++ b/src/systemd/sd-lldp.h
@@ -27,7 +27,7 @@
_SD_BEGIN_DECLARATIONS;
-/* IEEE 802.3AB Clause 9: TLV Types */
+/* IEEE 802.1AB-2009 Clause 8: TLV Types */
enum {
SD_LLDP_TYPE_END = 0,
SD_LLDP_TYPE_CHASSIS_ID = 1,
@@ -41,7 +41,7 @@ enum {
SD_LLDP_TYPE_PRIVATE = 127,
};
-/* IEEE 802.3AB Clause 9.5.2: Chassis subtypes */
+/* IEEE 802.1AB-2009 Clause 8.5.2: Chassis subtypes */
enum {
SD_LLDP_CHASSIS_SUBTYPE_RESERVED = 0,
SD_LLDP_CHASSIS_SUBTYPE_CHASSIS_COMPONENT = 1,
@@ -53,7 +53,7 @@ enum {
SD_LLDP_CHASSIS_SUBTYPE_LOCALLY_ASSIGNED = 7,
};
-/* IEEE 802.3AB Clause 9.5.3: Port subtype */
+/* IEEE 802.1AB-2009 Clause 8.5.3: Port subtype */
enum {
SD_LLDP_PORT_SUBTYPE_RESERVED = 0,
SD_LLDP_PORT_SUBTYPE_INTERFACE_ALIAS = 1,
@@ -65,6 +65,7 @@ enum {
SD_LLDP_PORT_SUBTYPE_LOCALLY_ASSIGNED = 7,
};
+/* IEEE 802.1AB-2009 Clause 8.5.8: System capabilities */
enum {
SD_LLDP_SYSTEM_CAPABILITIES_OTHER = 1 << 0,
SD_LLDP_SYSTEM_CAPABILITIES_REPEATER = 1 << 1,
@@ -95,6 +96,7 @@ enum {
#define SD_LLDP_OUI_802_1 (uint8_t[]) { 0x00, 0x80, 0xc2 }
#define SD_LLDP_OUI_802_3 (uint8_t[]) { 0x00, 0x12, 0x0f }
+/* IEEE 802.1AB-2009 Annex E */
enum {
SD_LLDP_OUI_802_1_SUBTYPE_PORT_VLAN_ID = 1,
SD_LLDP_OUI_802_1_SUBTYPE_PORT_PROTOCOL_VLAN_ID = 2,
@@ -105,6 +107,14 @@ enum {
SD_LLDP_OUI_802_1_SUBTYPE_LINK_AGGREGATION = 7,
};
+/* IEEE 802.1AB-2009 Annex F */
+enum {
+ SD_LLDP_OUI_802_3_SUBTYPE_MAC_PHY_CONFIG_STATUS = 1,
+ SD_LLDP_OUI_802_3_SUBTYPE_POWER_VIA_MDI = 2,
+ SD_LLDP_OUI_802_3_SUBTYPE_LINK_AGGREGATION = 3,
+ SD_LLDP_OUI_802_3_SUBTYPE_MAXIMUM_FRAME_SIZE = 4,
+};
+
typedef struct sd_lldp sd_lldp;
typedef struct sd_lldp_neighbor sd_lldp_neighbor;
@@ -168,8 +178,8 @@ int sd_lldp_neighbor_tlv_rewind(sd_lldp_neighbor *n);
int sd_lldp_neighbor_tlv_next(sd_lldp_neighbor *n);
int sd_lldp_neighbor_tlv_get_type(sd_lldp_neighbor *n, uint8_t *type);
int sd_lldp_neighbor_tlv_is_type(sd_lldp_neighbor *n, uint8_t type);
-int sd_lldp_neighbor_tlv_get_oui(sd_lldp_neighbor *n, uint8_t oui[3], uint8_t *subtype);
-int sd_lldp_neighbor_tlv_is_oui(sd_lldp_neighbor *n, const uint8_t oui[3], uint8_t subtype);
+int sd_lldp_neighbor_tlv_get_oui(sd_lldp_neighbor *n, uint8_t oui[_SD_ARRAY_STATIC 3], uint8_t *subtype);
+int sd_lldp_neighbor_tlv_is_oui(sd_lldp_neighbor *n, const uint8_t oui[_SD_ARRAY_STATIC 3], uint8_t subtype);
int sd_lldp_neighbor_tlv_get_raw(sd_lldp_neighbor *n, const void **ret, size_t *size);
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_lldp, sd_lldp_unref);
diff --git a/src/systemd/sd-netlink.h b/src/systemd/sd-netlink.h
index 30be5b113c..9e6e437bab 100644
--- a/src/systemd/sd-netlink.h
+++ b/src/systemd/sd-netlink.h
@@ -78,6 +78,8 @@ int sd_netlink_message_append_u32(sd_netlink_message *m, unsigned short type, ui
int sd_netlink_message_append_data(sd_netlink_message *m, unsigned short type, const void *data, size_t len);
int sd_netlink_message_append_in_addr(sd_netlink_message *m, unsigned short type, const struct in_addr *data);
int sd_netlink_message_append_in6_addr(sd_netlink_message *m, unsigned short type, const struct in6_addr *data);
+int sd_netlink_message_append_sockaddr_in(sd_netlink_message *m, unsigned short type, const struct sockaddr_in *data);
+int sd_netlink_message_append_sockaddr_in6(sd_netlink_message *m, unsigned short type, const struct sockaddr_in6 *data);
int sd_netlink_message_append_ether_addr(sd_netlink_message *m, unsigned short type, const struct ether_addr *data);
int sd_netlink_message_append_cache_info(sd_netlink_message *m, unsigned short type, const struct ifa_cacheinfo *info);
@@ -200,7 +202,6 @@ int sd_netlink_slot_set_floating(sd_netlink_slot *slot, int b);
int sd_netlink_slot_get_description(sd_netlink_slot *slot, const char **description);
int sd_netlink_slot_set_description(sd_netlink_slot *slot, const char *description);
-
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_netlink, sd_netlink_unref);
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_netlink_message, sd_netlink_message_unref);
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_netlink_slot, sd_netlink_slot_unref);
diff --git a/src/test/meson.build b/src/test/meson.build
index ea049a6fba..08026ea8c4 100644
--- a/src/test/meson.build
+++ b/src/test/meson.build
@@ -929,7 +929,8 @@ tests += [
[['src/libsystemd/sd-resolve/test-resolve.c'],
[],
- [threads]],
+ [threads],
+ '', 'timeout=120'],
[['src/libsystemd/sd-login/test-login.c'],
[],
@@ -957,7 +958,7 @@ tests += [
]
-if cxx.found()
+if cxx_cmd != ''
tests += [
[['src/libsystemd/sd-bus/test-bus-vtable-cc.cc'],
[],
diff --git a/src/test/test-barrier.c b/src/test/test-barrier.c
index 6ae84cd6fc..6469129fa4 100644
--- a/src/test/test-barrier.c
+++ b/src/test/test-barrier.c
@@ -17,6 +17,7 @@
#include "barrier.h"
#include "util.h"
#include "tests.h"
+#include "virt.h"
/* 20ms to test deadlocks; All timings use multiples of this constant as
* alarm/sleep timers. If this timeout is too small for slow machines to perform
@@ -420,11 +421,27 @@ TEST_BARRIER(test_barrier_pending_exit,
TEST_BARRIER_WAIT_SUCCESS(pid2));
int main(int argc, char *argv[]) {
+ int v;
test_setup_logging(LOG_INFO);
if (!slow_tests_enabled())
return log_tests_skipped("slow tests are disabled");
+ /*
+ * This test uses real-time alarms and sleeps to test for CPU races
+ * explicitly. This is highly fragile if your system is under load. We
+ * already increased the BASE_TIME value to make the tests more robust,
+ * but that just makes the test take significantly longer. Given the recent
+ * issues when running the test in a virtualized environments, limit it
+ * to bare metal machines only, to minimize false-positives in CIs.
+ */
+ v = detect_virtualization();
+ if (IN_SET(v, -EPERM, -EACCES))
+ return log_tests_skipped("Cannot detect virtualization");
+
+ if (v != VIRTUALIZATION_NONE)
+ return log_tests_skipped("This test requires a baremetal machine");
+
test_barrier_sync();
test_barrier_wait_next();
test_barrier_wait_next_twice();
diff --git a/src/test/test-bpf.c b/src/test/test-bpf.c
index ea5f0f5bc6..cd8d68f215 100644
--- a/src/test/test-bpf.c
+++ b/src/test/test-bpf.c
@@ -2,6 +2,7 @@
#include <linux/libbpf.h>
#include <string.h>
+#include <sys/mman.h>
#include <unistd.h>
#include "bpf-firewall.h"
@@ -14,6 +15,30 @@
#include "tests.h"
#include "unit.h"
+/* We use the same limit here that PID 1 bumps RLIMIT_MEMLOCK to if it can */
+#define CAN_MEMLOCK_SIZE (64U*1024U*1024U)
+
+static bool can_memlock(void) {
+ void *p;
+ bool b;
+
+ /* Let's see if we can mlock() a larger blob of memory. BPF programs are charged against
+ * RLIMIT_MEMLOCK, hence let's first make sure we can lock memory at all, and skip the test if we
+ * cannot. Why not check RLIMIT_MEMLOCK explicitly? Because in container environments the
+ * RLIMIT_MEMLOCK value we see might not match the RLIMIT_MEMLOCK value actually in effect. */
+
+ p = mmap(NULL, CAN_MEMLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_SHARED, -1, 0);
+ if (p == MAP_FAILED)
+ return false;
+
+ b = mlock(p, CAN_MEMLOCK_SIZE) >= 0;
+ if (b)
+ assert_se(munlock(p, CAN_MEMLOCK_SIZE) >= 0);
+
+ assert_se(munmap(p, CAN_MEMLOCK_SIZE) >= 0);
+ return b;
+}
+
int main(int argc, char *argv[]) {
struct bpf_insn exit_insn[] = {
BPF_MOV64_IMM(BPF_REG_0, 1),
@@ -26,10 +51,21 @@ int main(int argc, char *argv[]) {
_cleanup_(manager_freep) Manager *m = NULL;
Unit *u;
char log_buf[65535];
+ struct rlimit rl;
int r;
test_setup_logging(LOG_DEBUG);
+ if (is_run_on_travis_ci())
+ return log_tests_skipped("test-bpf fails on Travis CI: https://github.com/systemd/systemd/issues/9666");
+
+ assert_se(getrlimit(RLIMIT_MEMLOCK, &rl) >= 0);
+ rl.rlim_cur = rl.rlim_max = MAX3(rl.rlim_cur, rl.rlim_max, CAN_MEMLOCK_SIZE);
+ (void) setrlimit(RLIMIT_MEMLOCK, &rl);
+
+ if (!can_memlock())
+ return log_tests_skipped("Can't use mlock(), skipping.");
+
r = enter_cgroup_subroot();
if (r == -ENOMEDIUM)
return log_tests_skipped("cgroupfs not available");
diff --git a/src/test/test-capability.c b/src/test/test-capability.c
index dae85f2f91..325d7c8cc2 100644
--- a/src/test/test-capability.c
+++ b/src/test/test-capability.c
@@ -13,6 +13,7 @@
#include "fd-util.h"
#include "fileio.h"
#include "macro.h"
+#include "missing_prctl.h"
#include "parse-util.h"
#include "tests.h"
#include "util.h"
diff --git a/src/test/test-conf-parser.c b/src/test/test-conf-parser.c
index 2921338f62..1738938fce 100644
--- a/src/test/test-conf-parser.c
+++ b/src/test/test-conf-parser.c
@@ -248,6 +248,18 @@ static const char* const config_file[] = {
"3\n",
"[Section]\n"
+ " #hogehoge\\\n" /* whitespaces before comments */
+ " setting1=1\\\n" /* whitespaces before key */
+ "2\\\n"
+ "3\n",
+
+ "[Section]\n"
+ " setting1=1\\\n" /* whitespaces before key */
+ " #hogehoge\\\n" /* commented out line prefixed with whitespaces in continuation */
+ "2\\\n"
+ "3\n",
+
+ "[Section]\n"
"setting1=1\\\n" /* continuation with extra trailing backslash at the end */
"2\\\n"
"3\\\n",
@@ -323,27 +335,27 @@ static void test_config_parse(unsigned i, const char *s) {
assert_se(streq(setting1, "1"));
break;
- case 4 ... 7:
+ case 4 ... 9:
assert_se(r == 0);
assert_se(streq(setting1, "1 2 3"));
break;
- case 8:
+ case 10:
assert_se(r == 0);
assert_se(streq(setting1, "1\\\\ \\\\2"));
break;
- case 9:
+ case 11:
assert_se(r == 0);
assert_se(streq(setting1, x1000("ABCD")));
break;
- case 10 ... 11:
+ case 12 ... 13:
assert_se(r == 0);
assert_se(streq(setting1, x1000("ABCD") " foobar"));
break;
- case 12 ... 13:
+ case 14 ... 15:
assert_se(r == -ENOBUFS);
assert_se(setting1 == NULL);
break;
diff --git a/src/test/test-execute.c b/src/test/test-execute.c
index 2115061add..eb8f7c4eff 100644
--- a/src/test/test-execute.c
+++ b/src/test/test-execute.c
@@ -13,6 +13,7 @@
#include "fs-util.h"
#include "macro.h"
#include "manager.h"
+#include "missing_prctl.h"
#include "mkdir.h"
#include "path-util.h"
#include "rm-rf.h"
@@ -130,7 +131,7 @@ static bool check_user_has_group_with_same_name(const char *name) {
}
static bool is_inaccessible_available(void) {
- char *p;
+ const char *p;
FOREACH_STRING(p,
"/run/systemd/inaccessible/reg",
@@ -769,6 +770,7 @@ int main(int argc, char *argv[]) {
(void) unsetenv("USER");
(void) unsetenv("LOGNAME");
(void) unsetenv("SHELL");
+ (void) unsetenv("HOME");
can_unshare = have_namespaces();
diff --git a/src/test/test-fileio.c b/src/test/test-fileio.c
index bf918c1d1e..2ddaabe7f8 100644
--- a/src/test/test-fileio.c
+++ b/src/test/test-fileio.c
@@ -26,7 +26,8 @@ static void test_parse_env_file(void) {
p[] = "/tmp/test-fileio-out-XXXXXX";
FILE *f;
_cleanup_free_ char *one = NULL, *two = NULL, *three = NULL, *four = NULL, *five = NULL,
- *six = NULL, *seven = NULL, *eight = NULL, *nine = NULL, *ten = NULL;
+ *six = NULL, *seven = NULL, *eight = NULL, *nine = NULL, *ten = NULL,
+ *eleven = NULL, *twelve = NULL, *thirteen = NULL;
_cleanup_strv_free_ char **a = NULL, **b = NULL;
char **i;
unsigned k;
@@ -43,7 +44,7 @@ static void test_parse_env_file(void) {
"three = \"333\n"
"xxxx\"\n"
"four = \'44\\\"44\'\n"
- "five = \'55\\\'55\' \"FIVE\" cinco \n"
+ "five = \"55\\\"55\" \"FIVE\" cinco \n"
"six = seis sechs\\\n"
" sis\n"
"seven=\"sevenval\" #nocomment\n"
@@ -51,7 +52,10 @@ static void test_parse_env_file(void) {
"export nine=nineval\n"
"ten=ignored\n"
"ten=ignored\n"
- "ten=", f);
+ "ten=\n"
+ "eleven=\\value\n"
+ "twelve=\"\\value\"\n"
+ "thirteen='\\value'", f);
fflush(f);
fclose(f);
@@ -65,14 +69,17 @@ static void test_parse_env_file(void) {
assert_se(streq_ptr(a[0], "one=BAR"));
assert_se(streq_ptr(a[1], "two=bar"));
assert_se(streq_ptr(a[2], "three=333\nxxxx"));
- assert_se(streq_ptr(a[3], "four=44\"44"));
- assert_se(streq_ptr(a[4], "five=55\'55FIVEcinco"));
+ assert_se(streq_ptr(a[3], "four=44\\\"44"));
+ assert_se(streq_ptr(a[4], "five=55\"55FIVEcinco"));
assert_se(streq_ptr(a[5], "six=seis sechs sis"));
assert_se(streq_ptr(a[6], "seven=sevenval#nocomment"));
assert_se(streq_ptr(a[7], "eight=eightval #nocomment"));
assert_se(streq_ptr(a[8], "export nine=nineval"));
assert_se(streq_ptr(a[9], "ten="));
- assert_se(a[10] == NULL);
+ assert_se(streq_ptr(a[10], "eleven=value"));
+ assert_se(streq_ptr(a[11], "twelve=\\value"));
+ assert_se(streq_ptr(a[12], "thirteen=\\value"));
+ assert_se(a[13] == NULL);
strv_env_clean(a);
@@ -93,7 +100,10 @@ static void test_parse_env_file(void) {
"seven", &seven,
"eight", &eight,
"export nine", &nine,
- "ten", &ten);
+ "ten", &ten,
+ "eleven", &eleven,
+ "twelve", &twelve,
+ "thirteen", &thirteen);
assert_se(r >= 0);
@@ -107,17 +117,23 @@ static void test_parse_env_file(void) {
log_info("eight=[%s]", strna(eight));
log_info("export nine=[%s]", strna(nine));
log_info("ten=[%s]", strna(nine));
+ log_info("eleven=[%s]", strna(eleven));
+ log_info("twelve=[%s]", strna(twelve));
+ log_info("thirteen=[%s]", strna(thirteen));
assert_se(streq(one, "BAR"));
assert_se(streq(two, "bar"));
assert_se(streq(three, "333\nxxxx"));
- assert_se(streq(four, "44\"44"));
- assert_se(streq(five, "55\'55FIVEcinco"));
+ assert_se(streq(four, "44\\\"44"));
+ assert_se(streq(five, "55\"55FIVEcinco"));
assert_se(streq(six, "seis sechs sis"));
assert_se(streq(seven, "sevenval#nocomment"));
assert_se(streq(eight, "eightval #nocomment"));
assert_se(streq(nine, "nineval"));
assert_se(ten == NULL);
+ assert_se(streq(eleven, "value"));
+ assert_se(streq(twelve, "\\value"));
+ assert_se(streq(thirteen, "\\value"));
{
/* prepare a temporary file to write the environment to */
diff --git a/src/test/test-fs-util.c b/src/test/test-fs-util.c
index b3a4b1749c..e049abc4a4 100644
--- a/src/test/test-fs-util.c
+++ b/src/test/test-fs-util.c
@@ -361,11 +361,11 @@ static void test_unlink_noerrno(void) {
{
PROTECT_ERRNO;
- errno = -42;
+ errno = 42;
assert_se(unlink_noerrno(name) >= 0);
- assert_se(errno == -42);
+ assert_se(errno == 42);
assert_se(unlink_noerrno(name) < 0);
- assert_se(errno == -42);
+ assert_se(errno == 42);
}
}
diff --git a/src/test/test-hexdecoct.c b/src/test/test-hexdecoct.c
index 6e9b94b933..52217429b1 100644
--- a/src/test/test-hexdecoct.c
+++ b/src/test/test-hexdecoct.c
@@ -234,7 +234,6 @@ static void test_unbase32hexmem(void) {
test_unbase32hexmem_one("CPNMUOJ1E8======", false, -EINVAL, NULL);
test_unbase32hexmem_one("A", false, -EINVAL, NULL);
- test_unbase32hexmem_one("A", false, -EINVAL, NULL);
test_unbase32hexmem_one("AAA", false, -EINVAL, NULL);
test_unbase32hexmem_one("AAAAAA", false, -EINVAL, NULL);
test_unbase32hexmem_one("AB", false, -EINVAL, NULL);
diff --git a/src/test/test-in-addr-util.c b/src/test/test-in-addr-util.c
index 75c3e305c3..16844e9565 100644
--- a/src/test/test-in-addr-util.c
+++ b/src/test/test-in-addr-util.c
@@ -2,83 +2,85 @@
#include <netinet/in.h>
+#include "log.h"
#include "in-addr-util.h"
-static void test_in_addr_prefix_from_string(const char *p, int family, int ret, const union in_addr_union *u, unsigned char prefixlen, bool use_default) {
+static void test_in_addr_prefix_from_string(
+ const char *p,
+ int family,
+ int ret,
+ const union in_addr_union *u,
+ unsigned char prefixlen,
+ int ret_refuse,
+ unsigned char prefixlen_refuse,
+ int ret_legacy,
+ unsigned char prefixlen_legacy) {
+
union in_addr_union q;
unsigned char l;
- int r;
+ int f, r;
- r = in_addr_prefix_from_string_internal(p, use_default, family, &q, &l);
+ r = in_addr_prefix_from_string(p, family, &q, &l);
assert_se(r == ret);
- if (r >= 0) {
- int f;
+ if (r < 0)
+ return;
+
+ assert_se(in_addr_equal(family, &q, u));
+ assert_se(l == prefixlen);
+
+ r = in_addr_prefix_from_string_auto(p, &f, &q, &l);
+ assert_se(r >= 0);
+
+ assert_se(f == family);
+ assert_se(in_addr_equal(family, &q, u));
+ assert_se(l == prefixlen);
+
+ r = in_addr_prefix_from_string_auto_internal(p, PREFIXLEN_REFUSE, &f, &q, &l);
+ assert_se(r == ret_refuse);
+ if (r >= 0) {
+ assert_se(f == family);
assert_se(in_addr_equal(family, &q, u));
- assert_se(l == prefixlen);
+ assert_se(l == prefixlen_refuse);
+ }
- r = in_addr_prefix_from_string_auto_internal(p, use_default, &f, &q, &l);
- assert_se(r >= 0);
+ r = in_addr_prefix_from_string_auto_internal(p, PREFIXLEN_LEGACY, &f, &q, &l);
+ assert_se(r == ret_legacy);
+ if (r >= 0) {
assert_se(f == family);
assert_se(in_addr_equal(family, &q, u));
- assert_se(l == prefixlen);
+ assert_se(l == prefixlen_legacy);
}
}
int main(int argc, char *argv[]) {
- test_in_addr_prefix_from_string("", AF_INET, -EINVAL, NULL, 0, false);
- test_in_addr_prefix_from_string("/", AF_INET, -EINVAL, NULL, 0, false);
- test_in_addr_prefix_from_string("/8", AF_INET, -EINVAL, NULL, 0, false);
- test_in_addr_prefix_from_string("1.2.3.4", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 32, false);
- test_in_addr_prefix_from_string("1.2.3.4/0", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 0, false);
- test_in_addr_prefix_from_string("1.2.3.4/1", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 1, false);
- test_in_addr_prefix_from_string("1.2.3.4/2", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 2, false);
- test_in_addr_prefix_from_string("1.2.3.4/32", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 32, false);
- test_in_addr_prefix_from_string("1.2.3.4/33", AF_INET, -ERANGE, NULL, 0, false);
- test_in_addr_prefix_from_string("1.2.3.4/-1", AF_INET, -ERANGE, NULL, 0, false);
- test_in_addr_prefix_from_string("::1", AF_INET, -EINVAL, NULL, 0, false);
-
- test_in_addr_prefix_from_string("", AF_INET6, -EINVAL, NULL, 0, false);
- test_in_addr_prefix_from_string("/", AF_INET6, -EINVAL, NULL, 0, false);
- test_in_addr_prefix_from_string("/8", AF_INET6, -EINVAL, NULL, 0, false);
- test_in_addr_prefix_from_string("::1", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 128, false);
- test_in_addr_prefix_from_string("::1/0", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 0, false);
- test_in_addr_prefix_from_string("::1/1", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 1, false);
- test_in_addr_prefix_from_string("::1/2", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 2, false);
- test_in_addr_prefix_from_string("::1/32", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 32, false);
- test_in_addr_prefix_from_string("::1/33", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 33, false);
- test_in_addr_prefix_from_string("::1/64", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 64, false);
- test_in_addr_prefix_from_string("::1/128", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 128, false);
- test_in_addr_prefix_from_string("::1/129", AF_INET6, -ERANGE, NULL, 0, false);
- test_in_addr_prefix_from_string("::1/-1", AF_INET6, -ERANGE, NULL, 0, false);
-
- test_in_addr_prefix_from_string("", AF_INET, -EINVAL, NULL, 0, true);
- test_in_addr_prefix_from_string("/", AF_INET, -EINVAL, NULL, 0, true);
- test_in_addr_prefix_from_string("/8", AF_INET, -EINVAL, NULL, 0, true);
- test_in_addr_prefix_from_string("1.2.3.4", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 8, true);
- test_in_addr_prefix_from_string("1.2.3.4/0", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 0, true);
- test_in_addr_prefix_from_string("1.2.3.4/1", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 1, true);
- test_in_addr_prefix_from_string("1.2.3.4/2", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 2, true);
- test_in_addr_prefix_from_string("1.2.3.4/32", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 32, true);
- test_in_addr_prefix_from_string("1.2.3.4/33", AF_INET, -ERANGE, NULL, 0, true);
- test_in_addr_prefix_from_string("1.2.3.4/-1", AF_INET, -ERANGE, NULL, 0, true);
- test_in_addr_prefix_from_string("::1", AF_INET, -EINVAL, NULL, 0, true);
-
- test_in_addr_prefix_from_string("", AF_INET6, -EINVAL, NULL, 0, true);
- test_in_addr_prefix_from_string("/", AF_INET6, -EINVAL, NULL, 0, true);
- test_in_addr_prefix_from_string("/8", AF_INET6, -EINVAL, NULL, 0, true);
- test_in_addr_prefix_from_string("::1", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 0, true);
- test_in_addr_prefix_from_string("::1/0", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 0, true);
- test_in_addr_prefix_from_string("::1/1", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 1, true);
- test_in_addr_prefix_from_string("::1/2", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 2, true);
- test_in_addr_prefix_from_string("::1/32", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 32, true);
- test_in_addr_prefix_from_string("::1/33", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 33, true);
- test_in_addr_prefix_from_string("::1/64", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 64, true);
- test_in_addr_prefix_from_string("::1/128", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 128, true);
- test_in_addr_prefix_from_string("::1/129", AF_INET6, -ERANGE, NULL, 0, true);
- test_in_addr_prefix_from_string("::1/-1", AF_INET6, -ERANGE, NULL, 0, true);
+ test_in_addr_prefix_from_string("", AF_INET, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0);
+ test_in_addr_prefix_from_string("/", AF_INET, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0);
+ test_in_addr_prefix_from_string("/8", AF_INET, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0);
+ test_in_addr_prefix_from_string("1.2.3.4", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 32, -ENOANO, 0, 0, 8);
+ test_in_addr_prefix_from_string("1.2.3.4/0", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 0, 0, 0, 0, 0);
+ test_in_addr_prefix_from_string("1.2.3.4/1", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 1, 0, 1, 0, 1);
+ test_in_addr_prefix_from_string("1.2.3.4/2", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 2, 0, 2, 0, 2);
+ test_in_addr_prefix_from_string("1.2.3.4/32", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 32, 0, 32, 0, 32);
+ test_in_addr_prefix_from_string("1.2.3.4/33", AF_INET, -ERANGE, NULL, 0, -ERANGE, 0, -ERANGE, 0);
+ test_in_addr_prefix_from_string("1.2.3.4/-1", AF_INET, -ERANGE, NULL, 0, -ERANGE, 0, -ERANGE, 0);
+ test_in_addr_prefix_from_string("::1", AF_INET, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0);
+
+ test_in_addr_prefix_from_string("", AF_INET6, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0);
+ test_in_addr_prefix_from_string("/", AF_INET6, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0);
+ test_in_addr_prefix_from_string("/8", AF_INET6, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0);
+ test_in_addr_prefix_from_string("::1", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 128, -ENOANO, 0, 0, 0);
+ test_in_addr_prefix_from_string("::1/0", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 0, 0, 0, 0, 0);
+ test_in_addr_prefix_from_string("::1/1", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 1, 0, 1, 0, 1);
+ test_in_addr_prefix_from_string("::1/2", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 2, 0, 2, 0, 2);
+ test_in_addr_prefix_from_string("::1/32", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 32, 0, 32, 0, 32);
+ test_in_addr_prefix_from_string("::1/33", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 33, 0, 33, 0, 33);
+ test_in_addr_prefix_from_string("::1/64", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 64, 0, 64, 0, 64);
+ test_in_addr_prefix_from_string("::1/128", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 128, 0, 128, 0, 128);
+ test_in_addr_prefix_from_string("::1/129", AF_INET6, -ERANGE, NULL, 0, -ERANGE, 0, -ERANGE, 0);
+ test_in_addr_prefix_from_string("::1/-1", AF_INET6, -ERANGE, NULL, 0, -ERANGE, 0, -ERANGE, 0);
return 0;
}
diff --git a/src/test/test-json.c b/src/test/test-json.c
index 5aa4d19dbe..fdf1b4f40c 100644
--- a/src/test/test-json.c
+++ b/src/test/test-json.c
@@ -1,9 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#include <math.h>
-#if HAVE_VALGRIND_VALGRIND_H
-#include <valgrind/valgrind.h>
-#endif
#include "alloc-util.h"
#include "fd-util.h"
@@ -45,12 +42,13 @@ static void test_tokenizer(const char *data, ...) {
d = va_arg(ap, long double);
-#if HAVE_VALGRIND_VALGRIND_H
- if (!RUNNING_ON_VALGRIND)
-#endif
- /* Valgrind doesn't support long double calculations and automatically downgrades to 80bit:
- * http://www.valgrind.org/docs/manual/manual-core.html#manual-core.limits */
- assert_se(fabsl(d - v.real) < 0.001L);
+ /* Valgrind doesn't support long double calculations and automatically downgrades to 80bit:
+ * http://www.valgrind.org/docs/manual/manual-core.html#manual-core.limits.
+ * Some architectures might not support long double either.
+ */
+
+ assert_se(fabsl(d - v.real) < 1e-10 ||
+ fabsl((d - v.real) / v.real) < 1e-10);
} else if (t == JSON_TOKEN_INTEGER) {
intmax_t i;
@@ -211,7 +209,6 @@ static void test_2(JsonVariant *v) {
assert_se(p && json_variant_type(p) == JSON_VARIANT_REAL && fabsl(json_variant_real(p) - 1.27) < 0.001);
}
-
static void test_zeroes(JsonVariant *v) {
size_t i;
@@ -285,6 +282,7 @@ static void test_build(void) {
a = json_variant_unref(a);
b = json_variant_unref(b);
+ const char* arr_1234[] = {"one", "two", "three", "four", NULL};
assert_se(json_build(&a, JSON_BUILD_ARRAY(JSON_BUILD_OBJECT(JSON_BUILD_PAIR("x", JSON_BUILD_BOOLEAN(true)),
JSON_BUILD_PAIR("y", JSON_BUILD_OBJECT(JSON_BUILD_PAIR("this", JSON_BUILD_NULL)))),
JSON_BUILD_VARIANT(NULL),
@@ -292,8 +290,9 @@ static void test_build(void) {
JSON_BUILD_STRING(NULL),
JSON_BUILD_NULL,
JSON_BUILD_INTEGER(77),
- JSON_BUILD_ARRAY(JSON_BUILD_VARIANT(JSON_VARIANT_STRING_CONST("foobar")), JSON_BUILD_VARIANT(JSON_VARIANT_STRING_CONST("zzz"))),
- JSON_BUILD_STRV(STRV_MAKE("one", "two", "three", "four")))) >= 0);
+ JSON_BUILD_ARRAY(JSON_BUILD_VARIANT(JSON_VARIANT_STRING_CONST("foobar")),
+ JSON_BUILD_VARIANT(JSON_VARIANT_STRING_CONST("zzz"))),
+ JSON_BUILD_STRV((char**) arr_1234))) >= 0);
assert_se(json_variant_format(a, 0, &s) >= 0);
log_info("GOT: %s\n", s);
diff --git a/src/test/test-libudev.c b/src/test/test-libudev.c
index 10bf365035..15c0f8853d 100644
--- a/src/test/test-libudev.c
+++ b/src/test/test-libudev.c
@@ -7,6 +7,7 @@
#include <unistd.h>
#include "alloc-util.h"
+#include "build.h"
#include "fd-util.h"
#include "libudev-list-internal.h"
#include "libudev-util.h"
@@ -364,16 +365,23 @@ static void test_util_replace_whitespace(void) {
test_util_replace_whitespace_one_len("hoge hoge ", 1, "h");
test_util_replace_whitespace_one_len("hoge hoge ", 0, "");
- test_util_replace_whitespace_one_len(" hoge hoge ", 9, "hoge_hoge");
- test_util_replace_whitespace_one_len(" hoge hoge ", 8, "hoge_hog");
- test_util_replace_whitespace_one_len(" hoge hoge ", 7, "hoge_ho");
- test_util_replace_whitespace_one_len(" hoge hoge ", 6, "hoge_h");
- test_util_replace_whitespace_one_len(" hoge hoge ", 5, "hoge");
- test_util_replace_whitespace_one_len(" hoge hoge ", 4, "hoge");
- test_util_replace_whitespace_one_len(" hoge hoge ", 3, "hog");
- test_util_replace_whitespace_one_len(" hoge hoge ", 2, "ho");
- test_util_replace_whitespace_one_len(" hoge hoge ", 1, "h");
- test_util_replace_whitespace_one_len(" hoge hoge ", 0, "");
+ test_util_replace_whitespace_one_len(" hoge hoge ", 16, "hoge_hoge");
+ test_util_replace_whitespace_one_len(" hoge hoge ", 15, "hoge_hoge");
+ test_util_replace_whitespace_one_len(" hoge hoge ", 14, "hoge_hog");
+ test_util_replace_whitespace_one_len(" hoge hoge ", 13, "hoge_ho");
+ test_util_replace_whitespace_one_len(" hoge hoge ", 12, "hoge_h");
+ test_util_replace_whitespace_one_len(" hoge hoge ", 11, "hoge");
+ test_util_replace_whitespace_one_len(" hoge hoge ", 10, "hoge");
+ test_util_replace_whitespace_one_len(" hoge hoge ", 9, "hoge");
+ test_util_replace_whitespace_one_len(" hoge hoge ", 8, "hoge");
+ test_util_replace_whitespace_one_len(" hoge hoge ", 7, "hog");
+ test_util_replace_whitespace_one_len(" hoge hoge ", 6, "ho");
+ test_util_replace_whitespace_one_len(" hoge hoge ", 5, "h");
+ test_util_replace_whitespace_one_len(" hoge hoge ", 4, "");
+ test_util_replace_whitespace_one_len(" hoge hoge ", 3, "");
+ test_util_replace_whitespace_one_len(" hoge hoge ", 2, "");
+ test_util_replace_whitespace_one_len(" hoge hoge ", 1, "");
+ test_util_replace_whitespace_one_len(" hoge hoge ", 0, "");
}
static void test_util_resolve_subsys_kernel_one(const char *str, bool read_value, int retval, const char *expected) {
@@ -507,7 +515,7 @@ int main(int argc, char *argv[]) {
return EXIT_SUCCESS;
case 'V':
- printf("%s\n", PACKAGE_VERSION);
+ printf("%s\n", GIT_VERSION);
return EXIT_SUCCESS;
case 'm':
diff --git a/src/test/test-mountpoint-util.c b/src/test/test-mountpoint-util.c
index 6d8bee0d63..8e45c0b1a7 100644
--- a/src/test/test-mountpoint-util.c
+++ b/src/test/test-mountpoint-util.c
@@ -8,7 +8,6 @@
#include "fileio.h"
#include "hashmap.h"
#include "log.h"
-#include "log.h"
#include "mountpoint-util.h"
#include "path-util.h"
#include "rm-rf.h"
diff --git a/src/test/test-path-util.c b/src/test/test-path-util.c
index 8854a94f6c..c64ca7b016 100644
--- a/src/test/test-path-util.c
+++ b/src/test/test-path-util.c
@@ -531,7 +531,7 @@ static void test_hidden_or_backup_file(void) {
static void test_systemd_installation_has_version(const char *path) {
int r;
- const unsigned versions[] = {0, 231, atoi(PACKAGE_VERSION), 999};
+ const unsigned versions[] = {0, 231, PROJECT_VERSION, 999};
unsigned i;
for (i = 0; i < ELEMENTSOF(versions); i++) {
diff --git a/src/test/test-prioq.c b/src/test/test-prioq.c
index bc5fdd15b2..53c9e090a7 100644
--- a/src/test/test-prioq.c
+++ b/src/test/test-prioq.c
@@ -69,6 +69,11 @@ static void test_struct(void) {
assert_se(q = prioq_new((compare_func_t) test_compare));
assert_se(s = set_new(&test_hash_ops));
+ assert_se(prioq_peek(q) == NULL);
+ assert_se(prioq_peek_by_index(q, 0) == NULL);
+ assert_se(prioq_peek_by_index(q, 1) == NULL);
+ assert_se(prioq_peek_by_index(q, (unsigned) -1) == NULL);
+
for (i = 0; i < SET_SIZE; i++) {
assert_se(t = new0(struct test, 1));
t->value = (unsigned) rand();
@@ -79,6 +84,17 @@ static void test_struct(void) {
assert_se(set_consume(s, t) >= 0);
}
+ for (i = 0; i < SET_SIZE; i++)
+ assert_se(prioq_peek_by_index(q, i));
+ assert_se(prioq_peek_by_index(q, SET_SIZE) == NULL);
+
+ unsigned count = 0;
+ PRIOQ_FOREACH_ITEM(q, t) {
+ assert_se(t);
+ count++;
+ }
+ assert_se(count == SET_SIZE);
+
while ((t = set_steal_first(s))) {
assert_se(prioq_remove(q, t, &t->idx) == 1);
assert_se(prioq_remove(q, t, &t->idx) == 0);
diff --git a/src/test/test-process-util.c b/src/test/test-process-util.c
index 5c87db08f5..b5ba651d89 100644
--- a/src/test/test-process-util.c
+++ b/src/test/test-process-util.c
@@ -70,11 +70,9 @@ static void test_get_process_comm(pid_t pid) {
assert_se(get_process_uid(pid, &u) == 0);
log_info("PID"PID_FMT" UID: "UID_FMT, pid, u);
- assert_se(u == 0 || pid != 1);
assert_se(get_process_gid(pid, &g) == 0);
log_info("PID"PID_FMT" GID: "GID_FMT, pid, g);
- assert_se(g == 0 || pid != 1);
r = get_process_environ(pid, &env);
assert_se(r >= 0 || r == -EACCES);
diff --git a/src/test/test-procfs-util.c b/src/test/test-procfs-util.c
index 08af380cc7..1d0612985b 100644
--- a/src/test/test-procfs-util.c
+++ b/src/test/test-procfs-util.c
@@ -18,7 +18,7 @@ int main(int argc, char *argv[]) {
assert_se(procfs_cpu_get_usage(&nsec) >= 0);
log_info("Current system CPU time: %s", format_timespan(buf, sizeof(buf), nsec/NSEC_PER_USEC, 1));
- assert_se(procfs_memory_get_current(&v) >= 0);
+ assert_se(procfs_memory_get_used(&v) >= 0);
log_info("Current memory usage: %s", format_bytes(buf, sizeof(buf), v));
assert_se(procfs_tasks_get_current(&v) >= 0);
diff --git a/src/test/test-sizeof.c b/src/test/test-sizeof.c
index 7a1e496ed2..35b087653e 100644
--- a/src/test/test-sizeof.c
+++ b/src/test/test-sizeof.c
@@ -13,11 +13,12 @@
#pragma GCC diagnostic ignored "-Wtype-limits"
-#define info(t) \
- printf("%s → %zu bits%s\n", STRINGIFY(t), \
- sizeof(t)*CHAR_BIT, \
- strstr(STRINGIFY(t), "signed") ? "" : \
- ((t)-1 < (t)0 ? ", signed" : ", unsigned"));
+#define info(t) \
+ printf("%s → %zu bits%s, %zu byte alignment\n", STRINGIFY(t), \
+ sizeof(t)*CHAR_BIT, \
+ strstr(STRINGIFY(t), "signed") ? "" : \
+ (t)-1 < (t)0 ? ", signed" : ", unsigned", \
+ __alignof__(t))
enum Enum {
enum_value,
diff --git a/src/test/test-stat-util.c b/src/test/test-stat-util.c
index d16fdd90d1..0e2155e911 100644
--- a/src/test/test-stat-util.c
+++ b/src/test/test-stat-util.c
@@ -56,7 +56,6 @@ static void test_path_is_fs_type(void) {
}
assert_se(path_is_fs_type("/proc", PROC_SUPER_MAGIC) > 0);
assert_se(path_is_fs_type("/proc", BTRFS_SUPER_MAGIC) == 0);
- assert_se(path_is_fs_type("/proc", BTRFS_SUPER_MAGIC) == 0);
assert_se(path_is_fs_type("/i-dont-exist", BTRFS_SUPER_MAGIC) == -ENOENT);
}
diff --git a/src/test/test-time-util.c b/src/test/test-time-util.c
index 2ec2ade3f1..eb6041c152 100644
--- a/src/test/test-time-util.c
+++ b/src/test/test-time-util.c
@@ -212,7 +212,6 @@ static void test_format_timespan(usec_t accuracy) {
test_format_timespan_one(12345678, accuracy);
test_format_timespan_one(1200000, accuracy);
test_format_timespan_one(1230000, accuracy);
- test_format_timespan_one(1230000, accuracy);
test_format_timespan_one(1234000, accuracy);
test_format_timespan_one(1234500, accuracy);
test_format_timespan_one(1234560, accuracy);
@@ -289,7 +288,6 @@ static void test_usec_sub_signed(void) {
assert_se(usec_sub_signed(4, 4) == 0);
assert_se(usec_sub_signed(4, 5) == 0);
assert_se(usec_sub_signed(USEC_INFINITY-3, -3) == USEC_INFINITY);
- assert_se(usec_sub_signed(USEC_INFINITY-3, -3) == USEC_INFINITY);
assert_se(usec_sub_signed(USEC_INFINITY-3, -4) == USEC_INFINITY);
assert_se(usec_sub_signed(USEC_INFINITY-3, -5) == USEC_INFINITY);
assert_se(usec_sub_signed(USEC_INFINITY, 5) == USEC_INFINITY);
diff --git a/src/test/test-udev.c b/src/test/test-udev.c
index 7a4622b875..ab31f5a2f1 100644
--- a/src/test/test-udev.c
+++ b/src/test/test-udev.c
@@ -11,6 +11,7 @@
#include <sys/signalfd.h>
#include <unistd.h>
+#include "build.h"
#include "device-private.h"
#include "fs-util.h"
#include "log.h"
@@ -81,7 +82,7 @@ static int run(int argc, char *argv[]) {
return 0;
}
- log_debug("version %s", PACKAGE_VERSION);
+ log_debug("version %s", GIT_VERSION);
mac_selinux_init();
action = argv[1];
diff --git a/src/test/test-util.c b/src/test/test-util.c
index 3c1b5f9b41..ffacd65669 100644
--- a/src/test/test-util.c
+++ b/src/test/test-util.c
@@ -139,11 +139,11 @@ static void test_container_of(void) {
uint64_t v1;
uint8_t pad2[2];
uint32_t v2;
- } _packed_ myval = { };
+ } myval = { };
log_info("/* %s */", __func__);
- assert_cc(sizeof(myval) == 17);
+ assert_cc(sizeof(myval) >= 17);
assert_se(container_of(&myval.v1, struct mytype, v1) == &myval);
assert_se(container_of(&myval.v2, struct mytype, v2) == &myval);
assert_se(container_of(&container_of(&myval.v2,
@@ -213,6 +213,30 @@ static void test_protect_errno(void) {
assert_se(errno == 12);
}
+static void test_unprotect_errno_inner_function(void) {
+ PROTECT_ERRNO;
+
+ errno = 2222;
+}
+
+static void test_unprotect_errno(void) {
+ log_info("/* %s */", __func__);
+
+ errno = 4711;
+
+ PROTECT_ERRNO;
+
+ errno = 815;
+
+ UNPROTECT_ERRNO;
+
+ assert_se(errno == 4711);
+
+ test_unprotect_errno_inner_function();
+
+ assert_se(errno == 4711);
+}
+
static void test_in_set(void) {
log_info("/* %s */", __func__);
@@ -383,6 +407,7 @@ int main(int argc, char *argv[]) {
test_div_round_up();
test_u64log2();
test_protect_errno();
+ test_unprotect_errno();
test_in_set();
test_log2i();
test_eqzero();
diff --git a/src/timedate/timedated.c b/src/timedate/timedated.c
index e16888945c..eeb17b613e 100644
--- a/src/timedate/timedated.c
+++ b/src/timedate/timedated.c
@@ -160,7 +160,7 @@ static int context_ntp_service_is_active(Context *c) {
/* Call context_update_ntp_status() to update UnitStatusInfo before calling this. */
LIST_FOREACH(units, info, c->units)
- count += streq_ptr(info->active_state, "active");
+ count += !STRPTR_IN_SET(info->active_state, "inactive", "failed");
return count;
}
@@ -174,7 +174,7 @@ static int context_ntp_service_is_enabled(Context *c) {
/* Call context_update_ntp_status() to update UnitStatusInfo before calling this. */
LIST_FOREACH(units, info, c->units)
- count += STRPTR_IN_SET(info->unit_file_state, "enabled", "enabled-runtime");
+ count += !STRPTR_IN_SET(info->unit_file_state, "masked", "masked-runtime", "disabled", "bad");
return count;
}
@@ -523,6 +523,10 @@ static int property_get_can_ntp(
assert(reply);
assert(error);
+ if (c->slot_job_removed)
+ /* When the previous request is not finished, then assume NTP is enabled. */
+ return sd_bus_message_append(reply, "b", true);
+
r = context_update_ntp_status(c, bus, reply);
if (r < 0)
return r;
@@ -548,6 +552,10 @@ static int property_get_ntp(
assert(reply);
assert(error);
+ if (c->slot_job_removed)
+ /* When the previous request is not finished, then assume NTP is active. */
+ return sd_bus_message_append(reply, "b", true);
+
r = context_update_ntp_status(c, bus, reply);
if (r < 0)
return r;
@@ -735,6 +743,9 @@ static int method_set_time(sd_bus_message *m, void *userdata, sd_bus_error *erro
assert(m);
assert(c);
+ if (c->slot_job_removed)
+ return sd_bus_error_set(error, BUS_ERROR_AUTOMATIC_TIME_SYNC_ENABLED, "Previous request is not finished, refusing.");
+
r = context_update_ntp_status(c, bus, m);
if (r < 0)
return sd_bus_error_set_errnof(error, r, "Failed to update context: %m");
diff --git a/src/timesync/timesyncd-manager.c b/src/timesync/timesyncd-manager.c
index 4b0696f3a3..6fde4a316b 100644
--- a/src/timesync/timesyncd-manager.c
+++ b/src/timesync/timesyncd-manager.c
@@ -616,8 +616,9 @@ static int manager_receive_response(sd_event_source *source, int fd, uint32_t re
m->good = true;
server_address_pretty(m->current_server_address, &pretty);
- log_info("Synchronized to time server %s (%s).", strna(pretty), m->current_server_name->string);
- sd_notifyf(false, "STATUS=Synchronized to time server %s (%s).", strna(pretty), m->current_server_name->string);
+ /* "for the first time", as further successful syncs will not be logged. */
+ log_info("Synchronized to time server for the first time %s (%s).", strna(pretty), m->current_server_name->string);
+ sd_notifyf(false, "STATUS=Synchronized to time server for the first time %s (%s).", strna(pretty), m->current_server_name->string);
}
r = manager_arm_timer(m, m->poll_interval_usec);
@@ -937,7 +938,7 @@ void manager_free(Manager *m) {
sd_resolve_unref(m->resolve);
sd_event_unref(m->event);
- sd_bus_unref(m->bus);
+ sd_bus_flush_close_unref(m->bus);
free(m);
}
diff --git a/src/timesync/timesyncd.c b/src/timesync/timesyncd.c
index 70774d757b..b4f70c0007 100644
--- a/src/timesync/timesyncd.c
+++ b/src/timesync/timesyncd.c
@@ -169,9 +169,7 @@ static int run(int argc, char *argv[]) {
log_debug_errno(r, "Failed to touch %s, ignoring: %m", CLOCK_FILE);
}
- (void) sd_event_get_exit_code(m->event, &r);
-
- return r;
+ return 0;
}
DEFINE_MAIN_FUNCTION(run);
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
index 19225f8cfd..b66765b407 100644
--- a/src/tmpfiles/tmpfiles.c
+++ b/src/tmpfiles/tmpfiles.c
@@ -1463,7 +1463,7 @@ static int copy_files(Item *i) {
dfd, bn,
i->uid_set ? i->uid : UID_INVALID,
i->gid_set ? i->gid : GID_INVALID,
- COPY_REFLINK);
+ COPY_REFLINK | COPY_MERGE_EMPTY);
if (r < 0) {
struct stat a, b;
@@ -3130,7 +3130,7 @@ static int link_parent(ItemArray *a) {
return 0;
path = a->items[0].path;
- prefix = alloca(strlen(path) + 1);
+ prefix = newa(char, strlen(path) + 1);
PATH_FOREACH_PREFIX(prefix, path) {
ItemArray *j;
diff --git a/src/udev/meson.build b/src/udev/meson.build
index e378d9190c..9d3f6d1c56 100644
--- a/src/udev/meson.build
+++ b/src/udev/meson.build
@@ -41,6 +41,8 @@ libudev_core_sources = '''
net/link-config.h
net/ethtool-util.c
net/ethtool-util.h
+ net/naming-scheme.c
+ net/naming-scheme.h
'''.split()
if conf.get('HAVE_KMOD') == 1
@@ -187,12 +189,11 @@ endforeach
install_data('udev.conf',
install_dir : join_paths(sysconfdir, 'udev'))
-udev_pc = configure_file(
+configure_file(
input : 'udev.pc.in',
output : 'udev.pc',
- configuration : substs)
-install_data(udev_pc,
- install_dir : pkgconfigdatadir)
+ configuration : substs,
+ install_dir : pkgconfigdatadir == 'no' ? '' : pkgconfigdatadir)
meson.add_install_script('sh', '-c',
mkdir_p.format(join_paths(sysconfdir, 'udev/rules.d')))
diff --git a/src/udev/net/ethtool-util.c b/src/udev/net/ethtool-util.c
index bc0deaf347..0dcec03f67 100644
--- a/src/udev/net/ethtool-util.c
+++ b/src/udev/net/ethtool-util.c
@@ -31,18 +31,18 @@ static const char* const wol_table[_WOL_MAX] = {
[WOL_ARP] = "arp",
[WOL_MAGIC] = "magic",
[WOL_MAGICSECURE] = "secureon",
- [WOL_OFF] = "off"
+ [WOL_OFF] = "off",
};
DEFINE_STRING_TABLE_LOOKUP(wol, WakeOnLan);
DEFINE_CONFIG_PARSE_ENUM(config_parse_wol, wol, WakeOnLan, "Failed to parse WakeOnLan setting");
-static const char* const port_table[_NET_DEV_PORT_MAX] = {
+static const char* const port_table[] = {
[NET_DEV_PORT_TP] = "tp",
[NET_DEV_PORT_AUI] = "aui",
[NET_DEV_PORT_MII] = "mii",
[NET_DEV_PORT_FIBRE] = "fibre",
- [NET_DEV_PORT_BNC] = "bnc"
+ [NET_DEV_PORT_BNC] = "bnc",
};
DEFINE_STRING_TABLE_LOOKUP(port, NetDevPort);
@@ -583,7 +583,7 @@ int ethtool_set_glinksettings(int *fd, const char *ifname, struct link_config *l
struct ifreq ifr = {};
int r;
- if (link->autonegotiation != 0) {
+ if (link->autonegotiation != AUTONEG_DISABLE && eqzero(link->advertise)) {
log_info("link_config: autonegotiation is unset or enabled, the speed and duplex are not writable.");
return 0;
}
@@ -612,9 +612,11 @@ int ethtool_set_glinksettings(int *fd, const char *ifname, struct link_config *l
if (link->port != _NET_DEV_PORT_INVALID)
u->base.port = link->port;
- u->base.autoneg = link->autonegotiation;
+ if (link->autonegotiation >= 0)
+ u->base.autoneg = link->autonegotiation;
if (!eqzero(link->advertise)) {
+ u->base.autoneg = AUTONEG_ENABLE;
memcpy(&u->link_modes.advertising, link->advertise, sizeof(link->advertise));
memzero((uint8_t*) &u->link_modes.advertising + sizeof(link->advertise),
ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NBYTES - sizeof(link->advertise));
diff --git a/src/udev/net/ethtool-util.h b/src/udev/net/ethtool-util.h
index e4bc5161d5..618b26bf59 100644
--- a/src/udev/net/ethtool-util.h
+++ b/src/udev/net/ethtool-util.h
@@ -42,14 +42,14 @@ typedef enum NetDevFeature {
} NetDevFeature;
typedef enum NetDevPort {
- NET_DEV_PORT_TP = 0x00,
- NET_DEV_PORT_AUI = 0x01,
- NET_DEV_PORT_MII = 0x02,
- NET_DEV_PORT_FIBRE = 0x03,
- NET_DEV_PORT_BNC = 0x04,
- NET_DEV_PORT_DA = 0x05,
- NET_DEV_PORT_NONE = 0xef,
- NET_DEV_PORT_OTHER = 0xff,
+ NET_DEV_PORT_TP = PORT_TP,
+ NET_DEV_PORT_AUI = PORT_AUI,
+ NET_DEV_PORT_MII = PORT_MII,
+ NET_DEV_PORT_FIBRE = PORT_FIBRE,
+ NET_DEV_PORT_BNC = PORT_BNC,
+ NET_DEV_PORT_DA = PORT_DA,
+ NET_DEV_PORT_NONE = PORT_NONE,
+ NET_DEV_PORT_OTHER = PORT_OTHER,
_NET_DEV_PORT_MAX,
_NET_DEV_PORT_INVALID = -1
} NetDevPort;
diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c
index ac66ffd047..eb2477cea4 100644
--- a/src/udev/net/link-config.c
+++ b/src/udev/net/link-config.c
@@ -14,6 +14,7 @@
#include "link-config.h"
#include "log.h"
#include "missing_network.h"
+#include "naming-scheme.h"
#include "netlink-util.h"
#include "network-internal.h"
#include "parse-util.h"
@@ -186,6 +187,22 @@ static bool enable_name_policy(void) {
return proc_cmdline_get_bool("net.ifnames", &b) <= 0 || b;
}
+static int link_name_type(sd_device *device, unsigned *type) {
+ const char *s;
+ int r;
+
+ r = sd_device_get_sysattr_value(device, "name_assign_type", &s);
+ if (r < 0)
+ return log_device_debug_errno(device, r, "Failed to query name_assign_type: %m");
+
+ r = safe_atou(s, type);
+ if (r < 0)
+ return log_device_warning_errno(device, r, "Failed to parse name_assign_type \"%s\": %m", s);
+
+ log_device_debug(device, "Device has name_assign_type=%d", *type);
+ return 0;
+}
+
int link_config_load(link_config_ctx *ctx) {
_cleanup_strv_free_ char **files;
char **f;
@@ -256,13 +273,13 @@ int link_config_get(link_config_ctx *ctx, sd_device *device, link_config **ret)
if (name_assign_type == NET_NAME_ENUM) {
log_warning("Config file %s applies to device based on potentially unpredictable interface name '%s'",
- link->filename, sysname);
+ link->filename, sysname);
*ret = link;
return 0;
} else if (name_assign_type == NET_NAME_RENAMED) {
log_warning("Config file %s matches device based on renamed interface name '%s', ignoring",
- link->filename, sysname);
+ link->filename, sysname);
continue;
}
@@ -272,13 +289,11 @@ int link_config_get(link_config_ctx *ctx, sd_device *device, link_config **ret)
link->filename, sysname);
*ret = link;
-
return 0;
}
}
*ret = NULL;
-
return -ENOENT;
}
@@ -298,31 +313,6 @@ static bool mac_is_random(sd_device *device) {
return type == NET_ADDR_RANDOM;
}
-static bool should_rename(sd_device *device, bool respect_predictable) {
- const char *s;
- unsigned type;
- int r;
-
- /* if we can't get the assgin type, assume we should rename */
- if (sd_device_get_sysattr_value(device, "name_assign_type", &s) < 0)
- return true;
-
- r = safe_atou(s, &type);
- if (r < 0)
- return true;
-
- switch (type) {
- case NET_NAME_PREDICTABLE:
- /* the kernel claims to have given a predictable name */
- if (respect_predictable)
- return false;
- _fallthrough_;
- default:
- /* the name is known to be bad, or of an unknown type */
- return true;
- }
-}
-
static int get_mac(sd_device *device, bool want_random,
struct ether_addr *mac) {
int r;
@@ -349,12 +339,12 @@ static int get_mac(sd_device *device, bool want_random,
int link_config_apply(link_config_ctx *ctx, link_config *config,
sd_device *device, const char **name) {
- bool respect_predictable = false;
struct ether_addr generated_mac;
struct ether_addr *mac = NULL;
const char *new_name = NULL;
const char *old_name;
- unsigned speed;
+ unsigned speed, name_type = NET_NAME_UNKNOWN;
+ NamePolicy policy;
int r, ifindex;
assert(ctx);
@@ -407,38 +397,63 @@ int link_config_apply(link_config_ctx *ctx, link_config *config,
if (r < 0)
return log_device_warning_errno(device, r, "Could not find ifindex: %m");
- if (ctx->enable_name_policy && config->name_policy) {
- NamePolicy *policy;
- for (policy = config->name_policy;
- !new_name && *policy != _NAMEPOLICY_INVALID; policy++) {
- switch (*policy) {
- case NAMEPOLICY_KERNEL:
- respect_predictable = true;
- break;
- case NAMEPOLICY_DATABASE:
- (void) sd_device_get_property_value(device, "ID_NET_NAME_FROM_DATABASE", &new_name);
- break;
- case NAMEPOLICY_ONBOARD:
- (void) sd_device_get_property_value(device, "ID_NET_NAME_ONBOARD", &new_name);
- break;
- case NAMEPOLICY_SLOT:
- (void) sd_device_get_property_value(device, "ID_NET_NAME_SLOT", &new_name);
- break;
- case NAMEPOLICY_PATH:
- (void) sd_device_get_property_value(device, "ID_NET_NAME_PATH", &new_name);
- break;
- case NAMEPOLICY_MAC:
- (void) sd_device_get_property_value(device, "ID_NET_NAME_MAC", &new_name);
- break;
- default:
- break;
+ (void) link_name_type(device, &name_type);
+
+ if (IN_SET(name_type, NET_NAME_USER, NET_NAME_RENAMED)
+ && !naming_scheme_has(NAMING_ALLOW_RERENAMES)) {
+ log_device_debug(device, "Device already has a name given by userspace, not renaming.");
+ goto no_rename;
+ }
+
+ if (ctx->enable_name_policy && config->name_policy)
+ for (NamePolicy *p = config->name_policy; !new_name && *p != _NAMEPOLICY_INVALID; p++) {
+ policy = *p;
+
+ switch (policy) {
+ case NAMEPOLICY_KERNEL:
+ if (name_type != NET_NAME_PREDICTABLE)
+ continue;
+
+ /* The kernel claims to have given a predictable name, keep it. */
+ log_device_debug(device, "Policy *%s*: keeping predictable kernel name",
+ name_policy_to_string(policy));
+ goto no_rename;
+ case NAMEPOLICY_KEEP:
+ if (!IN_SET(name_type, NET_NAME_USER, NET_NAME_RENAMED))
+ continue;
+
+ log_device_debug(device, "Policy *%s*: keeping existing userspace name",
+ name_policy_to_string(policy));
+ goto no_rename;
+ case NAMEPOLICY_DATABASE:
+ (void) sd_device_get_property_value(device, "ID_NET_NAME_FROM_DATABASE", &new_name);
+ break;
+ case NAMEPOLICY_ONBOARD:
+ (void) sd_device_get_property_value(device, "ID_NET_NAME_ONBOARD", &new_name);
+ break;
+ case NAMEPOLICY_SLOT:
+ (void) sd_device_get_property_value(device, "ID_NET_NAME_SLOT", &new_name);
+ break;
+ case NAMEPOLICY_PATH:
+ (void) sd_device_get_property_value(device, "ID_NET_NAME_PATH", &new_name);
+ break;
+ case NAMEPOLICY_MAC:
+ (void) sd_device_get_property_value(device, "ID_NET_NAME_MAC", &new_name);
+ break;
+ default:
+ assert_not_reached("invalid policy");
}
}
- }
- if (!new_name && should_rename(device, respect_predictable))
+ if (new_name)
+ log_device_debug(device, "Policy *%s* yields \"%s\".", name_policy_to_string(policy), new_name);
+ else if (config->name) {
new_name = config->name;
+ log_device_debug(device, "Policies didn't yield a name, using specified Name=%s.", new_name);
+ } else
+ log_device_debug(device, "Policies didn't yield a name and Name= is not given, not renaming.");
+ no_rename:
switch (config->mac_policy) {
case MACPOLICY_PERSISTENT:
@@ -497,7 +512,7 @@ int link_get_driver(link_config_ctx *ctx, sd_device *device, char **ret) {
static const char* const mac_policy_table[_MACPOLICY_MAX] = {
[MACPOLICY_PERSISTENT] = "persistent",
[MACPOLICY_RANDOM] = "random",
- [MACPOLICY_NONE] = "none"
+ [MACPOLICY_NONE] = "none",
};
DEFINE_STRING_TABLE_LOOKUP(mac_policy, MACPolicy);
@@ -506,11 +521,12 @@ DEFINE_CONFIG_PARSE_ENUM(config_parse_mac_policy, mac_policy, MACPolicy,
static const char* const name_policy_table[_NAMEPOLICY_MAX] = {
[NAMEPOLICY_KERNEL] = "kernel",
+ [NAMEPOLICY_KEEP] = "keep",
[NAMEPOLICY_DATABASE] = "database",
[NAMEPOLICY_ONBOARD] = "onboard",
[NAMEPOLICY_SLOT] = "slot",
[NAMEPOLICY_PATH] = "path",
- [NAMEPOLICY_MAC] = "mac"
+ [NAMEPOLICY_MAC] = "mac",
};
DEFINE_STRING_TABLE_LOOKUP(name_policy, NamePolicy);
diff --git a/src/udev/net/link-config.h b/src/udev/net/link-config.h
index 8204959034..1113b1052e 100644
--- a/src/udev/net/link-config.h
+++ b/src/udev/net/link-config.h
@@ -22,6 +22,7 @@ typedef enum MACPolicy {
typedef enum NamePolicy {
NAMEPOLICY_KERNEL,
+ NAMEPOLICY_KEEP,
NAMEPOLICY_DATABASE,
NAMEPOLICY_ONBOARD,
NAMEPOLICY_SLOT,
diff --git a/src/udev/net/naming-scheme.c b/src/udev/net/naming-scheme.c
new file mode 100644
index 0000000000..27cede5e2e
--- /dev/null
+++ b/src/udev/net/naming-scheme.c
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#include "alloc-util.h"
+#include "naming-scheme.h"
+#include "proc-cmdline.h"
+#include "string-util.h"
+
+static const NamingScheme naming_schemes[] = {
+ { "v238", NAMING_V238 },
+ { "v239", NAMING_V239 },
+ { "v240", NAMING_V240 },
+ /* … add more schemes here, as the logic to name devices is updated … */
+};
+
+static const NamingScheme* naming_scheme_from_name(const char *name) {
+ size_t i;
+
+ if (streq(name, "latest"))
+ return naming_schemes + ELEMENTSOF(naming_schemes) - 1;
+
+ for (i = 0; i < ELEMENTSOF(naming_schemes); i++)
+ if (streq(naming_schemes[i].name, name))
+ return naming_schemes + i;
+
+ return NULL;
+}
+
+const NamingScheme* naming_scheme(void) {
+ static const NamingScheme *cache = NULL;
+ _cleanup_free_ char *buffer = NULL;
+ const char *e, *k;
+
+ if (cache)
+ return cache;
+
+ /* Acquire setting from the kernel command line */
+ (void) proc_cmdline_get_key("net.naming-scheme", 0, &buffer);
+
+ /* Also acquire it from an env var */
+ e = getenv("NET_NAMING_SCHEME");
+ if (e) {
+ if (*e == ':') {
+ /* If prefixed with ':' the kernel cmdline takes precedence */
+ k = buffer ?: e + 1;
+ } else
+ k = e; /* Otherwise the env var takes precedence */
+ } else
+ k = buffer;
+
+ if (k) {
+ cache = naming_scheme_from_name(k);
+ if (cache) {
+ log_info("Using interface naming scheme '%s'.", cache->name);
+ return cache;
+ }
+
+ log_warning("Unknown interface naming scheme '%s' requested, ignoring.", k);
+ }
+
+ cache = naming_scheme_from_name(DEFAULT_NET_NAMING_SCHEME);
+ assert(cache);
+ log_info("Using default interface naming scheme '%s'.", cache->name);
+
+ return cache;
+}
diff --git a/src/udev/net/naming-scheme.h b/src/udev/net/naming-scheme.h
new file mode 100644
index 0000000000..0b3d9bff1d
--- /dev/null
+++ b/src/udev/net/naming-scheme.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include <stdbool.h>
+
+#include "macro.h"
+
+/* So here's the deal: net_id is supposed to be an excercise in providing stable names for network devices. However, we
+ * also want to keep updating the naming scheme used in future versions of net_id. These two goals of course are
+ * contradictory: on one hand we want things to not change and on the other hand we want them to improve. Our way out
+ * of this dilemma is to introduce the "naming scheme" concept: each time we improve the naming logic we define a new
+ * flag for it. Then, we keep a list of schemes, each identified by a name associated with the flags it implements. Via
+ * a kernel command line and environment variable we then allow the user to pick the scheme they want us to follow:
+ * installers could "freeze" the used scheme at the moment of installation this way.
+ *
+ * Developers: each time you tweak the naming logic here, define a new flag below, and condition the tweak with
+ * it. Each time we do a release we'll then add a new scheme entry and include all newly defined flags.
+ *
+ * Note that this is only half a solution to the problem though: not only udev/net_id gets updated all the time, the
+ * kernel gets too. And thus a kernel that previously didn't expose some sysfs attribute we look for might eventually
+ * do, and thus affect our naming scheme too. Thus, enforcing a naming scheme will make interfacing more stable across
+ * OS versions, but not fully stabilize them. */
+typedef enum NamingSchemeFlags {
+ /* First, the individual features */
+ NAMING_SR_IOV_V = 1 << 0, /* Use "v" suffix for SR-IOV, see 609948c7043a40008b8299529c978ed8e11de8f6*/
+ NAMING_NPAR_ARI = 1 << 1, /* Use NPAR "ARI", see 6bc04997b6eab35d1cb9fa73889892702c27be09 */
+ NAMING_INFINIBAND = 1 << 2, /* Use "ib" prefix for infiniband, see 938d30aa98df887797c9e05074a562ddacdcdf5e */
+ NAMING_ZERO_ACPI_INDEX = 1 << 3, /* Allow zero acpi_index field, see d81186ef4f6a888a70f20a1e73a812d6acb9e22f */
+ NAMING_ALLOW_RERENAMES = 1 << 4, /* Allow re-renaming of devices, see #9006 */
+
+ /* And now the masks that combine the features above */
+ NAMING_V238 = 0,
+ NAMING_V239 = NAMING_V238 | NAMING_SR_IOV_V | NAMING_NPAR_ARI,
+ NAMING_V240 = NAMING_V239 | NAMING_INFINIBAND | NAMING_ZERO_ACPI_INDEX | NAMING_ALLOW_RERENAMES,
+
+ _NAMING_SCHEME_FLAGS_INVALID = -1,
+} NamingSchemeFlags;
+
+typedef struct NamingScheme {
+ const char *name;
+ NamingSchemeFlags flags;
+} NamingScheme;
+
+const NamingScheme* naming_scheme(void);
+
+static inline bool naming_scheme_has(NamingSchemeFlags flags) {
+ return FLAGS_SET(naming_scheme()->flags, flags);
+}
diff --git a/src/udev/scsi_id/scsi_id.c b/src/udev/scsi_id/scsi_id.c
index e94f2946f9..2698cdd82f 100644
--- a/src/udev/scsi_id/scsi_id.c
+++ b/src/udev/scsi_id/scsi_id.c
@@ -18,6 +18,7 @@
#include <unistd.h>
#include "alloc-util.h"
+#include "build.h"
#include "fd-util.h"
#include "libudev-util.h"
#include "scsi_id.h"
@@ -370,7 +371,7 @@ static int set_options(int argc, char **argv,
break;
case 'V':
- printf("%s\n", PACKAGE_VERSION);
+ printf("%s\n", GIT_VERSION);
exit(EXIT_SUCCESS);
case 'x':
diff --git a/src/udev/udev-builtin-blkid.c b/src/udev/udev-builtin-blkid.c
index df0f95461d..69d6c4bbee 100644
--- a/src/udev/udev-builtin-blkid.c
+++ b/src/udev/udev-builtin-blkid.c
@@ -240,7 +240,7 @@ static int builtin_blkid(sd_device *dev, int argc, char *argv[], bool test) {
if (r < 0)
return log_device_error_errno(dev, r, "Failed to parse '%s' as an integer: %m", optarg);
if (offset < 0)
- return log_device_error_errno(dev, -ERANGE, "Invalid offset %"PRIi64": %m", offset);
+ return log_device_error_errno(dev, SYNTHETIC_ERRNO(ERANGE), "Invalid offset %"PRIi64": %m", offset);
break;
case 'R':
noraid = true;
diff --git a/src/udev/udev-builtin-btrfs.c b/src/udev/udev-builtin-btrfs.c
index 85dba3d099..956be59afb 100644
--- a/src/udev/udev-builtin-btrfs.c
+++ b/src/udev/udev-builtin-btrfs.c
@@ -18,7 +18,7 @@ static int builtin_btrfs(sd_device *dev, int argc, char *argv[], bool test) {
int r;
if (argc != 3 || !streq(argv[1], "ready"))
- return log_device_error_errno(dev, EINVAL, "Invalid arguments");
+ return log_device_error_errno(dev, SYNTHETIC_ERRNO(EINVAL), "Invalid arguments");
fd = open("/dev/btrfs-control", O_RDWR|O_CLOEXEC);
if (fd < 0)
diff --git a/src/udev/udev-builtin-hwdb.c b/src/udev/udev-builtin-hwdb.c
index ccad98e892..225e0265a4 100644
--- a/src/udev/udev-builtin-hwdb.c
+++ b/src/udev/udev-builtin-hwdb.c
@@ -165,7 +165,7 @@ static int builtin_hwdb(sd_device *dev, int argc, char *argv[], bool test) {
if (r < 0)
return log_device_debug_errno(dev, r, "Failed to lookup hwdb: %m");
if (r == 0)
- return log_device_debug_errno(dev, ENOENT, "No entry found from hwdb: %m");
+ return log_device_debug_errno(dev, SYNTHETIC_ERRNO(ENODATA), "No entry found from hwdb.");
return r;
}
@@ -180,7 +180,7 @@ static int builtin_hwdb(sd_device *dev, int argc, char *argv[], bool test) {
if (r < 0)
return log_device_debug_errno(dev, r, "Failed to lookup hwdb: %m");
if (r == 0)
- return log_device_debug_errno(dev, ENOENT, "No entry found from hwdb: %m");
+ return log_device_debug_errno(dev, SYNTHETIC_ERRNO(ENODATA), "No entry found from hwdb.");
return r;
}
diff --git a/src/udev/udev-builtin-input_id.c b/src/udev/udev-builtin-input_id.c
index 13e9f0108d..e3db55b1a9 100644
--- a/src/udev/udev-builtin-input_id.c
+++ b/src/udev/udev-builtin-input_id.c
@@ -42,7 +42,7 @@ static const struct range high_key_blocks[] = {
{ KEY_ALS_TOGGLE, BTN_TRIGGER_HAPPY }
};
-static inline int abs_size_mm(const struct input_absinfo *absinfo) {
+static int abs_size_mm(const struct input_absinfo *absinfo) {
/* Resolution is defined to be in units/mm for ABS_X/Y */
return (absinfo->maximum - absinfo->minimum) / absinfo->resolution;
}
diff --git a/src/udev/udev-builtin-keyboard.c b/src/udev/udev-builtin-keyboard.c
index cb49a17c33..d80cdd26aa 100644
--- a/src/udev/udev-builtin-keyboard.c
+++ b/src/udev/udev-builtin-keyboard.c
@@ -74,7 +74,7 @@ static int map_keycode(sd_device *dev, int fd, int scancode, const char *keycode
/* check if it's a numeric code already */
keycode_num = strtoul(keycode, &endptr, 0);
if (endptr[0] !='\0')
- return log_device_error_errno(dev, EINVAL, "Failed to parse key identifier '%s'", keycode);
+ return log_device_error_errno(dev, SYNTHETIC_ERRNO(EINVAL), "Failed to parse key identifier '%s'", keycode);
}
map.scan = scancode;
@@ -89,7 +89,7 @@ static int map_keycode(sd_device *dev, int fd, int scancode, const char *keycode
return 0;
}
-static inline char* parse_token(const char *current, int32_t *val_out) {
+static char* parse_token(const char *current, int32_t *val_out) {
char *next;
int32_t val;
@@ -152,7 +152,7 @@ static int set_trackpoint_sensitivity(sd_device *dev, const char *value) {
if (r < 0)
return log_device_error_errno(dev, r, "Failed to parse POINTINGSTICK_SENSITIVITY '%s': %m", value);
else if (val_i < 0 || val_i > 255)
- return log_device_error_errno(dev, ERANGE, "POINTINGSTICK_SENSITIVITY %d outside range [0..255]", val_i);
+ return log_device_error_errno(dev, SYNTHETIC_ERRNO(ERANGE), "POINTINGSTICK_SENSITIVITY %d outside range [0..255]", val_i);
xsprintf(val_s, "%d", val_i);
diff --git a/src/udev/udev-builtin-net_id.c b/src/udev/udev-builtin-net_id.c
index 0292c4973c..03b281a771 100644
--- a/src/udev/udev-builtin-net_id.c
+++ b/src/udev/udev-builtin-net_id.c
@@ -106,6 +106,7 @@
#include "fd-util.h"
#include "fileio.h"
#include "fs-util.h"
+#include "naming-scheme.h"
#include "parse-util.h"
#include "proc-cmdline.h"
#include "stdio-util.h"
@@ -116,48 +117,6 @@
#define ONBOARD_INDEX_MAX (16*1024-1)
-/* So here's the deal: net_id is supposed to be an excercise in providing stable names for network devices. However, we
- * also want to keep updating the naming scheme used in future versions of net_id. These two goals of course are
- * contradictory: on one hand we want things to not change and on the other hand we want them to improve. Our way out
- * of this dilemma is to introduce the "naming scheme" concept: each time we improve the naming logic we define a new
- * flag for it. Then, we keep a list of schemes, each identified by a name associated with the flags it implements. Via
- * a kernel command line and environment variable we then allow the user to pick the scheme they want us to follow:
- * installers could "freeze" the used scheme at the moment of installation this way.
- *
- * Developers: each time you tweak the naming logic here, define a new flag below, and condition the tweak with
- * it. Each time we do a release we'll then add a new scheme entry and include all newly defined flags.
- *
- * Note that this is only half a solution to the problem though: not only udev/net_id gets updated all the time, the
- * kernel gets too. And thus a kernel that previously didn't expose some sysfs attribute we look for might eventually
- * do, and thus affect our naming scheme too. Thus, enforcing a naming scheme will make interfacing more stable across
- * OS versions, but not fully stabilize them. */
-typedef enum NamingSchemeFlags {
- /* First, the individual features */
- NAMING_SR_IOV_V = 1 << 0, /* Use "v" suffix for SR-IOV, see 609948c7043a40008b8299529c978ed8e11de8f6*/
- NAMING_NPAR_ARI = 1 << 1, /* Use NPAR "ARI", see 6bc04997b6eab35d1cb9fa73889892702c27be09 */
- NAMING_INFINIBAND = 1 << 2, /* Use "ib" prefix for infiniband, see 938d30aa98df887797c9e05074a562ddacdcdf5e */
- NAMING_ZERO_ACPI_INDEX = 1 << 3, /* Allow zero acpi_index field, see d81186ef4f6a888a70f20a1e73a812d6acb9e22f */
-
- /* And now the masks that combine the features above */
- NAMING_V238 = 0,
- NAMING_V239 = NAMING_V238|NAMING_SR_IOV_V|NAMING_NPAR_ARI,
- NAMING_V240 = NAMING_V239|NAMING_INFINIBAND|NAMING_ZERO_ACPI_INDEX,
-
- _NAMING_SCHEME_FLAGS_INVALID = -1,
-} NamingSchemeFlags;
-
-typedef struct NamingScheme {
- const char *name;
- NamingSchemeFlags flags;
-} NamingScheme;
-
-static const NamingScheme naming_schemes[] = {
- { "v238", NAMING_V238 },
- { "v239", NAMING_V239 },
- { "v240", NAMING_V240 },
- /* … add more schemes here, as the logic to name devices is updated … */
-};
-
enum netname_type{
NET_UNDEF,
NET_PCI,
@@ -193,62 +152,6 @@ struct virtfn_info {
char suffix[IFNAMSIZ];
};
-static const NamingScheme* naming_scheme_from_name(const char *name) {
- size_t i;
-
- if (streq(name, "latest"))
- return naming_schemes + ELEMENTSOF(naming_schemes) - 1;
-
- for (i = 0; i < ELEMENTSOF(naming_schemes); i++)
- if (streq(naming_schemes[i].name, name))
- return naming_schemes + i;
-
- return NULL;
-}
-
-static const NamingScheme* naming_scheme(void) {
- static const NamingScheme *cache = NULL;
- _cleanup_free_ char *buffer = NULL;
- const char *e, *k;
-
- if (cache)
- return cache;
-
- /* Acquire setting from the kernel command line */
- (void) proc_cmdline_get_key("net.naming-scheme", 0, &buffer);
-
- /* Also acquire it from an env var */
- e = getenv("NET_NAMING_SCHEME");
- if (e) {
- if (*e == ':') {
- /* If prefixed with ':' the kernel cmdline takes precedence */
- k = buffer ?: e + 1;
- } else
- k = e; /* Otherwise the env var takes precedence */
- } else
- k = buffer;
-
- if (k) {
- cache = naming_scheme_from_name(k);
- if (cache) {
- log_info("Using interface naming scheme '%s'.", cache->name);
- return cache;
- }
-
- log_warning("Unknown interface naming scheme '%s' requested, ignoring.", k);
- }
-
- cache = naming_scheme_from_name(DEFAULT_NET_NAMING_SCHEME);
- assert(cache);
- log_info("Using default interface naming scheme '%s'.", cache->name);
-
- return cache;
-}
-
-static bool naming_scheme_has(NamingSchemeFlags flags) {
- return FLAGS_SET(naming_scheme()->flags, flags);
-}
-
/* skip intermediate virtio devices */
static sd_device *skip_virtio(sd_device *dev) {
sd_device *parent;
@@ -460,7 +363,7 @@ static int dev_pci_slot(sd_device *dev, struct netnames *names) {
}
}
- /* kernel provided front panel port name for multiple port PCI device */
+ /* kernel provided front panel port name for multi-port PCI device */
(void) sd_device_get_sysattr_value(dev, "phys_port_name", &port_name);
/* compose a name based on the raw kernel's PCI bus, slot numbers */
@@ -478,7 +381,7 @@ static int dev_pci_slot(sd_device *dev, struct netnames *names) {
if (l == 0)
names->pci_path[0] = '\0';
- /* ACPI _SUN — slot user number */
+ /* ACPI _SUN — slot user number */
r = sd_device_new_from_subsystem_sysname(&pci, "subsystem", "pci");
if (r < 0)
return r;
diff --git a/src/udev/udev-builtin-net_setup_link.c b/src/udev/udev-builtin-net_setup_link.c
index c0d3d4aa01..a845dfa5c1 100644
--- a/src/udev/udev-builtin-net_setup_link.c
+++ b/src/udev/udev-builtin-net_setup_link.c
@@ -16,7 +16,7 @@ static int builtin_net_setup_link(sd_device *dev, int argc, char **argv, bool te
int r;
if (argc > 1)
- return log_device_error_errno(dev, EINVAL, "This program takes no arguments.");
+ return log_device_error_errno(dev, SYNTHETIC_ERRNO(EINVAL), "This program takes no arguments.");
r = link_get_driver(ctx, dev, &driver);
if (r >= 0)
diff --git a/src/udev/udev-builtin-path_id.c b/src/udev/udev-builtin-path_id.c
index 94f2740592..7ce1c5644f 100644
--- a/src/udev/udev-builtin-path_id.c
+++ b/src/udev/udev-builtin-path_id.c
@@ -110,7 +110,6 @@ static sd_device *handle_scsi_fibre_channel(sd_device *parent, char **path) {
assert(parent);
assert(path);
-
if (sd_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_target", &targetdev) < 0)
return NULL;
if (sd_device_get_sysname(targetdev, &sysname) < 0)
diff --git a/src/udev/udev-builtin.c b/src/udev/udev-builtin.c
index 3a61be10ca..48ce295a46 100644
--- a/src/udev/udev-builtin.c
+++ b/src/udev/udev-builtin.c
@@ -139,7 +139,7 @@ int udev_builtin_add_property(sd_device *dev, bool test, const char *key, const
key, val ? "=" : "", strempty(val));
if (test)
- printf("%s=%s\n", key, val);
+ printf("%s=%s\n", key, strempty(val));
return 0;
}
diff --git a/src/udev/udev-ctrl.c b/src/udev/udev-ctrl.c
index d90ebb7259..c217815ac6 100644
--- a/src/udev/udev-ctrl.c
+++ b/src/udev/udev-ctrl.c
@@ -213,14 +213,12 @@ static struct udev_ctrl_connection *udev_ctrl_connection_free(struct udev_ctrl_c
DEFINE_TRIVIAL_REF_UNREF_FUNC(struct udev_ctrl_connection, udev_ctrl_connection, udev_ctrl_connection_free);
-static int ctrl_send(struct udev_ctrl *uctrl, enum udev_ctrl_msg_type type, int intval, const char *buf, int timeout) {
- struct udev_ctrl_msg_wire ctrl_msg_wire;
- int err = 0;
-
- memzero(&ctrl_msg_wire, sizeof(struct udev_ctrl_msg_wire));
- strcpy(ctrl_msg_wire.version, "udev-" PACKAGE_VERSION);
- ctrl_msg_wire.magic = UDEV_CTRL_MAGIC;
- ctrl_msg_wire.type = type;
+static int ctrl_send(struct udev_ctrl *uctrl, enum udev_ctrl_msg_type type, int intval, const char *buf, usec_t timeout) {
+ struct udev_ctrl_msg_wire ctrl_msg_wire = {
+ .version = "udev-" STRINGIFY(PROJECT_VERSION),
+ .magic = UDEV_CTRL_MAGIC,
+ .type = type,
+ };
if (buf)
strscpy(ctrl_msg_wire.buf, sizeof(ctrl_msg_wire.buf), buf);
@@ -228,74 +226,64 @@ static int ctrl_send(struct udev_ctrl *uctrl, enum udev_ctrl_msg_type type, int
ctrl_msg_wire.intval = intval;
if (!uctrl->connected) {
- if (connect(uctrl->sock, &uctrl->saddr.sa, uctrl->addrlen) < 0) {
- err = -errno;
- goto out;
- }
+ if (connect(uctrl->sock, &uctrl->saddr.sa, uctrl->addrlen) < 0)
+ return -errno;
uctrl->connected = true;
}
- if (send(uctrl->sock, &ctrl_msg_wire, sizeof(ctrl_msg_wire), 0) < 0) {
- err = -errno;
- goto out;
- }
+ if (send(uctrl->sock, &ctrl_msg_wire, sizeof(ctrl_msg_wire), 0) < 0)
+ return -errno;
/* wait for peer message handling or disconnect */
for (;;) {
- struct pollfd pfd[1];
+ struct pollfd pfd = {
+ .fd = uctrl->sock,
+ .events = POLLIN,
+ };
int r;
- pfd[0].fd = uctrl->sock;
- pfd[0].events = POLLIN;
- r = poll(pfd, 1, timeout * MSEC_PER_SEC);
+ r = poll(&pfd, 1, DIV_ROUND_UP(timeout, USEC_PER_MSEC));
if (r < 0) {
if (errno == EINTR)
continue;
- err = -errno;
- break;
- }
-
- if (r > 0 && pfd[0].revents & POLLERR) {
- err = -EIO;
- break;
+ return -errno;
}
-
if (r == 0)
- err = -ETIMEDOUT;
- break;
+ return -ETIMEDOUT;
+ if (pfd.revents & POLLERR)
+ return -EIO;
+ return 0;
}
-out:
- return err;
}
-int udev_ctrl_send_set_log_level(struct udev_ctrl *uctrl, int priority, int timeout) {
+int udev_ctrl_send_set_log_level(struct udev_ctrl *uctrl, int priority, usec_t timeout) {
return ctrl_send(uctrl, UDEV_CTRL_SET_LOG_LEVEL, priority, NULL, timeout);
}
-int udev_ctrl_send_stop_exec_queue(struct udev_ctrl *uctrl, int timeout) {
+int udev_ctrl_send_stop_exec_queue(struct udev_ctrl *uctrl, usec_t timeout) {
return ctrl_send(uctrl, UDEV_CTRL_STOP_EXEC_QUEUE, 0, NULL, timeout);
}
-int udev_ctrl_send_start_exec_queue(struct udev_ctrl *uctrl, int timeout) {
+int udev_ctrl_send_start_exec_queue(struct udev_ctrl *uctrl, usec_t timeout) {
return ctrl_send(uctrl, UDEV_CTRL_START_EXEC_QUEUE, 0, NULL, timeout);
}
-int udev_ctrl_send_reload(struct udev_ctrl *uctrl, int timeout) {
+int udev_ctrl_send_reload(struct udev_ctrl *uctrl, usec_t timeout) {
return ctrl_send(uctrl, UDEV_CTRL_RELOAD, 0, NULL, timeout);
}
-int udev_ctrl_send_set_env(struct udev_ctrl *uctrl, const char *key, int timeout) {
+int udev_ctrl_send_set_env(struct udev_ctrl *uctrl, const char *key, usec_t timeout) {
return ctrl_send(uctrl, UDEV_CTRL_SET_ENV, 0, key, timeout);
}
-int udev_ctrl_send_set_children_max(struct udev_ctrl *uctrl, int count, int timeout) {
+int udev_ctrl_send_set_children_max(struct udev_ctrl *uctrl, int count, usec_t timeout) {
return ctrl_send(uctrl, UDEV_CTRL_SET_CHILDREN_MAX, count, NULL, timeout);
}
-int udev_ctrl_send_ping(struct udev_ctrl *uctrl, int timeout) {
+int udev_ctrl_send_ping(struct udev_ctrl *uctrl, usec_t timeout) {
return ctrl_send(uctrl, UDEV_CTRL_PING, 0, NULL, timeout);
}
-int udev_ctrl_send_exit(struct udev_ctrl *uctrl, int timeout) {
+int udev_ctrl_send_exit(struct udev_ctrl *uctrl, usec_t timeout) {
return ctrl_send(uctrl, UDEV_CTRL_EXIT, 0, NULL, timeout);
}
diff --git a/src/udev/udev-ctrl.h b/src/udev/udev-ctrl.h
index 87021cb880..8e452a4249 100644
--- a/src/udev/udev-ctrl.h
+++ b/src/udev/udev-ctrl.h
@@ -2,6 +2,7 @@
#pragma once
#include "macro.h"
+#include "time-util.h"
struct udev_ctrl;
struct udev_ctrl *udev_ctrl_new(void);
@@ -10,14 +11,14 @@ int udev_ctrl_enable_receiving(struct udev_ctrl *uctrl);
struct udev_ctrl *udev_ctrl_unref(struct udev_ctrl *uctrl);
int udev_ctrl_cleanup(struct udev_ctrl *uctrl);
int udev_ctrl_get_fd(struct udev_ctrl *uctrl);
-int udev_ctrl_send_set_log_level(struct udev_ctrl *uctrl, int priority, int timeout);
-int udev_ctrl_send_stop_exec_queue(struct udev_ctrl *uctrl, int timeout);
-int udev_ctrl_send_start_exec_queue(struct udev_ctrl *uctrl, int timeout);
-int udev_ctrl_send_reload(struct udev_ctrl *uctrl, int timeout);
-int udev_ctrl_send_ping(struct udev_ctrl *uctrl, int timeout);
-int udev_ctrl_send_exit(struct udev_ctrl *uctrl, int timeout);
-int udev_ctrl_send_set_env(struct udev_ctrl *uctrl, const char *key, int timeout);
-int udev_ctrl_send_set_children_max(struct udev_ctrl *uctrl, int count, int timeout);
+int udev_ctrl_send_set_log_level(struct udev_ctrl *uctrl, int priority, usec_t timeout);
+int udev_ctrl_send_stop_exec_queue(struct udev_ctrl *uctrl, usec_t timeout);
+int udev_ctrl_send_start_exec_queue(struct udev_ctrl *uctrl, usec_t timeout);
+int udev_ctrl_send_reload(struct udev_ctrl *uctrl, usec_t timeout);
+int udev_ctrl_send_ping(struct udev_ctrl *uctrl, usec_t timeout);
+int udev_ctrl_send_exit(struct udev_ctrl *uctrl, usec_t timeout);
+int udev_ctrl_send_set_env(struct udev_ctrl *uctrl, const char *key, usec_t timeout);
+int udev_ctrl_send_set_children_max(struct udev_ctrl *uctrl, int count, usec_t timeout);
struct udev_ctrl_connection;
struct udev_ctrl_connection *udev_ctrl_get_connection(struct udev_ctrl *uctrl);
diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c
index e28d6a5d08..07b7365e3a 100644
--- a/src/udev/udev-event.c
+++ b/src/udev/udev-event.c
@@ -504,38 +504,34 @@ static int on_spawn_timeout_warning(sd_event_source *s, uint64_t usec, void *use
static int on_spawn_sigchld(sd_event_source *s, const siginfo_t *si, void *userdata) {
Spawn *spawn = userdata;
+ int ret = -EIO;
assert(spawn);
switch (si->si_code) {
case CLD_EXITED:
- if (si->si_status == 0) {
+ if (si->si_status == 0)
log_debug("Process '%s' succeeded.", spawn->cmd);
- sd_event_exit(sd_event_source_get_event(s), 0);
-
- return 1;
- }
-
- log_full(spawn->accept_failure ? LOG_DEBUG : LOG_WARNING,
- "Process '%s' failed with exit code %i.", spawn->cmd, si->si_status);
+ else
+ log_full(spawn->accept_failure ? LOG_DEBUG : LOG_WARNING,
+ "Process '%s' failed with exit code %i.", spawn->cmd, si->si_status);
+ ret = si->si_status;
break;
case CLD_KILLED:
case CLD_DUMPED:
- log_warning("Process '%s' terminated by signal %s.", spawn->cmd, signal_to_string(si->si_status));
-
+ log_error("Process '%s' terminated by signal %s.", spawn->cmd, signal_to_string(si->si_status));
break;
default:
log_error("Process '%s' failed due to unknown reason.", spawn->cmd);
}
- sd_event_exit(sd_event_source_get_event(s), -EIO);
-
+ sd_event_exit(sd_event_source_get_event(s), ret);
return 1;
}
static int spawn_wait(Spawn *spawn) {
_cleanup_(sd_event_unrefp) sd_event *e = NULL;
- int r, ret;
+ int r;
assert(spawn);
@@ -570,27 +566,23 @@ static int spawn_wait(Spawn *spawn) {
}
}
- r = sd_event_add_io(e, NULL, spawn->fd_stdout, EPOLLIN, on_spawn_io, spawn);
- if (r < 0)
- return r;
+ if (spawn->fd_stdout >= 0) {
+ r = sd_event_add_io(e, NULL, spawn->fd_stdout, EPOLLIN, on_spawn_io, spawn);
+ if (r < 0)
+ return r;
+ }
- r = sd_event_add_io(e, NULL, spawn->fd_stderr, EPOLLIN, on_spawn_io, spawn);
- if (r < 0)
- return r;
+ if (spawn->fd_stderr >= 0) {
+ r = sd_event_add_io(e, NULL, spawn->fd_stderr, EPOLLIN, on_spawn_io, spawn);
+ if (r < 0)
+ return r;
+ }
r = sd_event_add_child(e, NULL, spawn->pid, WEXITED, on_spawn_sigchld, spawn);
if (r < 0)
return r;
- r = sd_event_loop(e);
- if (r < 0)
- return r;
-
- r = sd_event_get_exit_code(e, &ret);
- if (r < 0)
- return r;
-
- return ret;
+ return sd_event_loop(e);
}
int udev_event_spawn(UdevEvent *event,
@@ -675,12 +667,12 @@ int udev_event_spawn(UdevEvent *event,
};
r = spawn_wait(&spawn);
if (r < 0)
- return log_error_errno(r, "Failed to wait spawned command '%s': %m", cmd);
+ return log_error_errno(r, "Failed to wait for spawned command '%s': %m", cmd);
if (result)
result[spawn.result_len] = '\0';
- return r;
+ return r; /* 0 for success, and positive if the program failed */
}
static int rename_netif(UdevEvent *event) {
@@ -895,7 +887,7 @@ void udev_event_execute_run(UdevEvent *event, usec_t timeout_usec) {
(void) usleep(event->exec_delay_usec);
}
- udev_event_spawn(event, timeout_usec, false, command, NULL, 0);
+ (void) udev_event_spawn(event, timeout_usec, false, command, NULL, 0);
}
}
}
diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c
index c11eb8c1ac..1c00dd1e9e 100644
--- a/src/udev/udev-node.c
+++ b/src/udev/udev-node.c
@@ -181,6 +181,9 @@ static int link_find_prioritized(sd_device *dev, bool add, const char *stackdir,
priority = db_prio;
}
+ if (!target)
+ return -ENOENT;
+
*ret = TAKE_PTR(target);
return 0;
}
@@ -297,7 +300,7 @@ static int node_permissions_apply(sd_device *dev, bool apply,
return log_device_debug_errno(dev, errno, "cannot stat() node '%s' (%m)", devnode);
if (((stats.st_mode & S_IFMT) != (mode & S_IFMT)) || (stats.st_rdev != devnum))
- return log_device_debug_errno(dev, EEXIST, "Found node '%s' with non-matching devnum %s, skip handling",
+ return log_device_debug_errno(dev, SYNTHETIC_ERRNO(EEXIST), "Found node '%s' with non-matching devnum %s, skip handling",
devnode, id_filename);
if (apply) {
diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c
index 53c68d254a..bc9c6c26c5 100644
--- a/src/udev/udev-rules.c
+++ b/src/udev/udev-rules.c
@@ -441,8 +441,8 @@ static void dump_rules(UdevRules *rules) {
dump_token(rules, &rules->tokens[i]);
}
#else
-static inline void dump_token(UdevRules *rules, struct token *token) {}
-static inline void dump_rules(UdevRules *rules) {}
+static void dump_token(UdevRules *rules, struct token *token) {}
+static void dump_rules(UdevRules *rules) {}
#endif /* ENABLE_DEBUG_UDEV */
static int add_token(UdevRules *rules, struct token *token) {
@@ -645,11 +645,13 @@ static int import_program_into_properties(UdevEvent *event,
const char *program) {
char result[UTIL_LINE_SIZE];
char *line;
- int err;
+ int r;
- err = udev_event_spawn(event, timeout_usec, true, program, result, sizeof(result));
- if (err < 0)
- return err;
+ r = udev_event_spawn(event, timeout_usec, false, program, result, sizeof result);
+ if (r < 0)
+ return r;
+ if (r > 0)
+ return -EIO;
line = result;
while (line) {
@@ -831,13 +833,15 @@ static const char *get_key_attribute(char *str) {
return NULL;
}
-static void rule_add_key(struct rule_tmp *rule_tmp, enum token_type type,
- enum operation_type op,
- const char *value, const void *data) {
+static int rule_add_key(struct rule_tmp *rule_tmp, enum token_type type,
+ enum operation_type op,
+ const char *value, const void *data) {
struct token *token = rule_tmp->token + rule_tmp->token_cur;
const char *attr = NULL;
- assert(rule_tmp->token_cur < ELEMENTSOF(rule_tmp->token));
+ if (rule_tmp->token_cur >= ELEMENTSOF(rule_tmp->token))
+ return -E2BIG;
+
memzero(token, sizeof(struct token));
switch (type) {
@@ -968,6 +972,8 @@ static void rule_add_key(struct rule_tmp *rule_tmp, enum token_type type,
token->key.type = type;
token->key.op = op;
rule_tmp->token_cur++;
+
+ return 0;
}
static int sort_token(UdevRules *rules, struct rule_tmp *rule_tmp) {
@@ -1009,6 +1015,7 @@ static int sort_token(UdevRules *rules, struct rule_tmp *rule_tmp) {
#define LOG_RULE_WARNING(fmt, ...) LOG_RULE_FULL(LOG_WARNING, fmt, ##__VA_ARGS__)
#define LOG_RULE_DEBUG(fmt, ...) LOG_RULE_FULL(LOG_DEBUG, fmt, ##__VA_ARGS__)
#define LOG_AND_RETURN(fmt, ...) { LOG_RULE_ERROR(fmt, __VA_ARGS__); return; }
+#define LOG_AND_RETURN_ADD_KEY LOG_AND_RETURN("Temporary rule array too small, aborting event processing with %u items", rule_tmp.token_cur);
static void add_rule(UdevRules *rules, char *line,
const char *filename, unsigned filename_off, unsigned lineno) {
@@ -1018,6 +1025,7 @@ static void add_rule(UdevRules *rules, char *line,
.rules = rules,
.rule.type = TK_RULE,
};
+ int r;
/* the offset in the rule is limited to unsigned short */
if (filename_off < USHRT_MAX)
@@ -1051,26 +1059,26 @@ static void add_rule(UdevRules *rules, char *line,
break;
}
- if (rule_tmp.token_cur >= ELEMENTSOF(rule_tmp.token))
- LOG_AND_RETURN("Temporary rule array too small, aborting event processing with %u items", rule_tmp.token_cur);
-
if (streq(key, "ACTION")) {
if (op > OP_MATCH_MAX)
LOG_AND_RETURN("Invalid %s operation", key);
- rule_add_key(&rule_tmp, TK_M_ACTION, op, value, NULL);
+ if (rule_add_key(&rule_tmp, TK_M_ACTION, op, value, NULL) < 0)
+ LOG_AND_RETURN_ADD_KEY;
} else if (streq(key, "DEVPATH")) {
if (op > OP_MATCH_MAX)
LOG_AND_RETURN("Invalid %s operation", key);
- rule_add_key(&rule_tmp, TK_M_DEVPATH, op, value, NULL);
+ if (rule_add_key(&rule_tmp, TK_M_DEVPATH, op, value, NULL) < 0)
+ LOG_AND_RETURN_ADD_KEY;
} else if (streq(key, "KERNEL")) {
if (op > OP_MATCH_MAX)
LOG_AND_RETURN("Invalid %s operation", key);
- rule_add_key(&rule_tmp, TK_M_KERNEL, op, value, NULL);
+ if (rule_add_key(&rule_tmp, TK_M_KERNEL, op, value, NULL) < 0)
+ LOG_AND_RETURN_ADD_KEY;
} else if (streq(key, "SUBSYSTEM")) {
if (op > OP_MATCH_MAX)
@@ -1081,15 +1089,18 @@ static void add_rule(UdevRules *rules, char *line,
if (!streq(value, "subsystem"))
LOG_RULE_WARNING("'%s' must be specified as 'subsystem'; please fix", value);
- rule_add_key(&rule_tmp, TK_M_SUBSYSTEM, op, "subsystem|class|bus", NULL);
+ r = rule_add_key(&rule_tmp, TK_M_SUBSYSTEM, op, "subsystem|class|bus", NULL);
} else
- rule_add_key(&rule_tmp, TK_M_SUBSYSTEM, op, value, NULL);
+ r = rule_add_key(&rule_tmp, TK_M_SUBSYSTEM, op, value, NULL);
+ if (r < 0)
+ LOG_AND_RETURN_ADD_KEY;
} else if (streq(key, "DRIVER")) {
if (op > OP_MATCH_MAX)
LOG_AND_RETURN("Invalid %s operation", key);
- rule_add_key(&rule_tmp, TK_M_DRIVER, op, value, NULL);
+ if (rule_add_key(&rule_tmp, TK_M_DRIVER, op, value, NULL) < 0)
+ LOG_AND_RETURN_ADD_KEY;
} else if (startswith(key, "ATTR{")) {
attr = get_key_attribute(key + STRLEN("ATTR"));
@@ -1100,9 +1111,11 @@ static void add_rule(UdevRules *rules, char *line,
LOG_AND_RETURN("Invalid %s operation", "ATTR");
if (op < OP_MATCH_MAX)
- rule_add_key(&rule_tmp, TK_M_ATTR, op, value, attr);
+ r = rule_add_key(&rule_tmp, TK_M_ATTR, op, value, attr);
else
- rule_add_key(&rule_tmp, TK_A_ATTR, op, value, attr);
+ r = rule_add_key(&rule_tmp, TK_A_ATTR, op, value, attr);
+ if (r < 0)
+ LOG_AND_RETURN_ADD_KEY;
} else if (startswith(key, "SYSCTL{")) {
attr = get_key_attribute(key + STRLEN("SYSCTL"));
@@ -1113,9 +1126,11 @@ static void add_rule(UdevRules *rules, char *line,
LOG_AND_RETURN("Invalid %s operation", "ATTR");
if (op < OP_MATCH_MAX)
- rule_add_key(&rule_tmp, TK_M_SYSCTL, op, value, attr);
+ r = rule_add_key(&rule_tmp, TK_M_SYSCTL, op, value, attr);
else
- rule_add_key(&rule_tmp, TK_A_SYSCTL, op, value, attr);
+ r = rule_add_key(&rule_tmp, TK_A_SYSCTL, op, value, attr);
+ if (r < 0)
+ LOG_AND_RETURN_ADD_KEY;
} else if (startswith(key, "SECLABEL{")) {
attr = get_key_attribute(key + STRLEN("SECLABEL"));
@@ -1125,25 +1140,29 @@ static void add_rule(UdevRules *rules, char *line,
if (op == OP_REMOVE)
LOG_AND_RETURN("Invalid %s operation", "SECLABEL");
- rule_add_key(&rule_tmp, TK_A_SECLABEL, op, value, attr);
+ if (rule_add_key(&rule_tmp, TK_A_SECLABEL, op, value, attr) < 0)
+ LOG_AND_RETURN_ADD_KEY;
} else if (streq(key, "KERNELS")) {
if (op > OP_MATCH_MAX)
LOG_AND_RETURN("Invalid %s operation", key);
- rule_add_key(&rule_tmp, TK_M_KERNELS, op, value, NULL);
+ if (rule_add_key(&rule_tmp, TK_M_KERNELS, op, value, NULL) < 0)
+ LOG_AND_RETURN_ADD_KEY;
} else if (streq(key, "SUBSYSTEMS")) {
if (op > OP_MATCH_MAX)
LOG_AND_RETURN("Invalid %s operation", key);
- rule_add_key(&rule_tmp, TK_M_SUBSYSTEMS, op, value, NULL);
+ if (rule_add_key(&rule_tmp, TK_M_SUBSYSTEMS, op, value, NULL) < 0)
+ LOG_AND_RETURN_ADD_KEY;
} else if (streq(key, "DRIVERS")) {
if (op > OP_MATCH_MAX)
LOG_AND_RETURN("Invalid %s operation", key);
- rule_add_key(&rule_tmp, TK_M_DRIVERS, op, value, NULL);
+ if (rule_add_key(&rule_tmp, TK_M_DRIVERS, op, value, NULL) < 0)
+ LOG_AND_RETURN_ADD_KEY;
} else if (startswith(key, "ATTRS{")) {
if (op > OP_MATCH_MAX)
@@ -1157,13 +1176,15 @@ static void add_rule(UdevRules *rules, char *line,
LOG_RULE_WARNING("'device' link may not be available in future kernels; please fix");
if (strstr(attr, "../"))
LOG_RULE_WARNING("Direct reference to parent sysfs directory, may break in future kernels; please fix");
- rule_add_key(&rule_tmp, TK_M_ATTRS, op, value, attr);
+ if (rule_add_key(&rule_tmp, TK_M_ATTRS, op, value, attr) < 0)
+ LOG_AND_RETURN_ADD_KEY;
} else if (streq(key, "TAGS")) {
if (op > OP_MATCH_MAX)
LOG_AND_RETURN("Invalid %s operation", key);
- rule_add_key(&rule_tmp, TK_M_TAGS, op, value, NULL);
+ if (rule_add_key(&rule_tmp, TK_M_TAGS, op, value, NULL) < 0)
+ LOG_AND_RETURN_ADD_KEY;
} else if (startswith(key, "ENV{")) {
attr = get_key_attribute(key + STRLEN("ENV"));
@@ -1174,7 +1195,7 @@ static void add_rule(UdevRules *rules, char *line,
LOG_AND_RETURN("Invalid %s operation", "ENV");
if (op < OP_MATCH_MAX)
- rule_add_key(&rule_tmp, TK_M_ENV, op, value, attr);
+ r = rule_add_key(&rule_tmp, TK_M_ENV, op, value, attr);
else {
if (STR_IN_SET(attr,
"ACTION",
@@ -1190,26 +1211,32 @@ static void add_rule(UdevRules *rules, char *line,
"TAGS"))
LOG_AND_RETURN("Invalid ENV attribute, '%s' cannot be set", attr);
- rule_add_key(&rule_tmp, TK_A_ENV, op, value, attr);
+ r = rule_add_key(&rule_tmp, TK_A_ENV, op, value, attr);
}
+ if (r < 0)
+ LOG_AND_RETURN_ADD_KEY;
} else if (streq(key, "TAG")) {
if (op < OP_MATCH_MAX)
- rule_add_key(&rule_tmp, TK_M_TAG, op, value, NULL);
+ r = rule_add_key(&rule_tmp, TK_M_TAG, op, value, NULL);
else
- rule_add_key(&rule_tmp, TK_A_TAG, op, value, NULL);
+ r = rule_add_key(&rule_tmp, TK_A_TAG, op, value, NULL);
+ if (r < 0)
+ LOG_AND_RETURN_ADD_KEY;
} else if (streq(key, "PROGRAM")) {
if (op == OP_REMOVE)
LOG_AND_RETURN("Invalid %s operation", key);
- rule_add_key(&rule_tmp, TK_M_PROGRAM, op, value, NULL);
+ if (rule_add_key(&rule_tmp, TK_M_PROGRAM, op, value, NULL) < 0)
+ LOG_AND_RETURN_ADD_KEY;
} else if (streq(key, "RESULT")) {
if (op > OP_MATCH_MAX)
LOG_AND_RETURN("Invalid %s operation", key);
- rule_add_key(&rule_tmp, TK_M_RESULT, op, value, NULL);
+ if (rule_add_key(&rule_tmp, TK_M_RESULT, op, value, NULL) < 0)
+ LOG_AND_RETURN_ADD_KEY;
} else if (startswith(key, "IMPORT")) {
attr = get_key_attribute(key + STRLEN("IMPORT"));
@@ -1227,28 +1254,34 @@ static void add_rule(UdevRules *rules, char *line,
if (cmd >= 0) {
LOG_RULE_DEBUG("IMPORT found builtin '%s', replacing", value);
- rule_add_key(&rule_tmp, TK_M_IMPORT_BUILTIN, op, value, &cmd);
+ if (rule_add_key(&rule_tmp, TK_M_IMPORT_BUILTIN, op, value, &cmd) < 0)
+ LOG_AND_RETURN_ADD_KEY;
continue;
}
}
- rule_add_key(&rule_tmp, TK_M_IMPORT_PROG, op, value, NULL);
+ r = rule_add_key(&rule_tmp, TK_M_IMPORT_PROG, op, value, NULL);
} else if (streq(attr, "builtin")) {
const enum udev_builtin_cmd cmd = udev_builtin_lookup(value);
- if (cmd < 0)
- LOG_RULE_WARNING("IMPORT{builtin} '%s' unknown", value);
- else
- rule_add_key(&rule_tmp, TK_M_IMPORT_BUILTIN, op, value, &cmd);
+ if (cmd < 0) {
+ LOG_RULE_WARNING("IMPORT{builtin} '%s' unknown, ignoring", value);
+ continue;
+ } else
+ r = rule_add_key(&rule_tmp, TK_M_IMPORT_BUILTIN, op, value, &cmd);
} else if (streq(attr, "file"))
- rule_add_key(&rule_tmp, TK_M_IMPORT_FILE, op, value, NULL);
+ r = rule_add_key(&rule_tmp, TK_M_IMPORT_FILE, op, value, NULL);
else if (streq(attr, "db"))
- rule_add_key(&rule_tmp, TK_M_IMPORT_DB, op, value, NULL);
+ r = rule_add_key(&rule_tmp, TK_M_IMPORT_DB, op, value, NULL);
else if (streq(attr, "cmdline"))
- rule_add_key(&rule_tmp, TK_M_IMPORT_CMDLINE, op, value, NULL);
+ r = rule_add_key(&rule_tmp, TK_M_IMPORT_CMDLINE, op, value, NULL);
else if (streq(attr, "parent"))
- rule_add_key(&rule_tmp, TK_M_IMPORT_PARENT, op, value, NULL);
- else
+ r = rule_add_key(&rule_tmp, TK_M_IMPORT_PARENT, op, value, NULL);
+ else {
LOG_RULE_ERROR("Ignoring unknown %s{} type '%s'", "IMPORT", attr);
+ continue;
+ }
+ if (r < 0)
+ LOG_AND_RETURN_ADD_KEY;
} else if (startswith(key, "TEST")) {
mode_t mode = 0;
@@ -1259,9 +1292,11 @@ static void add_rule(UdevRules *rules, char *line,
attr = get_key_attribute(key + STRLEN("TEST"));
if (attr) {
mode = strtol(attr, NULL, 8);
- rule_add_key(&rule_tmp, TK_M_TEST, op, value, &mode);
+ r = rule_add_key(&rule_tmp, TK_M_TEST, op, value, &mode);
} else
- rule_add_key(&rule_tmp, TK_M_TEST, op, value, NULL);
+ r = rule_add_key(&rule_tmp, TK_M_TEST, op, value, NULL);
+ if (r < 0)
+ LOG_AND_RETURN_ADD_KEY;
} else if (startswith(key, "RUN")) {
attr = get_key_attribute(key + STRLEN("RUN"));
@@ -1273,16 +1308,21 @@ static void add_rule(UdevRules *rules, char *line,
if (streq(attr, "builtin")) {
const enum udev_builtin_cmd cmd = udev_builtin_lookup(value);
- if (cmd < 0)
- LOG_RULE_ERROR("RUN{builtin}: '%s' unknown", value);
- else
- rule_add_key(&rule_tmp, TK_A_RUN_BUILTIN, op, value, &cmd);
+ if (cmd < 0) {
+ LOG_RULE_ERROR("RUN{builtin}: '%s' unknown, ignoring", value);
+ continue;
+ } else
+ r = rule_add_key(&rule_tmp, TK_A_RUN_BUILTIN, op, value, &cmd);
} else if (streq(attr, "program")) {
const enum udev_builtin_cmd cmd = _UDEV_BUILTIN_MAX;
- rule_add_key(&rule_tmp, TK_A_RUN_PROGRAM, op, value, &cmd);
- } else
+ r = rule_add_key(&rule_tmp, TK_A_RUN_PROGRAM, op, value, &cmd);
+ } else {
LOG_RULE_ERROR("Ignoring unknown %s{} type '%s'", "RUN", attr);
+ continue;
+ }
+ if (r < 0)
+ LOG_AND_RETURN_ADD_KEY;
} else if (streq(key, "LABEL")) {
if (op == OP_REMOVE)
@@ -1294,14 +1334,15 @@ static void add_rule(UdevRules *rules, char *line,
if (op == OP_REMOVE)
LOG_AND_RETURN("Invalid %s operation", key);
- rule_add_key(&rule_tmp, TK_A_GOTO, 0, value, NULL);
+ if (rule_add_key(&rule_tmp, TK_A_GOTO, 0, value, NULL) < 0)
+ LOG_AND_RETURN_ADD_KEY;
} else if (startswith(key, "NAME")) {
if (op == OP_REMOVE)
LOG_AND_RETURN("Invalid %s operation", key);
if (op < OP_MATCH_MAX)
- rule_add_key(&rule_tmp, TK_M_NAME, op, value, NULL);
+ r = rule_add_key(&rule_tmp, TK_M_NAME, op, value, NULL);
else {
if (streq(value, "%k")) {
LOG_RULE_WARNING("NAME=\"%%k\" is ignored, because it breaks kernel supplied names; please remove");
@@ -1311,8 +1352,10 @@ static void add_rule(UdevRules *rules, char *line,
LOG_RULE_DEBUG("NAME=\"\" is ignored, because udev will not delete any device nodes; please remove");
continue;
}
- rule_add_key(&rule_tmp, TK_A_NAME, op, value, NULL);
+ r = rule_add_key(&rule_tmp, TK_A_NAME, op, value, NULL);
}
+ if (r < 0)
+ LOG_AND_RETURN_ADD_KEY;
rule_tmp.rule.rule.can_set_name = true;
} else if (streq(key, "SYMLINK")) {
@@ -1320,9 +1363,11 @@ static void add_rule(UdevRules *rules, char *line,
LOG_AND_RETURN("Invalid %s operation", key);
if (op < OP_MATCH_MAX)
- rule_add_key(&rule_tmp, TK_M_DEVLINK, op, value, NULL);
+ r = rule_add_key(&rule_tmp, TK_M_DEVLINK, op, value, NULL);
else
- rule_add_key(&rule_tmp, TK_A_DEVLINK, op, value, NULL);
+ r = rule_add_key(&rule_tmp, TK_A_DEVLINK, op, value, NULL);
+ if (r < 0)
+ LOG_AND_RETURN_ADD_KEY;
rule_tmp.rule.rule.can_set_name = true;
} else if (streq(key, "OWNER")) {
@@ -1334,12 +1379,18 @@ static void add_rule(UdevRules *rules, char *line,
uid = strtoul(value, &endptr, 10);
if (endptr[0] == '\0')
- rule_add_key(&rule_tmp, TK_A_OWNER_ID, op, NULL, &uid);
+ r = rule_add_key(&rule_tmp, TK_A_OWNER_ID, op, NULL, &uid);
else if (rules->resolve_name_timing == RESOLVE_NAME_EARLY && !strchr("$%", value[0])) {
uid = add_uid(rules, value);
- rule_add_key(&rule_tmp, TK_A_OWNER_ID, op, NULL, &uid);
+ r = rule_add_key(&rule_tmp, TK_A_OWNER_ID, op, NULL, &uid);
} else if (rules->resolve_name_timing != RESOLVE_NAME_NEVER)
- rule_add_key(&rule_tmp, TK_A_OWNER, op, value, NULL);
+ r = rule_add_key(&rule_tmp, TK_A_OWNER, op, value, NULL);
+ else {
+ LOG_RULE_ERROR("Invalid %s operation", key);
+ continue;
+ }
+ if (r < 0)
+ LOG_AND_RETURN_ADD_KEY;
rule_tmp.rule.rule.can_set_name = true;
@@ -1352,12 +1403,18 @@ static void add_rule(UdevRules *rules, char *line,
gid = strtoul(value, &endptr, 10);
if (endptr[0] == '\0')
- rule_add_key(&rule_tmp, TK_A_GROUP_ID, op, NULL, &gid);
+ r = rule_add_key(&rule_tmp, TK_A_GROUP_ID, op, NULL, &gid);
else if ((rules->resolve_name_timing == RESOLVE_NAME_EARLY) && !strchr("$%", value[0])) {
gid = add_gid(rules, value);
- rule_add_key(&rule_tmp, TK_A_GROUP_ID, op, NULL, &gid);
+ r = rule_add_key(&rule_tmp, TK_A_GROUP_ID, op, NULL, &gid);
} else if (rules->resolve_name_timing != RESOLVE_NAME_NEVER)
- rule_add_key(&rule_tmp, TK_A_GROUP, op, value, NULL);
+ r = rule_add_key(&rule_tmp, TK_A_GROUP, op, value, NULL);
+ else {
+ LOG_RULE_ERROR("Invalid %s operation", key);
+ continue;
+ }
+ if (r < 0)
+ LOG_AND_RETURN_ADD_KEY;
rule_tmp.rule.rule.can_set_name = true;
@@ -1370,9 +1427,12 @@ static void add_rule(UdevRules *rules, char *line,
mode = strtol(value, &endptr, 8);
if (endptr[0] == '\0')
- rule_add_key(&rule_tmp, TK_A_MODE_ID, op, NULL, &mode);
+ r = rule_add_key(&rule_tmp, TK_A_MODE_ID, op, NULL, &mode);
else
- rule_add_key(&rule_tmp, TK_A_MODE, op, value, NULL);
+ r = rule_add_key(&rule_tmp, TK_A_MODE, op, value, NULL);
+ if (r < 0)
+ LOG_AND_RETURN_ADD_KEY;
+
rule_tmp.rule.rule.can_set_name = true;
} else if (streq(key, "OPTIONS")) {
@@ -1385,37 +1445,48 @@ static void add_rule(UdevRules *rules, char *line,
if (pos) {
int prio = atoi(pos + STRLEN("link_priority="));
- rule_add_key(&rule_tmp, TK_A_DEVLINK_PRIO, op, NULL, &prio);
+ if (rule_add_key(&rule_tmp, TK_A_DEVLINK_PRIO, op, NULL, &prio) < 0)
+ LOG_AND_RETURN_ADD_KEY;
}
pos = strstr(value, "string_escape=");
if (pos) {
pos += STRLEN("string_escape=");
if (startswith(pos, "none"))
- rule_add_key(&rule_tmp, TK_A_STRING_ESCAPE_NONE, op, NULL, NULL);
+ r = rule_add_key(&rule_tmp, TK_A_STRING_ESCAPE_NONE, op, NULL, NULL);
else if (startswith(pos, "replace"))
- rule_add_key(&rule_tmp, TK_A_STRING_ESCAPE_REPLACE, op, NULL, NULL);
+ r = rule_add_key(&rule_tmp, TK_A_STRING_ESCAPE_REPLACE, op, NULL, NULL);
+ else {
+ LOG_RULE_ERROR("OPTIONS: unknown string_escape mode '%s', ignoring", pos);
+ r = 0;
+ }
+ if (r < 0)
+ LOG_AND_RETURN_ADD_KEY;
}
pos = strstr(value, "db_persist");
if (pos)
- rule_add_key(&rule_tmp, TK_A_DB_PERSIST, op, NULL, NULL);
+ if (rule_add_key(&rule_tmp, TK_A_DB_PERSIST, op, NULL, NULL) < 0)
+ LOG_AND_RETURN_ADD_KEY;
pos = strstr(value, "nowatch");
if (pos) {
static const int zero = 0;
- rule_add_key(&rule_tmp, TK_A_INOTIFY_WATCH, op, NULL, &zero);
+ if (rule_add_key(&rule_tmp, TK_A_INOTIFY_WATCH, op, NULL, &zero) < 0)
+ LOG_AND_RETURN_ADD_KEY;
} else {
static const int one = 1;
pos = strstr(value, "watch");
if (pos)
- rule_add_key(&rule_tmp, TK_A_INOTIFY_WATCH, op, NULL, &one);
+ if (rule_add_key(&rule_tmp, TK_A_INOTIFY_WATCH, op, NULL, &one) < 0)
+ LOG_AND_RETURN_ADD_KEY;
}
pos = strstr(value, "static_node=");
if (pos) {
pos += STRLEN("static_node=");
- rule_add_key(&rule_tmp, TK_A_STATIC_NODE, op, pos, NULL);
+ if (rule_add_key(&rule_tmp, TK_A_STATIC_NODE, op, pos, NULL) < 0)
+ LOG_AND_RETURN_ADD_KEY;
rule_tmp.rule.rule.has_static_node = true;
}
@@ -1959,7 +2030,7 @@ int udev_rules_apply_to_event(
rules_str(rules, rule->rule.filename_off),
rule->rule.filename_line);
- if (udev_event_spawn(event, timeout_usec, true, program, result, sizeof(result)) < 0) {
+ if (udev_event_spawn(event, timeout_usec, true, program, result, sizeof(result)) != 0) {
if (cur->key.op != OP_NOMATCH)
goto nomatch;
} else {
@@ -2229,13 +2300,12 @@ int udev_rules_apply_to_event(
r = hashmap_put(event->seclabel_list, name, label);
if (r < 0)
return log_oom();
-
- name = label = NULL;
-
log_device_debug(dev, "SECLABEL{%s}='%s' %s:%u",
name, label,
rules_str(rules, rule->rule.filename_off),
rule->rule.filename_line);
+ name = label = NULL;
+
break;
}
case TK_A_ENV: {
diff --git a/src/udev/udev.pc.in b/src/udev/udev.pc.in
index e384a6f7c9..5acbb2d01a 100644
--- a/src/udev/udev.pc.in
+++ b/src/udev/udev.pc.in
@@ -1,5 +1,5 @@
Name: udev
Description: udev
-Version: @PACKAGE_VERSION@
+Version: @PROJECT_VERSION@
udevdir=@udevlibexecdir@
diff --git a/src/udev/udevadm-control.c b/src/udev/udevadm-control.c
index d9320418cf..7cfc4c929d 100644
--- a/src/udev/udevadm-control.c
+++ b/src/udev/udevadm-control.c
@@ -26,6 +26,7 @@
#include "udevadm.h"
#include "udev-ctrl.h"
#include "util.h"
+#include "virt.h"
static int help(void) {
printf("%s control OPTION\n\n"
@@ -39,6 +40,7 @@ static int help(void) {
" -R --reload Reload rules and databases\n"
" -p --property=KEY=VALUE Set a global property for all events\n"
" -m --children-max=N Maximum number of children\n"
+ " --ping Wait for udev to respond to a ping message\n"
" -t --timeout=SECONDS Maximum time to block for a reply\n"
, program_invocation_short_name);
@@ -47,22 +49,27 @@ static int help(void) {
int control_main(int argc, char *argv[], void *userdata) {
_cleanup_(udev_ctrl_unrefp) struct udev_ctrl *uctrl = NULL;
- int timeout = 60;
+ usec_t timeout = 60 * USEC_PER_SEC;
int c, r;
+ enum {
+ ARG_PING = 0x100,
+ };
+
static const struct option options[] = {
- { "exit", no_argument, NULL, 'e' },
- { "log-priority", required_argument, NULL, 'l' },
- { "stop-exec-queue", no_argument, NULL, 's' },
- { "start-exec-queue", no_argument, NULL, 'S' },
- { "reload", no_argument, NULL, 'R' },
- { "reload-rules", no_argument, NULL, 'R' }, /* alias for -R */
- { "property", required_argument, NULL, 'p' },
- { "env", required_argument, NULL, 'p' }, /* alias for -p */
- { "children-max", required_argument, NULL, 'm' },
- { "timeout", required_argument, NULL, 't' },
- { "version", no_argument, NULL, 'V' },
- { "help", no_argument, NULL, 'h' },
+ { "exit", no_argument, NULL, 'e' },
+ { "log-priority", required_argument, NULL, 'l' },
+ { "stop-exec-queue", no_argument, NULL, 's' },
+ { "start-exec-queue", no_argument, NULL, 'S' },
+ { "reload", no_argument, NULL, 'R' },
+ { "reload-rules", no_argument, NULL, 'R' }, /* alias for -R */
+ { "property", required_argument, NULL, 'p' },
+ { "env", required_argument, NULL, 'p' }, /* alias for -p */
+ { "children-max", required_argument, NULL, 'm' },
+ { "ping", no_argument, NULL, ARG_PING },
+ { "timeout", required_argument, NULL, 't' },
+ { "version", no_argument, NULL, 'V' },
+ { "help", no_argument, NULL, 'h' },
{}
};
@@ -70,12 +77,18 @@ int control_main(int argc, char *argv[], void *userdata) {
if (r < 0)
return r;
+ if (running_in_chroot() > 0) {
+ log_info("Running in chroot, ignoring request.");
+ return 0;
+ }
+
if (argc <= 1)
- log_error("Option missing");
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "This command expects one or more options.");
uctrl = udev_ctrl_new();
if (!uctrl)
- return -ENOMEM;
+ return log_oom();
while ((c = getopt_long(argc, argv, "el:sSRp:m:t:Vh", options, NULL)) >= 0)
switch (c) {
@@ -109,10 +122,9 @@ int control_main(int argc, char *argv[], void *userdata) {
return r;
break;
case 'p':
- if (!strchr(optarg, '=')) {
- log_error("expect <KEY>=<value> instead of '%s'", optarg);
- return -EINVAL;
- }
+ if (!strchr(optarg, '='))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "expect <KEY>=<value> instead of '%s'", optarg);
+
r = udev_ctrl_send_set_env(uctrl, optarg, timeout);
if (r < 0)
return r;
@@ -129,19 +141,16 @@ int control_main(int argc, char *argv[], void *userdata) {
return r;
break;
}
- case 't': {
- usec_t s;
-
- r = parse_sec(optarg, &s);
+ case ARG_PING:
+ r = udev_ctrl_send_ping(uctrl, timeout);
if (r < 0)
- return log_error_errno(r, "Failed to parse timeout value '%s'.", optarg);
-
- if (DIV_ROUND_UP(s, USEC_PER_SEC) > INT_MAX)
- log_error("Timeout value is out of range, ignoring.");
- else
- timeout = s != USEC_INFINITY ? (int) DIV_ROUND_UP(s, USEC_PER_SEC) : INT_MAX;
+ return log_error_errno(r, "Failed to connect to udev daemon: %m");
+ break;
+ case 't':
+ r = parse_sec(optarg, &timeout);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse timeout value '%s': %m", optarg);
break;
- }
case 'V':
return print_version();
case 'h':
@@ -152,13 +161,9 @@ int control_main(int argc, char *argv[], void *userdata) {
assert_not_reached("Unknown option.");
}
- if (optind < argc) {
- log_error("Extraneous argument: %s", argv[optind]);
- return -EINVAL;
- } else if (optind == 1) {
- log_error("Option missing");
- return -EINVAL;
- }
+ if (optind < argc)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Extraneous argument: %s", argv[optind]);
return 0;
}
diff --git a/src/udev/udevadm-info.c b/src/udev/udevadm-info.c
index d141bc74b2..ebd15d384a 100644
--- a/src/udev/udevadm-info.c
+++ b/src/udev/udevadm-info.c
@@ -61,12 +61,15 @@ static bool skip_attribute(const char *name) {
static void print_all_attributes(sd_device *device, const char *key) {
const char *name, *value;
- FOREACH_DEVICE_PROPERTY(device, name, value) {
+ FOREACH_DEVICE_SYSATTR(device, name) {
size_t len;
if (skip_attribute(name))
continue;
+ if (sd_device_get_sysattr_value(device, name, &value) < 0)
+ continue;
+
/* skip any values that look like a path */
if (value[0] == '/')
continue;
@@ -387,10 +390,8 @@ int info_main(int argc, char *argv[], void *userdata) {
query = QUERY_PATH;
else if (streq(optarg, "all"))
query = QUERY_ALL;
- else {
- log_error("unknown query type");
- return -EINVAL;
- }
+ else
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "unknown query type");
break;
case 'r':
arg_root = true;
@@ -413,6 +414,7 @@ int info_main(int argc, char *argv[], void *userdata) {
arg_export = true;
break;
case 'P':
+ arg_export = true;
arg_export_prefix = optarg;
break;
case 'V':
@@ -425,7 +427,6 @@ int info_main(int argc, char *argv[], void *userdata) {
assert_not_reached("Unknown option");
}
-
if (action == ACTION_DEVICE_ID_FILE) {
if (argv[optind])
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
diff --git a/src/udev/udevadm-monitor.c b/src/udev/udevadm-monitor.c
index f7737d0790..3dde3f338a 100644
--- a/src/udev/udevadm-monitor.c
+++ b/src/udev/udevadm-monitor.c
@@ -17,6 +17,7 @@
#include "signal-util.h"
#include "string-util.h"
#include "udevadm.h"
+#include "virt.h"
static bool arg_show_property = false;
static bool arg_print_kernel = false;
@@ -143,11 +144,11 @@ static int parse_argv(int argc, char *argv[]) {
slash = strchr(optarg, '/');
if (slash) {
- devtype = strdup(devtype + 1);
+ devtype = strdup(slash + 1);
if (!devtype)
return -ENOMEM;
- subsystem = strndup(optarg, devtype - optarg);
+ subsystem = strndup(optarg, slash - optarg);
} else
subsystem = strdup(optarg);
@@ -210,6 +211,11 @@ int monitor_main(int argc, char *argv[], void *userdata) {
if (r <= 0)
goto finalize;
+ if (running_in_chroot() > 0) {
+ log_info("Running in chroot, ignoring request.");
+ return 0;
+ }
+
/* Callers are expecting to see events as they happen: Line buffering */
setlinebuf(stdout);
diff --git a/src/udev/udevadm-settle.c b/src/udev/udevadm-settle.c
index 4ae237d430..8d9c4509ff 100644
--- a/src/udev/udevadm-settle.c
+++ b/src/udev/udevadm-settle.c
@@ -18,6 +18,7 @@
#include "udevadm.h"
#include "udev-ctrl.h"
#include "util.h"
+#include "virt.h"
static usec_t arg_timeout = 120 * USEC_PER_SEC;
static const char *arg_exists = NULL;
@@ -88,6 +89,11 @@ int settle_main(int argc, char *argv[], void *userdata) {
if (r <= 0)
return r;
+ if (running_in_chroot() > 0) {
+ log_info("Running in chroot, ignoring request.");
+ return 0;
+ }
+
deadline = now(CLOCK_MONOTONIC) + arg_timeout;
/* guarantee that the udev daemon isn't pre-processing */
@@ -96,9 +102,9 @@ int settle_main(int argc, char *argv[], void *userdata) {
uctrl = udev_ctrl_new();
if (uctrl) {
- r = udev_ctrl_send_ping(uctrl, MAX(5U, arg_timeout / USEC_PER_SEC));
+ r = udev_ctrl_send_ping(uctrl, MAX(5 * USEC_PER_SEC, arg_timeout));
if (r < 0) {
- log_debug_errno(r, "Failed to connect to udev daemon.");
+ log_debug_errno(r, "Failed to connect to udev daemon: %m");
return 0;
}
}
diff --git a/src/udev/udevadm-trigger.c b/src/udev/udevadm-trigger.c
index f13a08f3f9..95329469e3 100644
--- a/src/udev/udevadm-trigger.c
+++ b/src/udev/udevadm-trigger.c
@@ -10,11 +10,14 @@
#include "fd-util.h"
#include "fileio.h"
#include "path-util.h"
+#include "process-util.h"
#include "set.h"
#include "string-util.h"
#include "strv.h"
#include "udevadm.h"
#include "udevadm-util.h"
+#include "udev-ctrl.h"
+#include "virt.h"
static bool arg_verbose = false;
static bool arg_dry_run = false;
@@ -117,6 +120,8 @@ static int help(void) {
" --name-match=NAME Trigger devices with this /dev name\n"
" -b --parent-match=NAME Trigger devices with that parent device\n"
" -w --settle Wait for the triggered events to complete\n"
+ " --wait-daemon[=SECONDS] Wait for udevd daemon to be initialized\n"
+ " before triggering uevents\n"
, program_invocation_short_name);
return 0;
@@ -125,6 +130,7 @@ static int help(void) {
int trigger_main(int argc, char *argv[], void *userdata) {
enum {
ARG_NAME = 0x100,
+ ARG_PING,
};
static const struct option options[] = {
@@ -142,6 +148,7 @@ int trigger_main(int argc, char *argv[], void *userdata) {
{ "name-match", required_argument, NULL, ARG_NAME },
{ "parent-match", required_argument, NULL, 'b' },
{ "settle", no_argument, NULL, 'w' },
+ { "wait-daemon", optional_argument, NULL, ARG_PING },
{ "version", no_argument, NULL, 'V' },
{ "help", no_argument, NULL, 'h' },
{}
@@ -155,9 +162,15 @@ int trigger_main(int argc, char *argv[], void *userdata) {
_cleanup_(sd_device_monitor_unrefp) sd_device_monitor *m = NULL;
_cleanup_(sd_event_unrefp) sd_event *event = NULL;
_cleanup_set_free_free_ Set *settle_set = NULL;
- bool settle = false;
+ usec_t ping_timeout_usec = 5 * USEC_PER_SEC;
+ bool settle = false, ping = false;
int c, r;
+ if (running_in_chroot() > 0) {
+ log_info("Running in chroot, ignoring request.");
+ return 0;
+ }
+
r = sd_device_enumerator_new(&e);
if (r < 0)
return r;
@@ -182,18 +195,14 @@ int trigger_main(int argc, char *argv[], void *userdata) {
device_type = TYPE_DEVICES;
else if (streq(optarg, "subsystems"))
device_type = TYPE_SUBSYSTEMS;
- else {
- log_error("Unknown type --type=%s", optarg);
- return -EINVAL;
- }
+ else
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown type --type=%s", optarg);
break;
case 'c':
if (STR_IN_SET(optarg, "add", "remove", "change"))
action = optarg;
- else {
- log_error("Unknown action '%s'", optarg);
- return -EINVAL;
- }
+ else
+ log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown action '%s'", optarg);
break;
case 's':
@@ -269,6 +278,16 @@ int trigger_main(int argc, char *argv[], void *userdata) {
break;
}
+ case ARG_PING: {
+ ping = true;
+ if (optarg) {
+ r = parse_sec(optarg, &ping_timeout_usec);
+ if (r < 0)
+ log_error_errno(r, "Failed to parse timeout value '%s', ignoring: %m", optarg);
+ }
+ break;
+ }
+
case 'V':
return print_version();
case 'h':
@@ -280,6 +299,24 @@ int trigger_main(int argc, char *argv[], void *userdata) {
}
}
+ if (!arg_dry_run || ping) {
+ r = must_be_root();
+ if (r < 0)
+ return r;
+ }
+
+ if (ping) {
+ _cleanup_(udev_ctrl_unrefp) struct udev_ctrl *uctrl = NULL;
+
+ uctrl = udev_ctrl_new();
+ if (!uctrl)
+ return log_oom();
+
+ r = udev_ctrl_send_ping(uctrl, ping_timeout_usec);
+ if (r < 0)
+ return log_error_errno(r, "Failed to connect to udev daemon: %m");
+ }
+
for (; optind < argc; optind++) {
_cleanup_(sd_device_unrefp) sd_device *dev = NULL;
diff --git a/src/udev/udevadm.c b/src/udev/udevadm.c
index 1125c54b9f..28194314de 100644
--- a/src/udev/udevadm.c
+++ b/src/udev/udevadm.c
@@ -113,12 +113,13 @@ static int run(int argc, char *argv[]) {
udev_parse_config();
log_parse_environment();
log_open();
- log_set_max_level_realm(LOG_REALM_SYSTEMD, log_get_max_level());
r = parse_argv(argc, argv);
if (r <= 0)
return r;
+ log_set_max_level_realm(LOG_REALM_SYSTEMD, log_get_max_level());
+
mac_selinux_init();
return udevadm_main(argc, argv);
}
diff --git a/src/udev/udevadm.h b/src/udev/udevadm.h
index 98f9019a48..86b24af086 100644
--- a/src/udev/udevadm.h
+++ b/src/udev/udevadm.h
@@ -3,6 +3,9 @@
#include <stdio.h>
+#include "build.h"
+#include "macro.h"
+
int info_main(int argc, char *argv[], void *userdata);
int trigger_main(int argc, char *argv[], void *userdata);
int settle_main(int argc, char *argv[], void *userdata);
@@ -13,6 +16,7 @@ int test_main(int argc, char *argv[], void *userdata);
int builtin_main(int argc, char *argv[], void *userdata);
static inline int print_version(void) {
- puts(PACKAGE_VERSION);
+ /* Dracut relies on the version being a single integer */
+ puts(STRINGIFY(PROJECT_VERSION));
return 0;
}
diff --git a/src/udev/udevd.c b/src/udev/udevd.c
index fb8724ea87..0303f36b4f 100644
--- a/src/udev/udevd.c
+++ b/src/udev/udevd.c
@@ -31,6 +31,7 @@
#include "sd-event.h"
#include "alloc-util.h"
+#include "build.h"
#include "cgroup-util.h"
#include "cpu-set-util.h"
#include "dev-setup.h"
@@ -185,20 +186,11 @@ static void worker_free(struct worker *worker) {
free(worker);
}
-static void manager_workers_free(Manager *manager) {
- struct worker *worker;
- Iterator i;
-
- assert(manager);
-
- HASHMAP_FOREACH(worker, manager->workers, i)
- worker_free(worker);
-
- manager->workers = hashmap_free(manager->workers);
-}
+DEFINE_TRIVIAL_CLEANUP_FUNC(struct worker *, worker_free);
+DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(worker_hash_op, void, trivial_hash_func, trivial_compare_func, struct worker, worker_free);
static int worker_new(struct worker **ret, Manager *manager, sd_device_monitor *worker_monitor, pid_t pid) {
- _cleanup_free_ struct worker *worker = NULL;
+ _cleanup_(worker_freep) struct worker *worker = NULL;
int r;
assert(ret);
@@ -206,17 +198,20 @@ static int worker_new(struct worker **ret, Manager *manager, sd_device_monitor *
assert(worker_monitor);
assert(pid > 1);
- worker = new0(struct worker, 1);
+ /* close monitor, but keep address around */
+ device_monitor_disconnect(worker_monitor);
+
+ worker = new(struct worker, 1);
if (!worker)
return -ENOMEM;
- worker->manager = manager;
- /* close monitor, but keep address around */
- device_monitor_disconnect(worker_monitor);
- worker->monitor = sd_device_monitor_ref(worker_monitor);
- worker->pid = pid;
+ *worker = (struct worker) {
+ .manager = manager,
+ .monitor = sd_device_monitor_ref(worker_monitor),
+ .pid = pid,
+ };
- r = hashmap_ensure_allocated(&manager->workers, NULL);
+ r = hashmap_ensure_allocated(&manager->workers, &worker_hash_op);
if (r < 0)
return r;
@@ -290,7 +285,7 @@ static void manager_clear_for_worker(Manager *manager) {
manager->event = sd_event_unref(manager->event);
- manager_workers_free(manager);
+ manager->workers = hashmap_free(manager->workers);
event_queue_cleanup(manager, EVENT_UNDEF);
manager->monitor = sd_device_monitor_unref(manager->monitor);
@@ -396,7 +391,7 @@ static int worker_lock_block_device(sd_device *dev, int *ret_fd) {
static int worker_process_device(Manager *manager, sd_device *dev) {
_cleanup_(udev_event_freep) UdevEvent *udev_event = NULL;
_cleanup_close_ int fd_lock = -1;
- const char *seqnum;
+ const char *seqnum, *action;
int r;
assert(manager);
@@ -404,9 +399,13 @@ static int worker_process_device(Manager *manager, sd_device *dev) {
r = sd_device_get_property_value(dev, "SEQNUM", &seqnum);
if (r < 0)
- log_device_debug_errno(dev, r, "Failed to get SEQNUM: %m");
+ return log_device_debug_errno(dev, r, "Failed to get SEQNUM: %m");
- log_device_debug(dev, "Processing device (SEQNUM=%s)", seqnum);
+ r = sd_device_get_property_value(dev, "ACTION", &action);
+ if (r < 0)
+ return log_device_debug_errno(dev, r, "Failed to get ACTION: %m");
+
+ log_device_debug(dev, "Processing device (SEQNUM=%s, ACTION=%s)", seqnum, action);
udev_event = udev_event_new(dev, arg_exec_delay_usec, manager->rtnl);
if (!udev_event)
@@ -432,7 +431,7 @@ static int worker_process_device(Manager *manager, sd_device *dev) {
return log_device_debug_errno(dev, r, "Failed to update database under /run/udev/data/: %m");
}
- log_device_debug(dev, "Device (SEQNUM=%s) processed", seqnum);
+ log_device_debug(dev, "Device (SEQNUM=%s, ACTION=%s) processed", seqnum, action);
return 0;
}
@@ -464,7 +463,7 @@ static int worker_device_monitor_handler(sd_device_monitor *monitor, sd_device *
static int worker_main(Manager *_manager, sd_device_monitor *monitor, sd_device *first_device) {
_cleanup_(sd_device_unrefp) sd_device *dev = first_device;
_cleanup_(manager_freep) Manager *manager = _manager;
- int r, ret;
+ int r;
assert(manager);
assert(monitor);
@@ -507,11 +506,7 @@ static int worker_main(Manager *_manager, sd_device_monitor *monitor, sd_device
if (r < 0)
return log_error_errno(r, "Event loop failed: %m");
- r = sd_event_get_exit_code(manager->event, &ret);
- if (r < 0)
- return log_error_errno(r, "Failed to get exit code: %m");
-
- return ret;
+ return 0;
}
static int worker_spawn(Manager *manager, struct event *event) {
@@ -534,7 +529,7 @@ static int worker_spawn(Manager *manager, struct event *event) {
if (r < 0)
return log_error_errno(r, "Worker: Failed to enable receiving of device: %m");
- r = safe_fork("(worker)", FORK_DEATHSIG, &pid);
+ r = safe_fork(NULL, FORK_DEATHSIG, &pid);
if (r < 0) {
event->state = EVENT_QUEUED;
return log_error_errno(r, "Failed to fork() worker: %m");
@@ -592,8 +587,8 @@ static void event_run(Manager *manager, struct event *event) {
static int event_queue_insert(Manager *manager, sd_device *dev) {
_cleanup_(sd_device_unrefp) sd_device *clone = NULL;
+ const char *val, *action;
struct event *event;
- const char *val;
uint64_t seqnum;
int r;
@@ -618,6 +613,11 @@ static int event_queue_insert(Manager *manager, sd_device *dev) {
if (seqnum == 0)
return -EINVAL;
+ /* Refuse devices do not have ACTION property. */
+ r = sd_device_get_property_value(dev, "ACTION", &action);
+ if (r < 0)
+ return r;
+
/* Save original device to restore the state on failures. */
r = device_shallow_clone(dev, &clone);
if (r < 0)
@@ -647,12 +647,7 @@ static int event_queue_insert(Manager *manager, sd_device *dev) {
LIST_APPEND(event, manager->events, event);
- if (DEBUG_LOGGING) {
- if (sd_device_get_property_value(dev, "ACTION", &val) < 0)
- val = NULL;
-
- log_device_debug(dev, "Device (SEQNUM=%"PRIu64", ACTION=%s) is queued", seqnum, strnull(val));
- }
+ log_device_debug(dev, "Device (SEQNUM=%"PRIu64", ACTION=%s) is queued", seqnum, action);
return 0;
}
@@ -875,7 +870,7 @@ static void event_queue_start(Manager *manager) {
assert_se(sd_event_now(manager->event, CLOCK_MONOTONIC, &usec) >= 0);
/* check for changed config, every 3 seconds at most */
if (manager->last_usec == 0 ||
- (usec - manager->last_usec) > 3 * USEC_PER_SEC) {
+ usec - manager->last_usec > 3 * USEC_PER_SEC) {
if (udev_rules_check_timestamp(manager->rules) ||
udev_builtin_validate())
manager_reload(manager);
@@ -960,12 +955,11 @@ static int on_worker(sd_event_source *s, int fd, uint32_t revents, void *userdat
continue;
}
- CMSG_FOREACH(cmsg, &msghdr) {
+ CMSG_FOREACH(cmsg, &msghdr)
if (cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SCM_CREDENTIALS &&
cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred)))
ucred = (struct ucred*) CMSG_DATA(cmsg);
- }
if (!ucred || ucred->pid <= 0) {
log_warning("Ignoring worker message without valid PID");
@@ -1033,7 +1027,8 @@ static int on_ctrl_msg(sd_event_source *s, int fd, uint32_t revents, void *userd
i = udev_ctrl_get_set_log_level(ctrl_msg);
if (i >= 0) {
log_debug("Received udev control message (SET_LOG_LEVEL), setting log_priority=%i", i);
- log_set_max_level(i);
+ log_set_max_level_realm(LOG_REALM_UDEV, i);
+ log_set_max_level_realm(LOG_REALM_SYSTEMD, i);
manager_kill_workers(manager);
}
@@ -1118,7 +1113,7 @@ static int on_ctrl_msg(sd_event_source *s, int fd, uint32_t revents, void *userd
}
if (udev_ctrl_get_ping(ctrl_msg) > 0)
- log_debug("Received udev control message (SYNC)");
+ log_debug("Received udev control message (PING)");
if (udev_ctrl_get_exit(ctrl_msg) > 0) {
log_debug("Received udev control message (EXIT)");
@@ -1338,9 +1333,9 @@ static int on_sigchld(sd_event_source *s, const struct signalfd_siginfo *si, voi
log_debug("Worker ["PID_FMT"] exited", pid);
else
log_warning("Worker ["PID_FMT"] exited with return code %i", pid, WEXITSTATUS(status));
- } else if (WIFSIGNALED(status)) {
+ } else if (WIFSIGNALED(status))
log_warning("Worker ["PID_FMT"] terminated by signal %i (%s)", pid, WTERMSIG(status), signal_to_string(WTERMSIG(status)));
- } else if (WIFSTOPPED(status)) {
+ else if (WIFSTOPPED(status)) {
log_info("Worker ["PID_FMT"] stopped", pid);
continue;
} else if (WIFCONTINUED(status)) {
@@ -1579,7 +1574,7 @@ static int parse_argv(int argc, char *argv[]) {
case 'h':
return help();
case 'V':
- printf("%s\n", PACKAGE_VERSION);
+ printf("%s\n", GIT_VERSION);
return 0;
case '?':
return -EINVAL;
@@ -1594,7 +1589,7 @@ static int parse_argv(int argc, char *argv[]) {
static int manager_new(Manager **ret, int fd_ctrl, int fd_uevent, const char *cgroup) {
_cleanup_(manager_freep) Manager *manager = NULL;
- int r, fd_worker;
+ int r;
assert(ret);
@@ -1608,25 +1603,13 @@ static int manager_new(Manager **ret, int fd_ctrl, int fd_uevent, const char *cg
.cgroup = cgroup,
};
- udev_builtin_init();
-
- r = udev_rules_new(&manager->rules, arg_resolve_name_timing);
- if (!manager->rules)
- return log_error_errno(r, "Failed to read udev rules: %m");
-
manager->ctrl = udev_ctrl_new_from_fd(fd_ctrl);
if (!manager->ctrl)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to initialize udev control socket");
- if (fd_ctrl < 0) {
- r = udev_ctrl_enable_receiving(manager->ctrl);
- if (r < 0)
- return log_error_errno(r, "Failed to bind udev control socket: %m");
- }
-
- fd_ctrl = udev_ctrl_get_fd(manager->ctrl);
- if (fd_ctrl < 0)
- return log_error_errno(fd_ctrl, "Failed to get udev control socket fd: %m");
+ r = udev_ctrl_enable_receiving(manager->ctrl);
+ if (r < 0)
+ return log_error_errno(r, "Failed to bind udev control socket: %m");
r = device_monitor_new_full(&manager->monitor, MONITOR_GROUP_KERNEL, fd_uevent);
if (r < 0)
@@ -1634,6 +1617,18 @@ static int manager_new(Manager **ret, int fd_ctrl, int fd_uevent, const char *cg
(void) sd_device_monitor_set_receive_buffer_size(manager->monitor, 128 * 1024 * 1024);
+ r = device_monitor_enable_receiving(manager->monitor);
+ if (r < 0)
+ return log_error_errno(r, "Failed to bind netlink socket: %m");
+
+ *ret = TAKE_PTR(manager);
+
+ return 0;
+}
+
+static int main_loop(Manager *manager) {
+ int fd_worker, fd_ctrl, r;
+
/* unnamed socket from workers to the main daemon */
r = socketpair(AF_LOCAL, SOCK_DGRAM|SOCK_CLOEXEC, 0, manager->worker_watch);
if (r < 0)
@@ -1679,6 +1674,10 @@ static int manager_new(Manager **ret, int fd_ctrl, int fd_uevent, const char *cg
if (r < 0)
return log_error_errno(r, "Failed to create watchdog event source: %m");
+ fd_ctrl = udev_ctrl_get_fd(manager->ctrl);
+ if (fd_ctrl < 0)
+ return log_error_errno(fd_ctrl, "Failed to get udev control socket fd: %m");
+
r = sd_event_add_io(manager->event, &manager->ctrl_event, fd_ctrl, EPOLLIN, on_ctrl_msg, manager);
if (r < 0)
return log_error_errno(r, "Failed to create udev control event source: %m");
@@ -1713,20 +1712,11 @@ static int manager_new(Manager **ret, int fd_ctrl, int fd_uevent, const char *cg
if (r < 0)
return log_error_errno(r, "Failed to create post event source: %m");
- *ret = TAKE_PTR(manager);
-
- return 0;
-}
-
-static int main_loop(int fd_ctrl, int fd_uevent, const char *cgroup) {
- _cleanup_(manager_freep) Manager *manager = NULL;
- int r;
+ udev_builtin_init();
- r = manager_new(&manager, fd_ctrl, fd_uevent, cgroup);
- if (r < 0) {
- r = log_error_errno(r, "Failed to allocate manager object: %m");
- goto exit;
- }
+ r = udev_rules_new(&manager->rules, arg_resolve_name_timing);
+ if (!manager->rules)
+ return log_error_errno(r, "Failed to read udev rules: %m");
r = udev_rules_apply_static_dev_perms(manager->rules);
if (r < 0)
@@ -1737,24 +1727,18 @@ static int main_loop(int fd_ctrl, int fd_uevent, const char *cgroup) {
"STATUS=Processing with %u children at max", arg_children_max);
r = sd_event_loop(manager->event);
- if (r < 0) {
+ if (r < 0)
log_error_errno(r, "Event loop failed: %m");
- goto exit;
- }
- sd_event_get_exit_code(manager->event, &r);
-
-exit:
sd_notify(false,
"STOPPING=1\n"
"STATUS=Shutting down...");
- if (manager)
- udev_ctrl_cleanup(manager->ctrl);
return r;
}
static int run(int argc, char *argv[]) {
_cleanup_free_ char *cgroup = NULL;
+ _cleanup_(manager_freep) Manager *manager = NULL;
int fd_ctrl = -1, fd_uevent = -1;
int r;
@@ -1814,10 +1798,10 @@ static int run(int argc, char *argv[]) {
dev_setup(NULL, UID_INVALID, GID_INVALID);
- if (getppid() == 1) {
- /* get our own cgroup, we regularly kill everything udev has left behind
- we only do this on systemd systems, and only if we are directly spawned
- by PID1. otherwise we are not guaranteed to have a dedicated cgroup */
+ if (getppid() == 1 && sd_booted() > 0) {
+ /* Get our own cgroup, we regularly kill everything udev has left behind.
+ * We only do this on systemd systems, and only if we are directly spawned
+ * by PID1. Otherwise we are not guaranteed to have a dedicated cgroup. */
r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &cgroup);
if (r < 0) {
if (IN_SET(r, -ENOENT, -ENOMEDIUM))
@@ -1831,10 +1815,14 @@ static int run(int argc, char *argv[]) {
if (r < 0)
return log_error_errno(r, "Failed to listen on fds: %m");
+ r = manager_new(&manager, fd_ctrl, fd_uevent, cgroup);
+ if (r < 0)
+ return log_error_errno(r, "Failed to create manager: %m");
+
if (arg_daemonize) {
pid_t pid;
- log_info("starting version " PACKAGE_VERSION);
+ log_info("Starting version " GIT_VERSION);
/* connect /dev/null to stdin, stdout, stderr */
if (log_get_max_level() < LOG_DEBUG) {
@@ -1858,7 +1846,10 @@ static int run(int argc, char *argv[]) {
log_debug_errno(r, "Failed to adjust OOM score, ignoring: %m");
}
- return main_loop(fd_ctrl, fd_uevent, cgroup);
+ r = main_loop(manager);
+ /* FIXME: move this into manager_free() */
+ udev_ctrl_cleanup(manager->ctrl);
+ return r;
}
DEFINE_MAIN_FUNCTION(run);
diff --git a/src/version/version.h.in b/src/version/version.h.in
new file mode 100644
index 0000000000..9f82d905a7
--- /dev/null
+++ b/src/version/version.h.in
@@ -0,0 +1 @@
+#define GIT_VERSION "@VCS_TAG@"