summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/basic/af-list.c2
-rw-r--r--src/basic/arphrd-list.c2
-rw-r--r--src/basic/calendarspec.c25
-rw-r--r--src/basic/cap-list.c2
-rw-r--r--src/basic/errno-list.c2
-rw-r--r--src/basic/missing.h22
-rw-r--r--src/basic/socket-util.c77
-rw-r--r--src/basic/socket-util.h4
-rw-r--r--src/basic/sparse-endian.h47
-rw-r--r--src/basic/special.h1
-rw-r--r--src/basic/user-util.c12
-rw-r--r--src/core/device.c2
-rw-r--r--src/core/load-fragment.h2
-rw-r--r--src/core/service.c10
-rw-r--r--src/core/socket.c31
-rw-r--r--src/core/triggers.systemd.in22
-rw-r--r--src/core/unit.c12
-rw-r--r--src/gpt-auto-generator/gpt-auto-generator.c2
-rw-r--r--src/journal-remote/journal-gatewayd.c2
-rw-r--r--src/journal/journald-server.h2
-rw-r--r--src/journal/sd-journal.c3
-rw-r--r--src/kernel-install/kernel-install8
-rw-r--r--src/libsystemd-network/ndisc-router.c10
-rw-r--r--src/libudev/libudev-util.c2
-rw-r--r--src/login/logind.h2
-rw-r--r--src/machine/image-dbus.c1
-rw-r--r--src/machine/machinectl.c18
-rw-r--r--src/network/netdev/netdev-gperf.gperf1
-rw-r--r--src/network/netdev/netdev.h2
-rw-r--r--src/network/networkd-conf.h2
-rw-r--r--src/network/networkd-link.c58
-rw-r--r--src/network/networkd-ndisc.c2
-rw-r--r--src/network/networkd-network-gperf.gperf4
-rw-r--r--src/network/networkd-network.h4
-rw-r--r--src/nspawn/nspawn-settings.h2
-rw-r--r--src/nspawn/nspawn.c17
-rw-r--r--src/nss-mymachines/nss-mymachines.c12
-rw-r--r--src/nss-systemd/nss-systemd.c26
-rw-r--r--src/resolve/dns-type.c2
-rw-r--r--src/resolve/resolved-conf.h2
-rw-r--r--src/resolve/resolved-etc-hosts.c6
-rw-r--r--src/shared/install.c24
-rw-r--r--src/shared/path-lookup.c2
-rw-r--r--src/socket-proxy/socket-proxyd.c2
-rw-r--r--src/systemctl/systemctl.c2
-rw-r--r--src/test/test-af-list.c2
-rw-r--r--src/test/test-arphrd-list.c2
-rw-r--r--src/test/test-calendarspec.c2
-rw-r--r--src/test/test-selinux.c8
-rw-r--r--src/test/test-socket-util.c26
-rw-r--r--src/timesync/timesyncd-conf.h2
-rw-r--r--src/tmpfiles/tmpfiles.c4
-rw-r--r--src/udev/net/link-config.h2
-rw-r--r--src/udev/udev-builtin-input_id.c3
-rw-r--r--src/udev/udev-builtin-keyboard.c2
-rw-r--r--src/udev/udev-event.c39
-rw-r--r--src/udev/udev-rules.c40
-rw-r--r--src/udev/udev.h4
-rw-r--r--src/udev/udevadm-test.c2
59 files changed, 445 insertions, 188 deletions
diff --git a/src/basic/af-list.c b/src/basic/af-list.c
index 3fac9c508b..4b291d177b 100644
--- a/src/basic/af-list.c
+++ b/src/basic/af-list.c
@@ -23,7 +23,7 @@
#include "af-list.h"
#include "macro.h"
-static const struct af_name* lookup_af(register const char *str, register unsigned int len);
+static const struct af_name* lookup_af(register const char *str, register GPERF_LEN_TYPE len);
#include "af-from-name.h"
#include "af-to-name.h"
diff --git a/src/basic/arphrd-list.c b/src/basic/arphrd-list.c
index 6792d1ee3f..2d598dc66f 100644
--- a/src/basic/arphrd-list.c
+++ b/src/basic/arphrd-list.c
@@ -23,7 +23,7 @@
#include "arphrd-list.h"
#include "macro.h"
-static const struct arphrd_name* lookup_arphrd(register const char *str, register unsigned int len);
+static const struct arphrd_name* lookup_arphrd(register const char *str, register GPERF_LEN_TYPE len);
#include "arphrd-from-name.h"
#include "arphrd-to-name.h"
diff --git a/src/basic/calendarspec.c b/src/basic/calendarspec.c
index 3e249505a5..2e5622699d 100644
--- a/src/basic/calendarspec.c
+++ b/src/basic/calendarspec.c
@@ -20,6 +20,7 @@
#include <alloca.h>
#include <ctype.h>
#include <errno.h>
+#include <limits.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
@@ -96,7 +97,7 @@ static void normalize_chain(CalendarComponent **c) {
* While we're counting the chain, also normalize `stop`
* so the length of the range is a multiple of `repeat`
*/
- if (i->stop > i->start)
+ if (i->stop > i->start && i->repeat > 0)
i->stop -= (i->stop - i->start) % i->repeat;
}
@@ -487,7 +488,7 @@ static int parse_weekdays(const char **p, CalendarSpec *c) {
}
}
-static int parse_component_decimal(const char **p, bool usec, unsigned long *res) {
+static int parse_component_decimal(const char **p, bool usec, int *res) {
unsigned long value;
const char *e = NULL;
char *ee = NULL;
@@ -502,8 +503,6 @@ static int parse_component_decimal(const char **p, bool usec, unsigned long *res
return -errno;
if (ee == *p)
return -EINVAL;
- if ((unsigned long) (int) value != value)
- return -ERANGE;
e = ee;
if (usec) {
@@ -511,12 +510,10 @@ static int parse_component_decimal(const char **p, bool usec, unsigned long *res
return -ERANGE;
value *= USEC_PER_SEC;
- if (*e == '.') {
- unsigned add;
- /* This is the start of a range, not a fractional part */
- if (e[1] == '.')
- goto finish;
+ /* One "." is a decimal point, but ".." is a range separator */
+ if (e[0] == '.' && e[1] != '.') {
+ unsigned add;
e++;
r = parse_fractional_part_u(&e, 6, &add);
@@ -529,7 +526,9 @@ static int parse_component_decimal(const char **p, bool usec, unsigned long *res
}
}
-finish:
+ if (value > INT_MAX)
+ return -ERANGE;
+
*p = e;
*res = value;
@@ -556,9 +555,8 @@ static int const_chain(int value, CalendarComponent **c) {
}
static int prepend_component(const char **p, bool usec, CalendarComponent **c) {
- unsigned long start, stop = -1, repeat = 0;
+ int r, start, stop = -1, repeat = 0;
CalendarComponent *cc;
- int r;
const char *e;
assert(p);
@@ -1016,8 +1014,7 @@ fail:
return r;
}
-static int find_end_of_month(struct tm *tm, bool utc, int day)
-{
+static int find_end_of_month(struct tm *tm, bool utc, int day) {
struct tm t = *tm;
t.tm_mon++;
diff --git a/src/basic/cap-list.c b/src/basic/cap-list.c
index 3e773a06f5..d68cc78d05 100644
--- a/src/basic/cap-list.c
+++ b/src/basic/cap-list.c
@@ -26,7 +26,7 @@
#include "parse-util.h"
#include "util.h"
-static const struct capability_name* lookup_capability(register const char *str, register unsigned int len);
+static const struct capability_name* lookup_capability(register const char *str, register GPERF_LEN_TYPE len);
#include "cap-from-name.h"
#include "cap-to-name.h"
diff --git a/src/basic/errno-list.c b/src/basic/errno-list.c
index 31b66bad5e..c6a01eec8b 100644
--- a/src/basic/errno-list.c
+++ b/src/basic/errno-list.c
@@ -23,7 +23,7 @@
#include "macro.h"
static const struct errno_name* lookup_errno(register const char *str,
- register unsigned int len);
+ register GPERF_LEN_TYPE len);
#include "errno-from-name.h"
#include "errno-to-name.h"
diff --git a/src/basic/missing.h b/src/basic/missing.h
index dd4425697f..480462357d 100644
--- a/src/basic/missing.h
+++ b/src/basic/missing.h
@@ -34,6 +34,7 @@
#include <net/ethernet.h>
#include <stdlib.h>
#include <sys/resource.h>
+#include <sys/socket.h>
#include <sys/syscall.h>
#include <uchar.h>
#include <unistd.h>
@@ -50,6 +51,23 @@
#include <linux/btrfs.h>
#endif
+#ifdef HAVE_LINUX_VM_SOCKETS_H
+#include <linux/vm_sockets.h>
+#else
+#define VMADDR_CID_ANY -1U
+struct sockaddr_vm {
+ unsigned short svm_family;
+ unsigned short svm_reserved1;
+ unsigned int svm_port;
+ unsigned int svm_cid;
+ unsigned char svm_zero[sizeof(struct sockaddr) -
+ sizeof(unsigned short) -
+ sizeof(unsigned short) -
+ sizeof(unsigned int) -
+ sizeof(unsigned int)];
+};
+#endif /* !HAVE_LINUX_VM_SOCKETS_H */
+
#include "macro.h"
#ifndef RLIMIT_RTTIME
@@ -1163,4 +1181,8 @@ struct ethtool_link_settings {
#define SOL_ALG 279
#endif
+#ifndef AF_VSOCK
+#define AF_VSOCK 40
+#endif
+
#include "missing_syscall.h"
diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c
index 4ebf106109..77f81a60ba 100644
--- a/src/basic/socket-util.c
+++ b/src/basic/socket-util.c
@@ -113,6 +113,30 @@ int socket_address_parse(SocketAddress *a, const char *s) {
memcpy(a->sockaddr.un.sun_path+1, s+1, l);
a->size = offsetof(struct sockaddr_un, sun_path) + 1 + l;
+ } else if (startswith(s, "vsock:")) {
+ /* AF_VSOCK socket in vsock:cid:port notation */
+ const char *cid_start = s + strlen("vsock:");
+
+ e = strchr(cid_start, ':');
+ if (!e)
+ return -EINVAL;
+
+ r = safe_atou(e+1, &u);
+ if (r < 0)
+ return r;
+
+ n = strndupa(cid_start, e - cid_start);
+ if (!isempty(n)) {
+ r = safe_atou(n, &a->sockaddr.vm.svm_cid);
+ if (r < 0)
+ return r;
+ } else
+ a->sockaddr.vm.svm_cid = VMADDR_CID_ANY;
+
+ a->sockaddr.vm.svm_family = AF_VSOCK;
+ a->sockaddr.vm.svm_port = u;
+ a->size = sizeof(struct sockaddr_vm);
+
} else {
e = strchr(s, ':');
if (e) {
@@ -289,6 +313,15 @@ int socket_address_verify(const SocketAddress *a) {
return 0;
+ case AF_VSOCK:
+ if (a->size != sizeof(struct sockaddr_vm))
+ return -EINVAL;
+
+ if (a->type != SOCK_STREAM && a->type != SOCK_DGRAM)
+ return -EINVAL;
+
+ return 0;
+
default:
return -EAFNOSUPPORT;
}
@@ -394,6 +427,15 @@ bool socket_address_equal(const SocketAddress *a, const SocketAddress *b) {
break;
+ case AF_VSOCK:
+ if (a->sockaddr.vm.svm_cid != b->sockaddr.vm.svm_cid)
+ return false;
+
+ if (a->sockaddr.vm.svm_port != b->sockaddr.vm.svm_port)
+ return false;
+
+ break;
+
default:
/* Cannot compare, so we assume the addresses are different */
return false;
@@ -480,15 +522,27 @@ bool socket_address_matches_fd(const SocketAddress *a, int fd) {
return socket_address_equal(a, &b);
}
-int sockaddr_port(const struct sockaddr *_sa) {
+int sockaddr_port(const struct sockaddr *_sa, unsigned *port) {
union sockaddr_union *sa = (union sockaddr_union*) _sa;
assert(sa);
- if (!IN_SET(sa->sa.sa_family, AF_INET, AF_INET6))
- return -EAFNOSUPPORT;
+ switch (sa->sa.sa_family) {
+ case AF_INET:
+ *port = be16toh(sa->in.sin_port);
+ return 0;
+
+ case AF_INET6:
+ *port = be16toh(sa->in6.sin6_port);
+ return 0;
+
+ case AF_VSOCK:
+ *port = sa->vm.svm_port;
+ return 0;
- return be16toh(sa->sa.sa_family == AF_INET6 ? sa->in6.sin6_port : sa->in.sin_port);
+ default:
+ return -EAFNOSUPPORT;
+ }
}
int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_ipv6, bool include_port, char **ret) {
@@ -591,6 +645,18 @@ int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_
break;
+ case AF_VSOCK:
+ if (include_port)
+ r = asprintf(&p,
+ "vsock:%u:%u",
+ sa->vm.svm_cid,
+ sa->vm.svm_port);
+ else
+ r = asprintf(&p, "vsock:%u", sa->vm.svm_cid);
+ if (r < 0)
+ return -ENOMEM;
+ break;
+
default:
return -EOPNOTSUPP;
}
@@ -748,6 +814,9 @@ bool sockaddr_equal(const union sockaddr_union *a, const union sockaddr_union *b
if (a->sa.sa_family == AF_INET6)
return memcmp(&a->in6.sin6_addr, &b->in6.sin6_addr, sizeof(a->in6.sin6_addr)) == 0;
+ if (a->sa.sa_family == AF_VSOCK)
+ return a->vm.svm_cid == b->vm.svm_cid;
+
return false;
}
diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h
index 2ef572badb..3c42e220e5 100644
--- a/src/basic/socket-util.h
+++ b/src/basic/socket-util.h
@@ -30,6 +30,7 @@
#include <linux/if_packet.h>
#include "macro.h"
+#include "missing.h"
#include "util.h"
union sockaddr_union {
@@ -40,6 +41,7 @@ union sockaddr_union {
struct sockaddr_nl nl;
struct sockaddr_storage storage;
struct sockaddr_ll ll;
+ struct sockaddr_vm vm;
};
typedef struct SocketAddress {
@@ -100,7 +102,7 @@ const char* socket_address_get_path(const SocketAddress *a);
bool socket_ipv6_is_supported(void);
-int sockaddr_port(const struct sockaddr *_sa) _pure_;
+int sockaddr_port(const struct sockaddr *_sa, unsigned *port);
int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_ipv6, bool include_port, char **ret);
int getpeername_pretty(int fd, bool include_port, char **ret);
diff --git a/src/basic/sparse-endian.h b/src/basic/sparse-endian.h
index c913fda8c5..a3573b84a9 100644
--- a/src/basic/sparse-endian.h
+++ b/src/basic/sparse-endian.h
@@ -26,19 +26,19 @@
#include <stdint.h>
#ifdef __CHECKER__
-#define __bitwise __attribute__((bitwise))
-#define __force __attribute__((force))
+#define __sd_bitwise __attribute__((bitwise))
+#define __sd_force __attribute__((force))
#else
-#define __bitwise
-#define __force
+#define __sd_bitwise
+#define __sd_force
#endif
-typedef uint16_t __bitwise le16_t;
-typedef uint16_t __bitwise be16_t;
-typedef uint32_t __bitwise le32_t;
-typedef uint32_t __bitwise be32_t;
-typedef uint64_t __bitwise le64_t;
-typedef uint64_t __bitwise be64_t;
+typedef uint16_t __sd_bitwise le16_t;
+typedef uint16_t __sd_bitwise be16_t;
+typedef uint32_t __sd_bitwise le32_t;
+typedef uint32_t __sd_bitwise be32_t;
+typedef uint64_t __sd_bitwise le64_t;
+typedef uint64_t __sd_bitwise be64_t;
#undef htobe16
#undef htole16
@@ -69,20 +69,23 @@ typedef uint64_t __bitwise be64_t;
#define bswap_64_on_be(x) __bswap_64(x)
#endif
-static inline le16_t htole16(uint16_t value) { return (le16_t __force) bswap_16_on_be(value); }
-static inline le32_t htole32(uint32_t value) { return (le32_t __force) bswap_32_on_be(value); }
-static inline le64_t htole64(uint64_t value) { return (le64_t __force) bswap_64_on_be(value); }
+static inline le16_t htole16(uint16_t value) { return (le16_t __sd_force) bswap_16_on_be(value); }
+static inline le32_t htole32(uint32_t value) { return (le32_t __sd_force) bswap_32_on_be(value); }
+static inline le64_t htole64(uint64_t value) { return (le64_t __sd_force) bswap_64_on_be(value); }
-static inline be16_t htobe16(uint16_t value) { return (be16_t __force) bswap_16_on_le(value); }
-static inline be32_t htobe32(uint32_t value) { return (be32_t __force) bswap_32_on_le(value); }
-static inline be64_t htobe64(uint64_t value) { return (be64_t __force) bswap_64_on_le(value); }
+static inline be16_t htobe16(uint16_t value) { return (be16_t __sd_force) bswap_16_on_le(value); }
+static inline be32_t htobe32(uint32_t value) { return (be32_t __sd_force) bswap_32_on_le(value); }
+static inline be64_t htobe64(uint64_t value) { return (be64_t __sd_force) bswap_64_on_le(value); }
-static inline uint16_t le16toh(le16_t value) { return bswap_16_on_be((uint16_t __force)value); }
-static inline uint32_t le32toh(le32_t value) { return bswap_32_on_be((uint32_t __force)value); }
-static inline uint64_t le64toh(le64_t value) { return bswap_64_on_be((uint64_t __force)value); }
+static inline uint16_t le16toh(le16_t value) { return bswap_16_on_be((uint16_t __sd_force)value); }
+static inline uint32_t le32toh(le32_t value) { return bswap_32_on_be((uint32_t __sd_force)value); }
+static inline uint64_t le64toh(le64_t value) { return bswap_64_on_be((uint64_t __sd_force)value); }
-static inline uint16_t be16toh(be16_t value) { return bswap_16_on_le((uint16_t __force)value); }
-static inline uint32_t be32toh(be32_t value) { return bswap_32_on_le((uint32_t __force)value); }
-static inline uint64_t be64toh(be64_t value) { return bswap_64_on_le((uint64_t __force)value); }
+static inline uint16_t be16toh(be16_t value) { return bswap_16_on_le((uint16_t __sd_force)value); }
+static inline uint32_t be32toh(be32_t value) { return bswap_32_on_le((uint32_t __sd_force)value); }
+static inline uint64_t be64toh(be64_t value) { return bswap_64_on_le((uint64_t __sd_force)value); }
+
+#undef __sd_bitwise
+#undef __sd_force
#endif /* SPARSE_ENDIAN_H */
diff --git a/src/basic/special.h b/src/basic/special.h
index 5276bcf598..feb8e5fe21 100644
--- a/src/basic/special.h
+++ b/src/basic/special.h
@@ -103,6 +103,7 @@
#define SPECIAL_DBUS_SOCKET "dbus.socket"
#define SPECIAL_JOURNALD_SOCKET "systemd-journald.socket"
#define SPECIAL_JOURNALD_SERVICE "systemd-journald.service"
+#define SPECIAL_TMPFILES_SETUP_SERVICE "systemd-tmpfiles-setup.service"
/* Magic init signals */
#define SPECIAL_KBREQUEST_TARGET "kbrequest.target"
diff --git a/src/basic/user-util.c b/src/basic/user-util.c
index 938533d2e7..c619dad527 100644
--- a/src/basic/user-util.c
+++ b/src/basic/user-util.c
@@ -46,6 +46,8 @@
bool uid_is_valid(uid_t uid) {
+ /* Also see POSIX IEEE Std 1003.1-2008, 2016 Edition, 3.436. */
+
/* Some libc APIs use UID_INVALID as special placeholder */
if (uid == (uid_t) UINT32_C(0xFFFFFFFF))
return false;
@@ -519,7 +521,15 @@ bool valid_user_group_name(const char *u) {
const char *i;
long sz;
- /* Checks if the specified name is a valid user/group name. */
+ /* Checks if the specified name is a valid user/group name. Also see POSIX IEEE Std 1003.1-2008, 2016 Edition,
+ * 3.437. We are a bit stricter here however. Specifically we deviate from POSIX rules:
+ *
+ * - We don't allow any dots (this would break chown syntax which permits dots as user/group name separator)
+ * - We require that names fit into the appropriate utmp field
+ * - We don't allow empty user names
+ *
+ * Note that other systems are even more restrictive, and don't permit underscores or uppercase characters.
+ */
if (isempty(u))
return false;
diff --git a/src/core/device.c b/src/core/device.c
index bd481c8050..0e67c96552 100644
--- a/src/core/device.c
+++ b/src/core/device.c
@@ -385,7 +385,7 @@ static int device_setup_unit(Manager *m, struct udev_device *dev, const char *pa
* on its radar. In this case the device unit is partially initialized
* and includes the deps on the mount unit but at that time the "bind
* mounts" flag wasn't not present. Fix this up now. */
- if (device_is_bound_by_mounts(u, dev))
+ if (dev && device_is_bound_by_mounts(u, dev))
device_upgrade_mount_deps(u);
/* Note that this won't dispatch the load queue, the caller
diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h
index bbac2d84b5..fc27a07955 100644
--- a/src/core/load-fragment.h
+++ b/src/core/load-fragment.h
@@ -120,7 +120,7 @@ int config_parse_restrict_namespaces(const char *unit, const char *filename, uns
int config_parse_bind_paths(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
/* gperf prototypes */
-const struct ConfigPerfItem* load_fragment_gperf_lookup(const char *key, unsigned length);
+const struct ConfigPerfItem* load_fragment_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
extern const char load_fragment_gperf_nulstr[];
typedef enum Disabled {
diff --git a/src/core/service.c b/src/core/service.c
index 73a8104d17..54074ff7bc 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -1292,10 +1292,10 @@ static int service_spawn(
return r;
}
- if (r == 0 && IN_SET(sa.sa.sa_family, AF_INET, AF_INET6)) {
+ if (r == 0 && IN_SET(sa.sa.sa_family, AF_INET, AF_INET6, AF_VSOCK)) {
_cleanup_free_ char *addr = NULL;
char *t;
- int port;
+ unsigned port;
r = sockaddr_pretty(&sa.sa, salen, true, false, &addr);
if (r < 0)
@@ -1306,9 +1306,9 @@ static int service_spawn(
return -ENOMEM;
our_env[n_env++] = t;
- port = sockaddr_port(&sa.sa);
- if (port < 0)
- return port;
+ r = sockaddr_port(&sa.sa, &port);
+ if (r < 0)
+ return r;
if (asprintf(&t, "REMOTE_PORT=%u", port) < 0)
return -ENOMEM;
diff --git a/src/core/socket.c b/src/core/socket.c
index 0960a30039..3cae6b31bb 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -63,6 +63,7 @@ struct SocketPeer {
Socket *socket;
union sockaddr_union peer;
+ socklen_t peer_salen;
};
static const UnitActiveState state_translation_table[_SOCKET_STATE_MAX] = {
@@ -448,7 +449,7 @@ static int socket_verify(Socket *s) {
return 0;
if (!s->ports) {
- log_unit_error(UNIT(s), "Unit lacks Listen setting. Refusing.");
+ log_unit_error(UNIT(s), "Unit has no Listen setting (ListenStream=, ListenDatagram=, ListenFIFO=, ...). Refusing.");
return -EINVAL;
}
@@ -484,12 +485,15 @@ static void peer_address_hash_func(const void *p, struct siphash *state) {
const SocketPeer *s = p;
assert(s);
- assert(IN_SET(s->peer.sa.sa_family, AF_INET, AF_INET6));
if (s->peer.sa.sa_family == AF_INET)
siphash24_compress(&s->peer.in.sin_addr, sizeof(s->peer.in.sin_addr), state);
- else
+ else if (s->peer.sa.sa_family == AF_INET6)
siphash24_compress(&s->peer.in6.sin6_addr, sizeof(s->peer.in6.sin6_addr), state);
+ else if (s->peer.sa.sa_family == AF_VSOCK)
+ siphash24_compress(&s->peer.vm.svm_cid, sizeof(s->peer.vm.svm_cid), state);
+ else
+ assert_not_reached("Unknown address family.");
}
static int peer_address_compare_func(const void *a, const void *b) {
@@ -505,6 +509,12 @@ static int peer_address_compare_func(const void *a, const void *b) {
return memcmp(&x->peer.in.sin_addr, &y->peer.in.sin_addr, sizeof(x->peer.in.sin_addr));
case AF_INET6:
return memcmp(&x->peer.in6.sin6_addr, &y->peer.in6.sin6_addr, sizeof(x->peer.in6.sin6_addr));
+ case AF_VSOCK:
+ if (x->peer.vm.svm_cid < y->peer.vm.svm_cid)
+ return -1;
+ if (x->peer.vm.svm_cid > y->peer.vm.svm_cid)
+ return 1;
+ return 0;
}
assert_not_reached("Black sheep in the family!");
}
@@ -591,7 +601,7 @@ int socket_acquire_peer(Socket *s, int fd, SocketPeer **p) {
if (r < 0)
return log_error_errno(errno, "getpeername failed: %m");
- if (!IN_SET(sa.peer.sa.sa_family, AF_INET, AF_INET6)) {
+ if (!IN_SET(sa.peer.sa.sa_family, AF_INET, AF_INET6, AF_VSOCK)) {
*p = NULL;
return 0;
}
@@ -607,6 +617,7 @@ int socket_acquire_peer(Socket *s, int fd, SocketPeer **p) {
return log_oom();
remote->peer = sa.peer;
+ remote->peer_salen = salen;
r = set_put(s->peers_by_address, remote);
if (r < 0)
@@ -937,6 +948,16 @@ static int instance_from_socket(int fd, unsigned nr, char **instance) {
break;
}
+ case AF_VSOCK:
+ if (asprintf(&r,
+ "%u-%u:%u-%u:%u",
+ nr,
+ local.vm.svm_cid, local.vm.svm_port,
+ remote.vm.svm_cid, remote.vm.svm_port) < 0)
+ return -ENOMEM;
+
+ break;
+
default:
assert_not_reached("Unhandled socket type.");
}
@@ -2189,7 +2210,7 @@ static void socket_enter_running(Socket *s, int cfd) {
} else if (r > 0 && p->n_ref > s->max_connections_per_source) {
_cleanup_free_ char *t = NULL;
- sockaddr_pretty(&p->peer.sa, FAMILY_ADDRESS_SIZE(p->peer.sa.sa_family), true, false, &t);
+ (void) sockaddr_pretty(&p->peer.sa, p->peer_salen, true, false, &t);
log_unit_warning(UNIT(s),
"Too many incoming connections (%u) from source %s, dropping connection.",
diff --git a/src/core/triggers.systemd.in b/src/core/triggers.systemd.in
index 0d8c303136..f8c8cbc5f9 100644
--- a/src/core/triggers.systemd.in
+++ b/src/core/triggers.systemd.in
@@ -27,11 +27,13 @@
-- installed, because other cases are covered by the *un scriptlets,
-- so sometimes we will reload needlessly.
-pid = posix.fork()
-if pid == 0 then
- assert(posix.exec("%{_bindir}/systemctl", "daemon-reload"))
-elseif pid > 0 then
- posix.wait(pid)
+if posix.access("/run/systemd/system") then
+ pid = posix.fork()
+ if pid == 0 then
+ assert(posix.exec("%{_bindir}/systemctl", "daemon-reload"))
+ elseif pid > 0 then
+ posix.wait(pid)
+ end
end
%transfiletriggerun -p <lua> -- @systemunitdir@ /etc/systemd/system
@@ -48,10 +50,12 @@ end
-- file in %transfiletriggerun and execute the daemon-reload in
-- the first %filetriggerpostun.
-posix.mkdir("%{_localstatedir}/lib")
-posix.mkdir("%{_localstatedir}/lib/rpm-state")
-posix.mkdir("%{_localstatedir}/lib/rpm-state/systemd")
-io.open("%{_localstatedir}/lib/rpm-state/systemd/needs-reload", "w")
+if posix.access("/run/systemd/system") then
+ posix.mkdir("%{_localstatedir}/lib")
+ posix.mkdir("%{_localstatedir}/lib/rpm-state")
+ posix.mkdir("%{_localstatedir}/lib/rpm-state/systemd")
+ io.open("%{_localstatedir}/lib/rpm-state/systemd/needs-reload", "w")
+end
%filetriggerpostun -P 1000100 -p <lua> -- @systemunitdir@ /etc/systemd/system
if posix.access("%{_localstatedir}/lib/rpm-state/systemd/needs-reload") then
diff --git a/src/core/unit.c b/src/core/unit.c
index 5d0b17425b..409668f6d2 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -866,11 +866,15 @@ int unit_add_exec_dependencies(Unit *u, ExecContext *c) {
return 0;
if (c->private_tmp) {
- r = unit_require_mounts_for(u, "/tmp");
- if (r < 0)
- return r;
+ const char *p;
+
+ FOREACH_STRING(p, "/tmp", "/var/tmp") {
+ r = unit_require_mounts_for(u, p);
+ if (r < 0)
+ return r;
+ }
- r = unit_require_mounts_for(u, "/var/tmp");
+ r = unit_add_dependency_by_name(u, UNIT_AFTER, SPECIAL_TMPFILES_SETUP_SERVICE, NULL, true);
if (r < 0)
return r;
}
diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c
index f05544f3d4..e61ef8f249 100644
--- a/src/gpt-auto-generator/gpt-auto-generator.c
+++ b/src/gpt-auto-generator/gpt-auto-generator.c
@@ -669,7 +669,7 @@ static int get_block_device_harder(const char *path, dev_t *dev) {
/* We found a device backed by multiple other devices. We don't really support automatic
* discovery on such setups, with the exception of dm-verity partitions. In this case there are
- * two backing devices: the data partitoin and the hash partition. We are fine with such
+ * two backing devices: the data partition and the hash partition. We are fine with such
* setups, however, only if both partitions are on the same physical device. Hence, let's
* verify this. */
diff --git a/src/journal-remote/journal-gatewayd.c b/src/journal-remote/journal-gatewayd.c
index f75a6f06d2..8ad9738edf 100644
--- a/src/journal-remote/journal-gatewayd.c
+++ b/src/journal-remote/journal-gatewayd.c
@@ -905,7 +905,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "key", required_argument, NULL, ARG_KEY },
{ "cert", required_argument, NULL, ARG_CERT },
{ "trust", required_argument, NULL, ARG_TRUST },
- { "directory", required_argument, NULL, 'D' },
+ { "directory", required_argument, NULL, 'D' },
{}
};
diff --git a/src/journal/journald-server.h b/src/journal/journald-server.h
index de1c48f805..716e758b7c 100644
--- a/src/journal/journald-server.h
+++ b/src/journal/journald-server.h
@@ -179,7 +179,7 @@ void server_dispatch_message(Server *s, struct iovec *iovec, unsigned n, unsigne
void server_driver_message(Server *s, sd_id128_t message_id, const char *format, ...) _printf_(3,0) _sentinel_;
/* gperf lookup function */
-const struct ConfigPerfItem* journald_gperf_lookup(const char *key, unsigned length);
+const struct ConfigPerfItem* journald_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
int config_parse_storage(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c
index 56257c41d4..71967a0f33 100644
--- a/src/journal/sd-journal.c
+++ b/src/journal/sd-journal.c
@@ -1661,6 +1661,9 @@ static int add_search_paths(sd_journal *j) {
NULSTR_FOREACH(p, search_paths)
(void) add_root_directory(j, p, true);
+ if (!(j->flags & SD_JOURNAL_LOCAL_ONLY))
+ (void) add_root_directory(j, "/var/log/journal/remote", true);
+
return 0;
}
diff --git a/src/kernel-install/kernel-install b/src/kernel-install/kernel-install
index a95b9717f0..c7d9f4eea9 100644
--- a/src/kernel-install/kernel-install
+++ b/src/kernel-install/kernel-install
@@ -34,7 +34,7 @@ dropindirs_sort()
local -a files
local f d i
- readarray -t files < <(
+ readarray -t files <<<"$(
for d in "$@"; do
for i in "$d/"*"$suffix"; do
if [[ -e "$i" ]]; then
@@ -42,7 +42,7 @@ dropindirs_sort()
fi
done
done | sort -Vu
- )
+ )"
for f in "${files[@]}"; do
for d in "$@"; do
@@ -104,11 +104,11 @@ fi
ret=0
-readarray -t PLUGINS < <(
+readarray -t PLUGINS <<<"$(
dropindirs_sort ".install" \
"/etc/kernel/install.d" \
"/usr/lib/kernel/install.d"
-)
+)"
case $COMMAND in
add)
diff --git a/src/libsystemd-network/ndisc-router.c b/src/libsystemd-network/ndisc-router.c
index cf56c89d76..845a6b7c6c 100644
--- a/src/libsystemd-network/ndisc-router.c
+++ b/src/libsystemd-network/ndisc-router.c
@@ -459,6 +459,7 @@ _public_ int sd_ndisc_router_prefix_get_preferred_lifetime(sd_ndisc_router *rt,
_public_ int sd_ndisc_router_prefix_get_flags(sd_ndisc_router *rt, uint8_t *ret) {
struct nd_opt_prefix_info *pi;
+ uint8_t flags;
int r;
assert_return(rt, -EINVAL);
@@ -468,7 +469,14 @@ _public_ int sd_ndisc_router_prefix_get_flags(sd_ndisc_router *rt, uint8_t *ret)
if (r < 0)
return r;
- *ret = pi->nd_opt_pi_flags_reserved;
+ flags = pi->nd_opt_pi_flags_reserved;
+
+ if ((flags & ND_OPT_PI_FLAG_AUTO) && (pi->nd_opt_pi_prefix_len != 64)) {
+ log_ndisc("Invalid prefix length, ignoring prefix for stateless autoconfiguration.");
+ flags &= ~ND_OPT_PI_FLAG_AUTO;
+ }
+
+ *ret = flags;
return 0;
}
diff --git a/src/libudev/libudev-util.c b/src/libudev/libudev-util.c
index 574cfeac85..a9819b9db3 100644
--- a/src/libudev/libudev-util.c
+++ b/src/libudev/libudev-util.c
@@ -186,7 +186,7 @@ int util_replace_whitespace(const char *str, char *to, size_t len)
to[j++] = str[i++];
}
to[j] = '\0';
- return 0;
+ return j;
}
/* allow chars in whitelist, plain ascii, hex-escaping and valid utf8 */
diff --git a/src/login/logind.h b/src/login/logind.h
index 086fa1eeb5..7556ee2e48 100644
--- a/src/login/logind.h
+++ b/src/login/logind.h
@@ -182,7 +182,7 @@ int manager_unit_is_active(Manager *manager, const char *unit);
int manager_job_is_active(Manager *manager, const char *path);
/* gperf lookup function */
-const struct ConfigPerfItem* logind_gperf_lookup(const char *key, unsigned length);
+const struct ConfigPerfItem* logind_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
int manager_set_lid_switch_ignore(Manager *m, usec_t until);
diff --git a/src/machine/image-dbus.c b/src/machine/image-dbus.c
index 1891f07586..d5051007fc 100644
--- a/src/machine/image-dbus.c
+++ b/src/machine/image-dbus.c
@@ -293,7 +293,6 @@ int bus_image_method_set_limit(
static int directory_image_get_os_release(Image *image, char ***ret, sd_bus_error *error) {
_cleanup_free_ char *path = NULL;
- _cleanup_close_ int fd = -1;
int r;
assert(image);
diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c
index efb20c3622..31a40d47c3 100644
--- a/src/machine/machinectl.c
+++ b/src/machine/machinectl.c
@@ -243,14 +243,16 @@ static int list_machines(int argc, char *argv[], void *userdata) {
if (name[0] == '.' && !arg_all)
continue;
- if (!GREEDY_REALLOC(machines, n_allocated, n_machines + 1)) {
+ if (!GREEDY_REALLOC0(machines, n_allocated, n_machines + 1)) {
r = log_oom();
goto out;
}
- machines[n_machines].os = NULL;
- machines[n_machines].version_id = NULL;
- r = call_get_os_release(
+ machines[n_machines].name = name;
+ machines[n_machines].class = class;
+ machines[n_machines].service = service;
+
+ (void) call_get_os_release(
bus,
"GetMachineOSRelease",
name,
@@ -258,12 +260,6 @@ static int list_machines(int argc, char *argv[], void *userdata) {
"VERSION_ID\0",
&machines[n_machines].os,
&machines[n_machines].version_id);
- if (r < 0)
- goto out;
-
- machines[n_machines].name = name;
- machines[n_machines].class = class;
- machines[n_machines].service = service;
l = strlen(name);
if (l > max_name)
@@ -331,7 +327,7 @@ static int list_machines(int argc, char *argv[], void *userdata) {
(int) max_version_id, strdash_if_empty(machines[j].version_id));
r = print_addresses(bus, machines[j].name, 0, "", prefix, arg_addrs);
- if (r == -ENOSYS)
+ if (r == -EOPNOTSUPP)
printf("-\n");
}
diff --git a/src/network/netdev/netdev-gperf.gperf b/src/network/netdev/netdev-gperf.gperf
index b3461e39a9..e74ae9eb9f 100644
--- a/src/network/netdev/netdev-gperf.gperf
+++ b/src/network/netdev/netdev-gperf.gperf
@@ -59,6 +59,7 @@ VXLAN.TOS, config_parse_unsigned, 0,
VXLAN.TTL, config_parse_unsigned, 0, offsetof(VxLan, ttl)
VXLAN.MacLearning, config_parse_bool, 0, offsetof(VxLan, learning)
VXLAN.ARPProxy, config_parse_bool, 0, offsetof(VxLan, arp_proxy)
+VXLAN.ReduceARPProxy, config_parse_bool, 0, offsetof(VxLan, arp_proxy)
VXLAN.L2MissNotification, config_parse_bool, 0, offsetof(VxLan, l2miss)
VXLAN.L3MissNotification, config_parse_bool, 0, offsetof(VxLan, l3miss)
VXLAN.RouteShortCircuit, config_parse_bool, 0, offsetof(VxLan, route_short_circuit)
diff --git a/src/network/netdev/netdev.h b/src/network/netdev/netdev.h
index 70ff947b99..37c7431213 100644
--- a/src/network/netdev/netdev.h
+++ b/src/network/netdev/netdev.h
@@ -175,7 +175,7 @@ NetDevKind netdev_kind_from_string(const char *d) _pure_;
int config_parse_netdev_kind(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
/* gperf */
-const struct ConfigPerfItem* network_netdev_gperf_lookup(const char *key, unsigned length);
+const struct ConfigPerfItem* network_netdev_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
/* Macros which append INTERFACE= to the message */
diff --git a/src/network/networkd-conf.h b/src/network/networkd-conf.h
index 93819626ba..1136975a5e 100644
--- a/src/network/networkd-conf.h
+++ b/src/network/networkd-conf.h
@@ -23,7 +23,7 @@ typedef struct Manager Manager;
int manager_parse_config_file(Manager *m);
-const struct ConfigPerfItem* networkd_gperf_lookup(const char *key, unsigned length);
+const struct ConfigPerfItem* networkd_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
int config_parse_duid_type(
const char *unit,
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 8d6992cee8..b993d27c2f 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -1338,6 +1338,58 @@ static int link_set_bridge(Link *link) {
return r;
}
+static int link_bond_set(Link *link) {
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
+ int r;
+
+ assert(link);
+ assert(link->network);
+
+ r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_NEWLINK, link->network->bond->ifindex);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
+
+ r = sd_netlink_message_set_flags(req, NLM_F_REQUEST | NLM_F_ACK);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not set netlink flags: %m");
+
+ r = sd_netlink_message_open_container(req, IFLA_LINKINFO);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append IFLA_PROTINFO attribute: %m");
+
+ r = sd_netlink_message_open_container_union(req, IFLA_INFO_DATA, "bond");
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append IFLA_INFO_DATA attribute: %m");
+
+ if (link->network->active_slave) {
+ r = sd_netlink_message_append_u32(req, IFLA_BOND_ACTIVE_SLAVE, link->ifindex);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append IFLA_BOND_ACTIVE_SLAVE attribute: %m");
+ }
+
+ if (link->network->primary_slave) {
+ r = sd_netlink_message_append_u32(req, IFLA_BOND_PRIMARY, link->ifindex);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append IFLA_BOND_PRIMARY attribute: %m");
+ }
+
+ r = sd_netlink_message_close_container(req);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append IFLA_LINKINFO attribute: %m");
+
+ r = sd_netlink_message_close_container(req);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append IFLA_INFO_DATA attribute: %m");
+
+ r = sd_netlink_call_async(link->manager->rtnl, req, set_flags_handler, link, 0, NULL);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
+
+ link_ref(link);
+
+ return r;
+}
+
static int link_lldp_save(Link *link) {
_cleanup_free_ char *temp_path = NULL;
_cleanup_fclose_ FILE *f = NULL;
@@ -1992,6 +2044,12 @@ static int link_joined(Link *link) {
log_link_error_errno(link, r, "Could not set bridge message: %m");
}
+ if (link->network->bond) {
+ r = link_bond_set(link);
+ if (r < 0)
+ log_link_error_errno(link, r, "Could not set bond message: %m");
+ }
+
if (link->network->use_br_vlan &&
(link->network->bridge || streq_ptr("bridge", link->kind))) {
r = link_set_bridge_vlan(link);
diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c
index 5097ab9d72..bc80c693d0 100644
--- a/src/network/networkd-ndisc.c
+++ b/src/network/networkd-ndisc.c
@@ -133,6 +133,7 @@ static void ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
route->family = AF_INET6;
route->table = link->network->ipv6_accept_ra_route_table;
+ route->priority = link->network->dhcp_route_metric;
route->protocol = RTPROT_RA;
route->pref = preference;
route->gw.in6 = gateway;
@@ -254,6 +255,7 @@ static void ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt)
route->family = AF_INET6;
route->table = link->network->ipv6_accept_ra_route_table;
+ route->priority = link->network->dhcp_route_metric;
route->protocol = RTPROT_RA;
route->flags = RTM_F_PREFIX;
route->dst_prefixlen = prefixlen;
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index c9b9044a14..7b54e81fb8 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -60,10 +60,12 @@ Network.IPForward, config_parse_address_family_boolean_with
Network.IPMasquerade, config_parse_bool, 0, offsetof(Network, ip_masquerade)
Network.IPv6PrivacyExtensions, config_parse_ipv6_privacy_extensions, 0, offsetof(Network, ipv6_privacy_extensions)
Network.IPv6AcceptRA, config_parse_tristate, 0, offsetof(Network, ipv6_accept_ra)
-/* legacy alias for the above */
Network.IPv6AcceptRouterAdvertisements, config_parse_tristate, 0, offsetof(Network, ipv6_accept_ra)
Network.IPv6DuplicateAddressDetection, config_parse_int, 0, offsetof(Network, ipv6_dad_transmits)
Network.IPv6HopLimit, config_parse_int, 0, offsetof(Network, ipv6_hop_limit)
+Network.ActiveSlave, config_parse_bool, 0, offsetof(Network, active_slave)
+Network.PrimarySlave, config_parse_bool, 0, offsetof(Network, primary_slave)
+Network.IPv4ProxyARP, config_parse_tristate, 0, offsetof(Network, proxy_arp)
Network.ProxyARP, config_parse_tristate, 0, offsetof(Network, proxy_arp)
Network.BindCarrier, config_parse_strv, 0, offsetof(Network, bind_carrier)
Address.Address, config_parse_address, 0, 0
diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h
index d13e306add..b7da9d22d4 100644
--- a/src/network/networkd-network.h
+++ b/src/network/networkd-network.h
@@ -167,6 +167,8 @@ struct Network {
int proxy_arp;
bool ipv6_accept_ra_use_dns;
+ bool active_slave;
+ bool primary_slave;
DHCPUseDomains ipv6_accept_ra_use_domains;
uint32_t ipv6_accept_ra_route_table;
@@ -242,7 +244,7 @@ int config_parse_ntp(const char *unit, const char *filename, unsigned line, cons
/* Legacy IPv4LL support */
int config_parse_ipv4ll(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-const struct ConfigPerfItem* network_network_gperf_lookup(const char *key, unsigned length);
+const struct ConfigPerfItem* network_network_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
extern const sd_bus_vtable network_vtable[];
diff --git a/src/nspawn/nspawn-settings.h b/src/nspawn/nspawn-settings.h
index 4bd0c642df..e9ea087191 100644
--- a/src/nspawn/nspawn-settings.h
+++ b/src/nspawn/nspawn-settings.h
@@ -103,7 +103,7 @@ bool settings_private_network(Settings *s);
DEFINE_TRIVIAL_CLEANUP_FUNC(Settings*, settings_free);
-const struct ConfigPerfItem* nspawn_gperf_lookup(const char *key, unsigned length);
+const struct ConfigPerfItem* nspawn_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
int config_parse_capability(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_id128(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index 6246c6d6fa..6396a69c5c 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -1440,12 +1440,9 @@ static int copy_devnodes(const char *dest) {
} else {
if (mknod(to, st.st_mode, st.st_rdev) < 0) {
- /*
- * This is some sort of protection too against
- * recursive userns chown on shared /dev/
- */
+ /* Explicitly warn the user when /dev is already populated. */
if (errno == EEXIST)
- log_notice("%s/dev/ should be an empty directory", dest);
+ log_notice("%s/dev is pre-mounted and pre-populated. If a pre-mounted /dev is provided it needs to be an unpopulated file system.", dest);
if (errno != EPERM)
return log_error_errno(errno, "mknod(%s) failed: %m", to);
@@ -2811,15 +2808,14 @@ static int nspawn_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t r
return 0;
}
-static int setup_sd_notify_parent(sd_event *event, int fd, pid_t *inner_child_pid) {
+static int setup_sd_notify_parent(sd_event *event, int fd, pid_t *inner_child_pid, sd_event_source **notify_event_source) {
int r;
- sd_event_source *notify_event_source;
- r = sd_event_add_io(event, &notify_event_source, fd, EPOLLIN, nspawn_dispatch_notify_fd, inner_child_pid);
+ r = sd_event_add_io(event, notify_event_source, fd, EPOLLIN, nspawn_dispatch_notify_fd, inner_child_pid);
if (r < 0)
return log_error_errno(r, "Failed to allocate notify event source: %m");
- (void) sd_event_source_set_description(notify_event_source, "nspawn-notify");
+ (void) sd_event_source_set_description(*notify_event_source, "nspawn-notify");
return 0;
}
@@ -3084,6 +3080,7 @@ static int run(int master,
uid_shift_socket_pair[2] = { -1, -1 };
_cleanup_close_ int notify_socket= -1;
_cleanup_(barrier_destroy) Barrier barrier = BARRIER_NULL;
+ _cleanup_(sd_event_source_unrefp) sd_event_source *notify_event_source = NULL;
_cleanup_(sd_event_unrefp) sd_event *event = NULL;
_cleanup_(pty_forward_freep) PTYForward *forward = NULL;
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
@@ -3367,7 +3364,7 @@ static int run(int master,
if (r < 0)
return log_error_errno(r, "Failed to get default event source: %m");
- r = setup_sd_notify_parent(event, notify_socket, PID_TO_PTR(*pid));
+ r = setup_sd_notify_parent(event, notify_socket, PID_TO_PTR(*pid), &notify_event_source);
if (r < 0)
return r;
diff --git a/src/nss-mymachines/nss-mymachines.c b/src/nss-mymachines/nss-mymachines.c
index 895f61c462..fac37faea5 100644
--- a/src/nss-mymachines/nss-mymachines.c
+++ b/src/nss-mymachines/nss-mymachines.c
@@ -512,10 +512,8 @@ enum nss_status _nss_mymachines_getpwuid_r(
BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
- if (!uid_is_valid(uid)) {
- r = -EINVAL;
- goto fail;
- }
+ if (!uid_is_valid(uid))
+ goto not_found;
/* We consider all uids < 65536 host uids */
if (uid < HOST_UID_LIMIT)
@@ -686,10 +684,8 @@ enum nss_status _nss_mymachines_getgrgid_r(
BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
- if (!gid_is_valid(gid)) {
- r = -EINVAL;
- goto fail;
- }
+ if (!gid_is_valid(gid))
+ goto not_found;
/* We consider all gids < 65536 host gids */
if (gid < HOST_GID_LIMIT)
diff --git a/src/nss-systemd/nss-systemd.c b/src/nss-systemd/nss-systemd.c
index c80972742b..fd5064c937 100644
--- a/src/nss-systemd/nss-systemd.c
+++ b/src/nss-systemd/nss-systemd.c
@@ -123,10 +123,10 @@ enum nss_status _nss_systemd_getpwnam_r(
assert(name);
assert(pwd);
- if (!valid_user_group_name(name)) {
- r = -EINVAL;
- goto fail;
- }
+ /* If the username is not valid, then we don't know it. Ideally libc would filter these for us anyway. We don't
+ * generate EINVAL here, because it isn't really out business to complain about invalid user names. */
+ if (!valid_user_group_name(name))
+ goto not_found;
/* Synthesize entries for the root and nobody users, in case they are missing in /etc/passwd */
if (streq(name, root_passwd.pw_name)) {
@@ -227,10 +227,8 @@ enum nss_status _nss_systemd_getpwuid_r(
BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
- if (!uid_is_valid(uid)) {
- r = -EINVAL;
- goto fail;
- }
+ if (!uid_is_valid(uid))
+ goto not_found;
/* Synthesize data for the root user and for nobody in case they are missing from /etc/passwd */
if (uid == root_passwd.pw_uid) {
@@ -329,10 +327,8 @@ enum nss_status _nss_systemd_getgrnam_r(
assert(name);
assert(gr);
- if (!valid_user_group_name(name)) {
- r = -EINVAL;
- goto fail;
- }
+ if (!valid_user_group_name(name))
+ goto not_found;
/* Synthesize records for root and nobody, in case they are missing form /etc/group */
if (streq(name, root_group.gr_name)) {
@@ -430,10 +426,8 @@ enum nss_status _nss_systemd_getgrgid_r(
BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
- if (!gid_is_valid(gid)) {
- r = -EINVAL;
- goto fail;
- }
+ if (!gid_is_valid(gid))
+ goto not_found;
/* Synthesize records for root and nobody, in case they are missing from /etc/group */
if (gid == root_group.gr_gid) {
diff --git a/src/resolve/dns-type.c b/src/resolve/dns-type.c
index aaf5ed62c1..d89ae28dcd 100644
--- a/src/resolve/dns-type.c
+++ b/src/resolve/dns-type.c
@@ -29,7 +29,7 @@ typedef const struct {
} dns_type;
static const struct dns_type_name *
-lookup_dns_type (register const char *str, register unsigned int len);
+lookup_dns_type (register const char *str, register GPERF_LEN_TYPE len);
#include "dns_type-from-name.h"
#include "dns_type-to-name.h"
diff --git a/src/resolve/resolved-conf.h b/src/resolve/resolved-conf.h
index fc425a36b2..8184d6cadf 100644
--- a/src/resolve/resolved-conf.h
+++ b/src/resolve/resolved-conf.h
@@ -41,7 +41,7 @@ int manager_parse_search_domains_and_warn(Manager *m, const char *string);
int manager_add_dns_server_by_string(Manager *m, DnsServerType type, const char *word);
int manager_parse_dns_server_string_and_warn(Manager *m, DnsServerType type, const char *string);
-const struct ConfigPerfItem* resolved_gperf_lookup(const char *key, unsigned length);
+const struct ConfigPerfItem* resolved_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
int config_parse_dns_servers(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_search_domains(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
diff --git a/src/resolve/resolved-etc-hosts.c b/src/resolve/resolved-etc-hosts.c
index 40d650949d..0a284825a1 100644
--- a/src/resolve/resolved-etc-hosts.c
+++ b/src/resolve/resolved-etc-hosts.c
@@ -431,8 +431,8 @@ int manager_etc_hosts_lookup(Manager *m, DnsQuestion* q, DnsAnswer **answer) {
for (i = 0; i < bn->n_items; i++) {
_cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
- if ((found_a && bn->items[i]->family != AF_INET) &&
- (found_aaaa && bn->items[i]->family != AF_INET6))
+ if ((!found_a && bn->items[i]->family == AF_INET) ||
+ (!found_aaaa && bn->items[i]->family == AF_INET6))
continue;
r = dns_resource_record_new_address(&rr, bn->items[i]->family, &bn->items[i]->address, bn->name);
@@ -444,5 +444,5 @@ int manager_etc_hosts_lookup(Manager *m, DnsQuestion* q, DnsAnswer **answer) {
return r;
}
- return 1;
+ return found_a || found_aaaa;
}
diff --git a/src/shared/install.c b/src/shared/install.c
index 474426d927..478abac8ab 100644
--- a/src/shared/install.c
+++ b/src/shared/install.c
@@ -1567,18 +1567,12 @@ static int install_info_symlink_wants(
if (strv_isempty(list))
return 0;
- if (unit_name_is_valid(i->name, UNIT_NAME_TEMPLATE)) {
+ if (unit_name_is_valid(i->name, UNIT_NAME_TEMPLATE) && i->default_instance) {
UnitFileInstallInfo instance = {
.type = _UNIT_FILE_TYPE_INVALID,
};
_cleanup_free_ char *path = NULL;
- /* Don't install any symlink if there's no default
- * instance configured */
-
- if (!i->default_instance)
- return 0;
-
r = unit_name_replace_instance(i->name, i->default_instance, &buf);
if (r < 0)
return r;
@@ -1861,7 +1855,7 @@ int unit_file_unmask(
_cleanup_lookup_paths_free_ LookupPaths paths = {};
_cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
- _cleanup_free_ char **todo = NULL;
+ _cleanup_strv_free_ char **todo = NULL;
size_t n_todo = 0, n_allocated = 0;
const char *config_path;
char **i;
@@ -1899,7 +1893,11 @@ int unit_file_unmask(
if (!GREEDY_REALLOC0(todo, n_allocated, n_todo + 2))
return -ENOMEM;
- todo[n_todo++] = *i;
+ todo[n_todo] = strdup(*i);
+ if (!todo[n_todo])
+ return -ENOMEM;
+
+ n_todo++;
}
strv_uniq(todo);
@@ -1947,7 +1945,7 @@ int unit_file_link(
unsigned *n_changes) {
_cleanup_lookup_paths_free_ LookupPaths paths = {};
- _cleanup_free_ char **todo = NULL;
+ _cleanup_strv_free_ char **todo = NULL;
size_t n_todo = 0, n_allocated = 0;
const char *config_path;
char **i;
@@ -1996,7 +1994,11 @@ int unit_file_link(
if (!GREEDY_REALLOC0(todo, n_allocated, n_todo + 2))
return -ENOMEM;
- todo[n_todo++] = *i;
+ todo[n_todo] = strdup(*i);
+ if (!todo[n_todo])
+ return -ENOMEM;
+
+ n_todo++;
}
strv_uniq(todo);
diff --git a/src/shared/path-lookup.c b/src/shared/path-lookup.c
index a23d09967e..586ef64e72 100644
--- a/src/shared/path-lookup.c
+++ b/src/shared/path-lookup.c
@@ -139,7 +139,7 @@ static char** user_dirs(
const char *e;
_cleanup_strv_free_ char **config_dirs = NULL, **data_dirs = NULL;
_cleanup_free_ char *data_home = NULL;
- _cleanup_free_ char **res = NULL;
+ _cleanup_strv_free_ char **res = NULL;
char **tmp;
int r;
diff --git a/src/socket-proxy/socket-proxyd.c b/src/socket-proxy/socket-proxyd.c
index b810891d7d..1b99b7bc82 100644
--- a/src/socket-proxy/socket-proxyd.c
+++ b/src/socket-proxy/socket-proxyd.c
@@ -564,7 +564,7 @@ static void help(void) {
printf("%1$s [HOST:PORT]\n"
"%1$s [SOCKET]\n\n"
"Bidirectionally proxy local sockets to another (possibly remote) socket.\n\n"
- " -c --max-connections= Set the maximum number of connections to be accepted\n"
+ " -c --connections-max= Set the maximum number of connections to be accepted\n"
" -h --help Show this help\n"
" --version Show package version\n",
program_invocation_short_name);
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index f7e85c1ade..8955d5f51f 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -1734,7 +1734,7 @@ static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, cha
if (r < 0)
return bus_log_parse_error(r);
- *deps = ret;
+ *deps = strv_uniq(ret);
ret = NULL;
return 0;
diff --git a/src/test/test-af-list.c b/src/test/test-af-list.c
index aeaa0929b1..e2479133de 100644
--- a/src/test/test-af-list.c
+++ b/src/test/test-af-list.c
@@ -24,7 +24,7 @@
#include "string-util.h"
#include "util.h"
-static const struct af_name* lookup_af(register const char *str, register unsigned int len);
+static const struct af_name* lookup_af(register const char *str, register GPERF_LEN_TYPE len);
#include "af-from-name.h"
#include "af-list.h"
diff --git a/src/test/test-arphrd-list.c b/src/test/test-arphrd-list.c
index f3989ad201..8f4f342faa 100644
--- a/src/test/test-arphrd-list.c
+++ b/src/test/test-arphrd-list.c
@@ -24,7 +24,7 @@
#include "string-util.h"
#include "util.h"
-static const struct arphrd_name* lookup_arphrd(register const char *str, register unsigned int len);
+static const struct arphrd_name* lookup_arphrd(register const char *str, register GPERF_LEN_TYPE len);
#include "arphrd-from-name.h"
#include "arphrd-list.h"
diff --git a/src/test/test-calendarspec.c b/src/test/test-calendarspec.c
index 5fd749a6a8..1f34a91b10 100644
--- a/src/test/test-calendarspec.c
+++ b/src/test/test-calendarspec.c
@@ -238,6 +238,8 @@ int main(int argc, char* argv[]) {
assert_se(calendar_spec_from_string("*:05..10/6", &c) < 0);
assert_se(calendar_spec_from_string("20/4:00", &c) < 0);
assert_se(calendar_spec_from_string("00:00/60", &c) < 0);
+ assert_se(calendar_spec_from_string("00:00:2300", &c) < 0);
+ assert_se(calendar_spec_from_string("00:00:18446744073709551615", &c) < 0);
test_timestamp();
test_hourly_bug_4031();
diff --git a/src/test/test-selinux.c b/src/test/test-selinux.c
index 7545ad3764..b676c25913 100644
--- a/src/test/test-selinux.c
+++ b/src/test/test-selinux.c
@@ -56,7 +56,7 @@ static void test_loading(void) {
n1 = now(CLOCK_MONOTONIC);
r = mac_selinux_init();
n2 = now(CLOCK_MONOTONIC);
- log_info_errno(r, "mac_selinux_init → %d (%m) %.2fs", r, (n2 - n1)/1e6);
+ log_info_errno(r, "mac_selinux_init → %d %.2fs (%m)", r, (n2 - n1)/1e6);
}
static void test_cleanup(void) {
@@ -78,18 +78,18 @@ static void test_misc(const char* fname) {
log_info("============ %s ==========", __func__);
r = mac_selinux_get_our_label(&label);
- log_info_errno(r, "mac_selinux_get_our_label → %d (%m), \"%s\"",
+ log_info_errno(r, "mac_selinux_get_our_label → %d, \"%s\" (%m)",
r, strnull(label));
r = mac_selinux_get_create_label_from_exe(fname, &label2);
- log_info_errno(r, "mac_selinux_create_label_from_exe → %d (%m), \"%s\"",
+ log_info_errno(r, "mac_selinux_create_label_from_exe → %d, \"%s\" (%m)",
r, strnull(label2));
fd = socket(AF_INET, SOCK_DGRAM, 0);
assert_se(fd >= 0);
r = mac_selinux_get_child_mls_label(fd, fname, label2, &label3);
- log_info_errno(r, "mac_selinux_get_child_mls_label → %d (%m), \"%s\"",
+ log_info_errno(r, "mac_selinux_get_child_mls_label → %d, \"%s\" (%m)",
r, strnull(label3));
}
diff --git a/src/test/test-socket-util.c b/src/test/test-socket-util.c
index 1f853a7f16..d80613dc84 100644
--- a/src/test/test-socket-util.c
+++ b/src/test/test-socket-util.c
@@ -92,6 +92,14 @@ static void test_socket_address_parse(void) {
assert_se(socket_address_parse(&a, "@abstract") >= 0);
assert_se(a.sockaddr.sa.sa_family == AF_UNIX);
+
+ assert_se(socket_address_parse(&a, "vsock::1234") >= 0);
+ assert_se(a.sockaddr.sa.sa_family == AF_VSOCK);
+ assert_se(socket_address_parse(&a, "vsock:2:1234") >= 0);
+ assert_se(a.sockaddr.sa.sa_family == AF_VSOCK);
+ assert_se(socket_address_parse(&a, "vsock:2:1234x") < 0);
+ assert_se(socket_address_parse(&a, "vsock:2x:1234") < 0);
+ assert_se(socket_address_parse(&a, "vsock:2") < 0);
}
static void test_socket_address_parse_netlink(void) {
@@ -145,6 +153,14 @@ static void test_socket_address_equal(void) {
assert_se(socket_address_parse_netlink(&a, "firewall") >= 0);
assert_se(socket_address_parse_netlink(&b, "firewall") >= 0);
assert_se(socket_address_equal(&a, &b));
+
+ assert_se(socket_address_parse(&a, "vsock:2:1234") >= 0);
+ assert_se(socket_address_parse(&b, "vsock:2:1234") >= 0);
+ assert_se(socket_address_equal(&a, &b));
+ assert_se(socket_address_parse(&b, "vsock:2:1235") >= 0);
+ assert_se(!socket_address_equal(&a, &b));
+ assert_se(socket_address_parse(&b, "vsock:3:1234") >= 0);
+ assert_se(!socket_address_equal(&a, &b));
}
static void test_socket_address_get_path(void) {
@@ -161,6 +177,9 @@ static void test_socket_address_get_path(void) {
assert_se(socket_address_parse(&a, "/foo/bar") >= 0);
assert_se(streq(socket_address_get_path(&a), "/foo/bar"));
+
+ assert_se(socket_address_parse(&a, "vsock:2:1234") >= 0);
+ assert_se(!socket_address_get_path(&a));
}
static void test_socket_address_is(void) {
@@ -408,11 +427,18 @@ static void test_sockaddr_equal(void) {
.in6.sin6_port = 0,
.in6.sin6_addr = IN6ADDR_ANY_INIT,
};
+ union sockaddr_union e = {
+ .vm.svm_family = AF_VSOCK,
+ .vm.svm_port = 0,
+ .vm.svm_cid = VMADDR_CID_ANY,
+ };
assert_se(sockaddr_equal(&a, &a));
assert_se(sockaddr_equal(&a, &b));
assert_se(sockaddr_equal(&d, &d));
+ assert_se(sockaddr_equal(&e, &e));
assert_se(!sockaddr_equal(&a, &c));
assert_se(!sockaddr_equal(&b, &c));
+ assert_se(!sockaddr_equal(&a, &e));
}
static void test_sockaddr_un_len(void) {
diff --git a/src/timesync/timesyncd-conf.h b/src/timesync/timesyncd-conf.h
index cba0724b1b..0280697e9c 100644
--- a/src/timesync/timesyncd-conf.h
+++ b/src/timesync/timesyncd-conf.h
@@ -22,7 +22,7 @@
#include "conf-parser.h"
#include "timesyncd-manager.h"
-const struct ConfigPerfItem* timesyncd_gperf_lookup(const char *key, unsigned length);
+const struct ConfigPerfItem* timesyncd_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
int manager_parse_server_string(Manager *m, ServerType type, const char *string);
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
index 79f75e165b..f4ce9791fb 100644
--- a/src/tmpfiles/tmpfiles.c
+++ b/src/tmpfiles/tmpfiles.c
@@ -649,7 +649,7 @@ static int path_set_perms(Item *i, const char *path) {
else {
log_debug("chmod \"%s\" to mode %o", path, m);
if (chmod(fn, m) < 0)
- return log_error_errno(errno, "chmod(%s) failed: %m", path);
+ return log_error_errno(errno, "chmod() of %s via %s failed: %m", path, fn);
}
}
@@ -662,7 +662,7 @@ static int path_set_perms(Item *i, const char *path) {
if (chown(fn,
i->uid_set ? i->uid : UID_INVALID,
i->gid_set ? i->gid : GID_INVALID) < 0)
- return log_error_errno(errno, "chown(%s) failed: %m", path);
+ return log_error_errno(errno, "chown() of %s via %s failed: %m", path, fn);
}
}
diff --git a/src/udev/net/link-config.h b/src/udev/net/link-config.h
index a99060d943..5a25cec6fd 100644
--- a/src/udev/net/link-config.h
+++ b/src/udev/net/link-config.h
@@ -94,7 +94,7 @@ const char *mac_policy_to_string(MACPolicy p) _const_;
MACPolicy mac_policy_from_string(const char *p) _pure_;
/* gperf lookup function */
-const struct ConfigPerfItem* link_config_gperf_lookup(const char *key, unsigned length);
+const struct ConfigPerfItem* link_config_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
int config_parse_mac_policy(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_name_policy(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
diff --git a/src/udev/udev-builtin-input_id.c b/src/udev/udev-builtin-input_id.c
index 59b9804dc4..51f364bf94 100644
--- a/src/udev/udev-builtin-input_id.c
+++ b/src/udev/udev-builtin-input_id.c
@@ -323,6 +323,9 @@ static int builtin_input_id(struct udev_device *dev, int argc, char *argv[], boo
if (!is_pointer && !is_key && test_bit(EV_REL, bitmask_ev) &&
(test_bit(REL_WHEEL, bitmask_rel) || test_bit(REL_HWHEEL, bitmask_rel)))
udev_builtin_add_property(dev, test, "ID_INPUT_KEY", "1");
+ if (test_bit(EV_SW, bitmask_ev))
+ udev_builtin_add_property(dev, test, "ID_INPUT_SWITCH", "1");
+
}
devnode = udev_device_get_devnode(dev);
diff --git a/src/udev/udev-builtin-keyboard.c b/src/udev/udev-builtin-keyboard.c
index aa10beafb0..09024116f2 100644
--- a/src/udev/udev-builtin-keyboard.c
+++ b/src/udev/udev-builtin-keyboard.c
@@ -29,7 +29,7 @@
#include "string-util.h"
#include "udev.h"
-static const struct key *keyboard_lookup_key(const char *str, unsigned len);
+static const struct key *keyboard_lookup_key(const char *str, GPERF_LEN_TYPE len);
#include "keyboard-keys-from-name.h"
static int install_force_release(struct udev_device *dev, const unsigned *release, unsigned release_count) {
diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c
index 304a28777b..be7c7367ff 100644
--- a/src/udev/udev-event.c
+++ b/src/udev/udev-event.c
@@ -73,7 +73,9 @@ void udev_event_unref(struct udev_event *event) {
free(event);
}
-size_t udev_event_apply_format(struct udev_event *event, const char *src, char *dest, size_t size) {
+size_t udev_event_apply_format(struct udev_event *event,
+ const char *src, char *dest, size_t size,
+ bool replace_whitespace) {
struct udev_device *dev = event->dev;
enum subst_type {
SUBST_UNKNOWN,
@@ -130,8 +132,10 @@ size_t udev_event_apply_format(struct udev_event *event, const char *src, char *
for (;;) {
enum subst_type type = SUBST_UNKNOWN;
- char attrbuf[UTIL_PATH_SIZE];
- char *attr = NULL;
+ char attrbuf[UTIL_PATH_SIZE], sbuf[UTIL_PATH_SIZE];
+ char *attr = NULL, *_s;
+ size_t _l;
+ bool replws = replace_whitespace;
while (from[0] != '\0') {
if (from[0] == '$') {
@@ -200,6 +204,19 @@ subst:
attr = NULL;
}
+ /* result subst handles space as field separator */
+ if (type == SUBST_RESULT)
+ replws = false;
+
+ if (replws) {
+ /* store dest string ptr and remaining len */
+ _s = s;
+ _l = l;
+ /* temporarily use sbuf */
+ s = &sbuf;
+ l = UTIL_PATH_SIZE;
+ }
+
switch (type) {
case SUBST_DEVPATH:
l = strpcpy(&s, l, udev_device_get_devpath(dev));
@@ -380,6 +397,20 @@ subst:
log_error("unknown substitution type=%i", type);
break;
}
+
+ /* replace whitespace in sbuf and copy to dest */
+ if (replws) {
+ size_t tmplen = UTIL_PATH_SIZE - l;
+
+ /* restore s and l to dest string values */
+ s = _s;
+ l = _l;
+
+ /* copy ws-replaced value to s */
+ tmplen = util_replace_whitespace(sbuf, s, MIN(tmplen, l));
+ l -= tmplen;
+ s += tmplen;
+ }
}
out:
@@ -927,7 +958,7 @@ void udev_event_execute_run(struct udev_event *event, usec_t timeout_usec, usec_
const char *cmd = udev_list_entry_get_name(list_entry);
enum udev_builtin_cmd builtin_cmd = udev_list_entry_get_num(list_entry);
- udev_event_apply_format(event, cmd, command, sizeof(command));
+ udev_event_apply_format(event, cmd, command, sizeof(command), false);
if (builtin_cmd < UDEV_BUILTIN_MAX)
udev_builtin_run(event->dev, builtin_cmd, command, false);
diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c
index b0238220e4..4d07b8fce0 100644
--- a/src/udev/udev-rules.c
+++ b/src/udev/udev-rules.c
@@ -1676,7 +1676,7 @@ static int match_attr(struct udev_rules *rules, struct udev_device *dev, struct
name = rules_str(rules, cur->key.attr_off);
switch (cur->key.attrsubst) {
case SB_FORMAT:
- udev_event_apply_format(event, name, nbuf, sizeof(nbuf));
+ udev_event_apply_format(event, name, nbuf, sizeof(nbuf), false);
name = nbuf;
/* fall through */
case SB_NONE:
@@ -1838,7 +1838,7 @@ void udev_rules_apply_to_event(struct udev_rules *rules,
_cleanup_free_ char *value = NULL;
size_t len;
- udev_event_apply_format(event, rules_str(rules, cur->key.attr_off), filename, sizeof(filename));
+ udev_event_apply_format(event, rules_str(rules, cur->key.attr_off), filename, sizeof(filename), false);
sysctl_normalize(filename);
if (sysctl_read(filename, &value) < 0)
goto nomatch;
@@ -1916,7 +1916,7 @@ void udev_rules_apply_to_event(struct udev_rules *rules,
struct stat statbuf;
int match;
- udev_event_apply_format(event, rules_str(rules, cur->key.value_off), filename, sizeof(filename));
+ udev_event_apply_format(event, rules_str(rules, cur->key.value_off), filename, sizeof(filename), false);
if (util_resolve_subsys_kernel(event->udev, filename, filename, sizeof(filename), 0) != 0) {
if (filename[0] != '/') {
char tmp[UTIL_PATH_SIZE];
@@ -1942,7 +1942,7 @@ void udev_rules_apply_to_event(struct udev_rules *rules,
char result[UTIL_LINE_SIZE];
event->program_result = mfree(event->program_result);
- udev_event_apply_format(event, rules_str(rules, cur->key.value_off), program, sizeof(program));
+ udev_event_apply_format(event, rules_str(rules, cur->key.value_off), program, sizeof(program), false);
log_debug("PROGRAM '%s' %s:%u",
program,
rules_str(rules, rule->rule.filename_off),
@@ -1969,7 +1969,7 @@ void udev_rules_apply_to_event(struct udev_rules *rules,
case TK_M_IMPORT_FILE: {
char import[UTIL_PATH_SIZE];
- udev_event_apply_format(event, rules_str(rules, cur->key.value_off), import, sizeof(import));
+ udev_event_apply_format(event, rules_str(rules, cur->key.value_off), import, sizeof(import), false);
if (import_file_into_properties(event->dev, import) != 0)
if (cur->key.op != OP_NOMATCH)
goto nomatch;
@@ -1978,7 +1978,7 @@ void udev_rules_apply_to_event(struct udev_rules *rules,
case TK_M_IMPORT_PROG: {
char import[UTIL_PATH_SIZE];
- udev_event_apply_format(event, rules_str(rules, cur->key.value_off), import, sizeof(import));
+ udev_event_apply_format(event, rules_str(rules, cur->key.value_off), import, sizeof(import), false);
log_debug("IMPORT '%s' %s:%u",
import,
rules_str(rules, rule->rule.filename_off),
@@ -2009,7 +2009,7 @@ void udev_rules_apply_to_event(struct udev_rules *rules,
event->builtin_run |= (1 << cur->key.builtin_cmd);
}
- udev_event_apply_format(event, rules_str(rules, cur->key.value_off), command, sizeof(command));
+ udev_event_apply_format(event, rules_str(rules, cur->key.value_off), command, sizeof(command), false);
log_debug("IMPORT builtin '%s' %s:%u",
udev_builtin_name(cur->key.builtin_cmd),
rules_str(rules, rule->rule.filename_off),
@@ -2077,7 +2077,7 @@ void udev_rules_apply_to_event(struct udev_rules *rules,
case TK_M_IMPORT_PARENT: {
char import[UTIL_PATH_SIZE];
- udev_event_apply_format(event, rules_str(rules, cur->key.value_off), import, sizeof(import));
+ udev_event_apply_format(event, rules_str(rules, cur->key.value_off), import, sizeof(import), false);
if (import_parent_into_properties(event->dev, import) != 0)
if (cur->key.op != OP_NOMATCH)
goto nomatch;
@@ -2115,7 +2115,7 @@ void udev_rules_apply_to_event(struct udev_rules *rules,
break;
if (cur->key.op == OP_ASSIGN_FINAL)
event->owner_final = true;
- udev_event_apply_format(event, rules_str(rules, cur->key.value_off), owner, sizeof(owner));
+ udev_event_apply_format(event, rules_str(rules, cur->key.value_off), owner, sizeof(owner), false);
event->owner_set = true;
r = get_user_creds(&ow, &event->uid, NULL, NULL, NULL);
if (r < 0) {
@@ -2141,7 +2141,7 @@ void udev_rules_apply_to_event(struct udev_rules *rules,
break;
if (cur->key.op == OP_ASSIGN_FINAL)
event->group_final = true;
- udev_event_apply_format(event, rules_str(rules, cur->key.value_off), group, sizeof(group));
+ udev_event_apply_format(event, rules_str(rules, cur->key.value_off), group, sizeof(group), false);
event->group_set = true;
r = get_group_creds(&gr, &event->gid);
if (r < 0) {
@@ -2165,7 +2165,7 @@ void udev_rules_apply_to_event(struct udev_rules *rules,
if (event->mode_final)
break;
- udev_event_apply_format(event, rules_str(rules, cur->key.value_off), mode_str, sizeof(mode_str));
+ udev_event_apply_format(event, rules_str(rules, cur->key.value_off), mode_str, sizeof(mode_str), false);
mode = strtol(mode_str, &endptr, 8);
if (endptr[0] != '\0') {
log_error("ignoring invalid mode '%s'", mode_str);
@@ -2222,7 +2222,7 @@ void udev_rules_apply_to_event(struct udev_rules *rules,
const char *name, *label;
name = rules_str(rules, cur->key.attr_off);
- udev_event_apply_format(event, rules_str(rules, cur->key.value_off), label_str, sizeof(label_str));
+ udev_event_apply_format(event, rules_str(rules, cur->key.value_off), label_str, sizeof(label_str), false);
if (label_str[0] != '\0')
label = label_str;
else
@@ -2256,10 +2256,10 @@ void udev_rules_apply_to_event(struct udev_rules *rules,
char temp[UTIL_NAME_SIZE];
/* append value separated by space */
- udev_event_apply_format(event, value, temp, sizeof(temp));
+ udev_event_apply_format(event, value, temp, sizeof(temp), false);
strscpyl(value_new, sizeof(value_new), value_old, " ", temp, NULL);
} else
- udev_event_apply_format(event, value, value_new, sizeof(value_new));
+ udev_event_apply_format(event, value, value_new, sizeof(value_new), false);
udev_device_add_property(event->dev, name, value_new);
break;
@@ -2268,7 +2268,7 @@ void udev_rules_apply_to_event(struct udev_rules *rules,
char tag[UTIL_PATH_SIZE];
const char *p;
- udev_event_apply_format(event, rules_str(rules, cur->key.value_off), tag, sizeof(tag));
+ udev_event_apply_format(event, rules_str(rules, cur->key.value_off), tag, sizeof(tag), false);
if (cur->key.op == OP_ASSIGN || cur->key.op == OP_ASSIGN_FINAL)
udev_device_cleanup_tags_list(event->dev);
for (p = tag; *p != '\0'; p++) {
@@ -2296,7 +2296,7 @@ void udev_rules_apply_to_event(struct udev_rules *rules,
break;
if (cur->key.op == OP_ASSIGN_FINAL)
event->name_final = true;
- udev_event_apply_format(event, name, name_str, sizeof(name_str));
+ udev_event_apply_format(event, name, name_str, sizeof(name_str), false);
if (esc == ESCAPE_UNSET || esc == ESCAPE_REPLACE) {
count = util_replace_chars(name_str, "/");
if (count > 0)
@@ -2336,7 +2336,7 @@ void udev_rules_apply_to_event(struct udev_rules *rules,
udev_device_cleanup_devlinks_list(event->dev);
/* allow multiple symlinks separated by spaces */
- udev_event_apply_format(event, rules_str(rules, cur->key.value_off), temp, sizeof(temp));
+ udev_event_apply_format(event, rules_str(rules, cur->key.value_off), temp, sizeof(temp), esc != ESCAPE_NONE);
if (esc == ESCAPE_UNSET)
count = util_replace_chars(temp, "/ ");
else if (esc == ESCAPE_REPLACE)
@@ -2376,7 +2376,7 @@ void udev_rules_apply_to_event(struct udev_rules *rules,
strscpyl(attr, sizeof(attr), udev_device_get_syspath(event->dev), "/", key_name, NULL);
attr_subst_subdir(attr, sizeof(attr));
- udev_event_apply_format(event, rules_str(rules, cur->key.value_off), value, sizeof(value));
+ udev_event_apply_format(event, rules_str(rules, cur->key.value_off), value, sizeof(value), false);
log_debug("ATTR '%s' writing '%s' %s:%u", attr, value,
rules_str(rules, rule->rule.filename_off),
rule->rule.filename_line);
@@ -2392,9 +2392,9 @@ void udev_rules_apply_to_event(struct udev_rules *rules,
char value[UTIL_NAME_SIZE];
int r;
- udev_event_apply_format(event, rules_str(rules, cur->key.attr_off), filename, sizeof(filename));
+ udev_event_apply_format(event, rules_str(rules, cur->key.attr_off), filename, sizeof(filename), false);
sysctl_normalize(filename);
- udev_event_apply_format(event, rules_str(rules, cur->key.value_off), value, sizeof(value));
+ udev_event_apply_format(event, rules_str(rules, cur->key.value_off), value, sizeof(value), false);
log_debug("SYSCTL '%s' writing '%s' %s:%u", filename, value,
rules_str(rules, rule->rule.filename_off), rule->rule.filename_line);
r = sysctl_write(filename, value);
diff --git a/src/udev/udev.h b/src/udev/udev.h
index 8433e8d9f2..c0cb7eae84 100644
--- a/src/udev/udev.h
+++ b/src/udev/udev.h
@@ -80,7 +80,9 @@ int udev_rules_apply_static_dev_perms(struct udev_rules *rules);
/* udev-event.c */
struct udev_event *udev_event_new(struct udev_device *dev);
void udev_event_unref(struct udev_event *event);
-size_t udev_event_apply_format(struct udev_event *event, const char *src, char *dest, size_t size);
+size_t udev_event_apply_format(struct udev_event *event,
+ const char *src, char *dest, size_t size,
+ bool replace_whitespace);
int udev_event_apply_subsys_kernel(struct udev_event *event, const char *string,
char *result, size_t maxsize, int read_value);
int udev_event_spawn(struct udev_event *event,
diff --git a/src/udev/udevadm-test.c b/src/udev/udevadm-test.c
index 702dbe5282..07b667f131 100644
--- a/src/udev/udevadm-test.c
+++ b/src/udev/udevadm-test.c
@@ -144,7 +144,7 @@ static int adm_test(struct udev *udev, int argc, char *argv[]) {
udev_list_entry_foreach(entry, udev_list_get_entry(&event->run_list)) {
char program[UTIL_PATH_SIZE];
- udev_event_apply_format(event, udev_list_entry_get_name(entry), program, sizeof(program));
+ udev_event_apply_format(event, udev_list_entry_get_name(entry), program, sizeof(program), false);
printf("run: '%s'\n", program);
}
out: