diff --git a/man/sd_bus_message_open_container.xml b/man/sd_bus_message_open_container.xml index 5a6551871..64fda41b1 100644 --- a/man/sd_bus_message_open_container.xml +++ b/man/sd_bus_message_open_container.xml @@ -80,7 +80,7 @@ m itself if there is no parent container. sd_bus_message_enter_container() enters the next container of the message - m. It behaves mostly the same as + m for reading. It behaves mostly the same as sd_bus_message_open_container(). Entering a container allows reading its contents with sd_bus_message_read3 @@ -89,7 +89,12 @@ sd_bus_message_exit_container() exits the scope of the last container entered with sd_bus_message_enter_container(). It behaves mostly the same as - sd_bus_message_close_container(). + sd_bus_message_close_container(). Note that + sd_bus_message_exit_container() may only be called after iterating through all + members of the container, i.e. reading or skipping them. Use + sd_bus_message_skip3 + to skip over felds of a container in order to be able to exit the container with + sd_bus_message_exit_container() without reading all members. @@ -128,6 +133,13 @@ Memory allocation failed. + + + -EBUSY + + sd_bus_message_exit_container() was called but there are + unread members left in the container. + @@ -158,6 +170,7 @@ sd-bus3, sd_bus_message_append3, sd_bus_message_read3, + sd_bus_message_skip3, The D-Bus specification diff --git a/man/systemd.timer.xml b/man/systemd.timer.xml index 582240271..32ddb1c6e 100644 --- a/man/systemd.timer.xml +++ b/man/systemd.timer.xml @@ -297,9 +297,10 @@ Takes a boolean argument. If true, the time when the service unit was last triggered is stored on disk. When the timer is activated, the service unit is triggered immediately if it - would have been triggered at least once during the time when the timer was inactive. This is useful - to catch up on missed runs of the service when the system was powered down. Note that this setting - only has an effect on timers configured with OnCalendar=. Defaults to + would have been triggered at least once during the time when the timer was inactive. Such triggering + is nonetheless subject to the delay imposed by RandomizedDelaySec=. + This is useful to catch up on missed runs of the service when the system was powered down. Note that + this setting only has an effect on timers configured with OnCalendar=. Defaults to false. Use systemctl clean --what=state … on the timer unit to remove the timestamp diff --git a/man/sysusers.d.xml b/man/sysusers.d.xml index 38a95d6e1..2d5023dc9 100644 --- a/man/sysusers.d.xml +++ b/man/sysusers.d.xml @@ -27,12 +27,12 @@ /usr/lib/sysusers.d/*.conf -#Type Name ID GECOS Home directory Shell -u user_name uid "User Description" /path/to/shell -u user_name uid:gid - - -u user_name /file/owned/by/user - - -g group_name gid "Group Description" -g group_name /file/owned/by/group - +#Type Name ID GECOS Home directory Shell +u user_name uid "User Description" /home/dir /path/to/shell +u user_name uid:gid "User Description" /home/dir /path/to/shell +u user_name /file/owned/by/user "User Description" /home/dir /path/to/shell +g group_name gid +g group_name /file/owned/by/group m user_name group_name r - lowest-highest diff --git a/meson.build b/meson.build index ba9e7afe5..e928b10be 100644 --- a/meson.build +++ b/meson.build @@ -227,6 +227,7 @@ conf.set_quoted('SYSTEMCTL_BINARY_PATH', join_paths(rootbin conf.set_quoted('SYSTEMD_TTY_ASK_PASSWORD_AGENT_BINARY_PATH', join_paths(rootbindir, 'systemd-tty-ask-password-agent')) conf.set_quoted('SYSTEMD_STDIO_BRIDGE_BINARY_PATH', join_paths(bindir, 'systemd-stdio-bridge')) conf.set_quoted('ROOTPREFIX', rootprefixdir) +conf.set_quoted('ROOTPREFIX_NOSLASH', rootprefixdir_noslash) conf.set_quoted('RANDOM_SEED_DIR', randomseeddir) conf.set_quoted('RANDOM_SEED', join_paths(randomseeddir, 'random-seed')) conf.set_quoted('SYSTEMD_CRYPTSETUP_PATH', join_paths(rootlibexecdir, 'systemd-cryptsetup')) diff --git a/shell-completion/bash/resolvectl b/shell-completion/bash/resolvectl index d4ac33903..54b241ce9 100644 --- a/shell-completion/bash/resolvectl +++ b/shell-completion/bash/resolvectl @@ -48,6 +48,7 @@ _resolvectl() { [DNSSEC]='dnssec' [DNSOVERTLS]='dnsovertls' [STANDALONE]='statistics reset-statistics flush-caches reset-server-features' + [LOG_LEVEL]='log-level' ) local -A ARGS=( [FAMILY]='tcp udp sctp' @@ -95,6 +96,9 @@ _resolvectl() { elif __contains_word "$verb" ${VERBS[STATUS]}; then comps="$interfaces" + elif __contains_word "$verb" ${VERBS[LOG_LEVEL]}; then + comps='debug info notice warning err crit alert emerg' + elif __contains_word "$verb" ${VERBS[FAMILY]}; then for ((i++; i < COMP_CWORD; i++)); do if __contains_word "${COMP_WORDS[i]}" ${ARGS[FAMILY]} && diff --git a/src/backlight/backlight.c b/src/backlight/backlight.c index 3a644363e..388bd0367 100644 --- a/src/backlight/backlight.c +++ b/src/backlight/backlight.c @@ -284,7 +284,8 @@ static bool shall_clamp(sd_device *d) { r = sd_device_get_property_value(d, "ID_BACKLIGHT_CLAMP", &s); if (r < 0) { - log_device_debug_errno(d, r, "Failed to get ID_BACKLIGHT_CLAMP property, ignoring: %m"); + if (r != -ENOENT) + log_device_debug_errno(d, r, "Failed to get ID_BACKLIGHT_CLAMP property, ignoring: %m"); return true; } diff --git a/src/basic/btrfs-util.c b/src/basic/btrfs-util.c index 71e1bc92e..7de777073 100644 --- a/src/basic/btrfs-util.c +++ b/src/basic/btrfs-util.c @@ -315,6 +315,15 @@ int btrfs_get_block_device_fd(int fd, dev_t *dev) { return -errno; } + /* For the root fs — when no initrd is involved — btrfs returns /dev/root on any kernels from + * the past few years. That sucks, as we have no API to determine the actual root then. let's + * return an recognizable error for this case, so that the caller can maybe print a nice + * message about this. + * + * https://bugzilla.kernel.org/show_bug.cgi?id=89721 */ + if (path_equal((char*) di.path, "/dev/root")) + return -EUCLEAN; + if (stat((char*) di.path, &st) < 0) return -errno; diff --git a/src/basic/btrfs-util.h b/src/basic/btrfs-util.h index c1bbb42ca..d9cb95af0 100644 --- a/src/basic/btrfs-util.h +++ b/src/basic/btrfs-util.h @@ -121,3 +121,9 @@ int btrfs_qgroup_find_parents(int fd, uint64_t qgroupid, uint64_t **ret); int btrfs_qgroup_get_quota_fd(int fd, uint64_t qgroupid, BtrfsQuotaInfo *quota); int btrfs_qgroup_get_quota(const char *path, uint64_t qgroupid, BtrfsQuotaInfo *quota); + +static inline int btrfs_log_dev_root(int level, int ret, const char *p) { + return log_full_errno(level, ret, + "File system behind %s is reported by btrfs to be backed by pseudo-device /dev/root, which is not a valid userspace accessible device node. " + "Cannot determine correct backing block device.", p); +} diff --git a/src/basic/capability-util.c b/src/basic/capability-util.c index 5a4d020f5..ae269e8a8 100644 --- a/src/basic/capability-util.c +++ b/src/basic/capability-util.c @@ -161,28 +161,21 @@ int capability_ambient_set_apply(uint64_t set, bool also_inherit) { return 0; } -int capability_bounding_set_drop(uint64_t keep, bool right_now) { - _cleanup_cap_free_ cap_t before_cap = NULL, after_cap = NULL; +int capability_gain_cap_setpcap(cap_t *ret_before_caps) { + _cleanup_cap_free_ cap_t caps = NULL; cap_flag_value_t fv; - int r; - - /* If we are run as PID 1 we will lack CAP_SETPCAP by default - * in the effective set (yes, the kernel drops that when - * executing init!), so get it back temporarily so that we can - * call PR_CAPBSET_DROP. */ - - before_cap = cap_get_proc(); - if (!before_cap) + caps = cap_get_proc(); + if (!caps) return -errno; - if (cap_get_flag(before_cap, CAP_SETPCAP, CAP_EFFECTIVE, &fv) < 0) + if (cap_get_flag(caps, CAP_SETPCAP, CAP_EFFECTIVE, &fv) < 0) return -errno; if (fv != CAP_SET) { _cleanup_cap_free_ cap_t temp_cap = NULL; static const cap_value_t v = CAP_SETPCAP; - temp_cap = cap_dup(before_cap); + temp_cap = cap_dup(caps); if (!temp_cap) return -errno; @@ -193,8 +186,27 @@ int capability_bounding_set_drop(uint64_t keep, bool right_now) { log_debug_errno(errno, "Can't acquire effective CAP_SETPCAP bit, ignoring: %m"); /* If we didn't manage to acquire the CAP_SETPCAP bit, we continue anyway, after all this just means - * we'll fail later, when we actually intend to drop some capabilities. */ + * we'll fail later, when we actually intend to drop some capabilities or try to set securebits. */ } + if (ret_before_caps) + /* Return the capabilities as they have been before setting CAP_SETPCAP */ + *ret_before_caps = TAKE_PTR(caps); + + return 0; +} + +int capability_bounding_set_drop(uint64_t keep, bool right_now) { + _cleanup_cap_free_ cap_t before_cap = NULL, after_cap = NULL; + int r; + + /* If we are run as PID 1 we will lack CAP_SETPCAP by default + * in the effective set (yes, the kernel drops that when + * executing init!), so get it back temporarily so that we can + * call PR_CAPBSET_DROP. */ + + r = capability_gain_cap_setpcap(&before_cap); + if (r < 0) + return r; after_cap = cap_dup(before_cap); if (!after_cap) diff --git a/src/basic/capability-util.h b/src/basic/capability-util.h index fcc59daed..fdf6ef846 100644 --- a/src/basic/capability-util.h +++ b/src/basic/capability-util.h @@ -14,6 +14,7 @@ unsigned cap_last_cap(void); int have_effective_cap(int value); +int capability_gain_cap_setpcap(cap_t *return_caps); int capability_bounding_set_drop(uint64_t keep, bool right_now); int capability_bounding_set_drop_usermode(uint64_t keep); diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c index 34a226078..461bc04e5 100644 --- a/src/basic/fs-util.c +++ b/src/basic/fs-util.c @@ -229,6 +229,7 @@ int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) { int fchmod_and_chown(int fd, mode_t mode, uid_t uid, gid_t gid) { bool do_chown, do_chmod; struct stat st; + int r; /* Change ownership and access mode of the specified fd. Tries to do so safely, ensuring that at no * point in time the access mode is above the old access mode under the old ownership or the new @@ -259,18 +260,22 @@ int fchmod_and_chown(int fd, mode_t mode, uid_t uid, gid_t gid) { if (do_chown && do_chmod) { mode_t minimal = st.st_mode & mode; /* the subset of the old and the new mask */ - if (((minimal ^ st.st_mode) & 07777) != 0) - if (fchmod_opath(fd, minimal & 07777) < 0) - return -errno; + if (((minimal ^ st.st_mode) & 07777) != 0) { + r = fchmod_opath(fd, minimal & 07777); + if (r < 0) + return r; + } } if (do_chown) if (fchownat(fd, "", uid, gid, AT_EMPTY_PATH) < 0) return -errno; - if (do_chmod) - if (fchmod_opath(fd, mode & 07777) < 0) - return -errno; + if (do_chmod) { + r = fchmod_opath(fd, mode & 07777); + if (r < 0) + return r; + } return do_chown || do_chmod; } diff --git a/src/basic/hashmap.c b/src/basic/hashmap.c index 67c439123..a4eeb110e 100644 --- a/src/basic/hashmap.c +++ b/src/basic/hashmap.c @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #include +#include #include #include @@ -19,7 +20,6 @@ #include "strv.h" #if ENABLE_DEBUG_HASHMAP -#include #include "list.h" #endif @@ -189,7 +189,6 @@ assert_cc(DIRECT_BUCKETS(struct set_entry) < (1 << 3)); * a handful of directly stored entries in a hashmap. When a hashmap * outgrows direct storage, it gets its own key for indirect storage. */ static uint8_t shared_hash_key[HASH_KEY_SIZE]; -static bool shared_hash_key_initialized; /* Fields that all hashmap/set types must have */ struct HashmapBase { @@ -768,6 +767,10 @@ static void reset_direct_storage(HashmapBase *h) { memset(p, DIB_RAW_INIT, sizeof(dib_raw_t) * hi->n_direct_buckets); } +static void shared_hash_key_initialize(void) { + random_bytes(shared_hash_key, sizeof(shared_hash_key)); +} + static struct HashmapBase *hashmap_base_new(const struct hash_ops *hash_ops, enum HashmapType type HASHMAP_DEBUG_PARAMS) { HashmapBase *h; const struct hashmap_type_info *hi = &hashmap_type_info[type]; @@ -790,10 +793,8 @@ static struct HashmapBase *hashmap_base_new(const struct hash_ops *hash_ops, enu reset_direct_storage(h); - if (!shared_hash_key_initialized) { - random_bytes(shared_hash_key, sizeof(shared_hash_key)); - shared_hash_key_initialized= true; - } + static pthread_once_t once = PTHREAD_ONCE_INIT; + assert_se(pthread_once(&once, shared_hash_key_initialize) == 0); #if ENABLE_DEBUG_HASHMAP h->debug.func = func; diff --git a/src/basic/in-addr-util.c b/src/basic/in-addr-util.c index ea50e2619..15307f6f1 100644 --- a/src/basic/in-addr-util.c +++ b/src/basic/in-addr-util.c @@ -795,13 +795,13 @@ static int in_addr_data_compare_func(const struct in_addr_data *x, const struct DEFINE_HASH_OPS(in_addr_data_hash_ops, struct in_addr_data, in_addr_data_hash_func, in_addr_data_compare_func); -static void in6_addr_hash_func(const struct in6_addr *addr, struct siphash *state) { +void in6_addr_hash_func(const struct in6_addr *addr, struct siphash *state) { assert(addr); siphash24_compress(addr, sizeof(*addr), state); } -static int in6_addr_compare_func(const struct in6_addr *a, const struct in6_addr *b) { +int in6_addr_compare_func(const struct in6_addr *a, const struct in6_addr *b) { return memcmp(a, b, sizeof(*a)); } diff --git a/src/basic/in-addr-util.h b/src/basic/in-addr-util.h index dc3f575bc..0d038399d 100644 --- a/src/basic/in-addr-util.h +++ b/src/basic/in-addr-util.h @@ -74,5 +74,8 @@ static inline size_t FAMILY_ADDRESS_SIZE(int family) { * See also oss-fuzz#11344. */ #define IN_ADDR_NULL ((union in_addr_union) { .in6 = {} }) +void in6_addr_hash_func(const struct in6_addr *addr, struct siphash *state); +int in6_addr_compare_func(const struct in6_addr *a, const struct in6_addr *b); + extern const struct hash_ops in_addr_data_hash_ops; extern const struct hash_ops in6_addr_hash_ops; diff --git a/src/basic/log.h b/src/basic/log.h index 15807d302..137d21005 100644 --- a/src/basic/log.h +++ b/src/basic/log.h @@ -234,12 +234,12 @@ void log_assert_failed_return_realm( #define log_full_errno(level, error, ...) \ log_full_errno_realm(LOG_REALM, (level), (error), __VA_ARGS__) -#define log_full(level, ...) log_full_errno((level), 0, __VA_ARGS__) +#define log_full(level, ...) (void) log_full_errno((level), 0, __VA_ARGS__) int log_emergency_level(void); /* Normal logging */ -#define log_debug(...) log_full(LOG_DEBUG, __VA_ARGS__) +#define log_debug(...) log_full_errno(LOG_DEBUG, 0, __VA_ARGS__) #define log_info(...) log_full(LOG_INFO, __VA_ARGS__) #define log_notice(...) log_full(LOG_NOTICE, __VA_ARGS__) #define log_warning(...) log_full(LOG_WARNING, __VA_ARGS__) diff --git a/src/basic/quota-util.c b/src/basic/quota-util.c index e048f5571..96ea9ee36 100644 --- a/src/basic/quota-util.c +++ b/src/basic/quota-util.c @@ -34,7 +34,7 @@ int quotactl_path(int cmd, const char *path, int id, void *addr) { r = get_block_device(path, &devno); if (r < 0) return r; - if (devno == 0) + if (devno == 0) /* Doesn't have a block device */ return -ENODEV; return quotactl_devno(cmd, devno, id, addr); diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c index fb1265985..4b3a4f206 100644 --- a/src/basic/socket-util.c +++ b/src/basic/socket-util.c @@ -617,40 +617,62 @@ bool sockaddr_equal(const union sockaddr_union *a, const union sockaddr_union *b return false; } -int fd_inc_sndbuf(int fd, size_t n) { +int fd_set_sndbuf(int fd, size_t n, bool increase) { int r, value; socklen_t l = sizeof(value); + if (n > INT_MAX) + return -ERANGE; + r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l); - if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2) + if (r >= 0 && l == sizeof(value) && increase ? (size_t) value >= n*2 : (size_t) value == n*2) return 0; - /* If we have the privileges we will ignore the kernel limit. */ + /* First, try to set the buffer size with SO_SNDBUF. */ + r = setsockopt_int(fd, SOL_SOCKET, SO_SNDBUF, n); + if (r < 0) + return r; - if (setsockopt_int(fd, SOL_SOCKET, SO_SNDBUF, n) < 0) { - r = setsockopt_int(fd, SOL_SOCKET, SO_SNDBUFFORCE, n); - if (r < 0) - return r; - } + /* SO_SNDBUF above may set to the kernel limit, instead of the requested size. + * So, we need to check the actual buffer size here. */ + r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l); + if (r >= 0 && l == sizeof(value) && increase ? (size_t) value >= n*2 : (size_t) value == n*2) + return 1; + + /* If we have the privileges we will ignore the kernel limit. */ + r = setsockopt_int(fd, SOL_SOCKET, SO_SNDBUFFORCE, n); + if (r < 0) + return r; return 1; } -int fd_inc_rcvbuf(int fd, size_t n) { +int fd_set_rcvbuf(int fd, size_t n, bool increase) { int r, value; socklen_t l = sizeof(value); + if (n > INT_MAX) + return -ERANGE; + r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l); - if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2) + if (r >= 0 && l == sizeof(value) && increase ? (size_t) value >= n*2 : (size_t) value == n*2) return 0; - /* If we have the privileges we will ignore the kernel limit. */ + /* First, try to set the buffer size with SO_RCVBUF. */ + r = setsockopt_int(fd, SOL_SOCKET, SO_RCVBUF, n); + if (r < 0) + return r; - if (setsockopt_int(fd, SOL_SOCKET, SO_RCVBUF, n) < 0) { - r = setsockopt_int(fd, SOL_SOCKET, SO_RCVBUFFORCE, n); - if (r < 0) - return r; - } + /* SO_RCVBUF above may set to the kernel limit, instead of the requested size. + * So, we need to check the actual buffer size here. */ + r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l); + if (r >= 0 && l == sizeof(value) && increase ? (size_t) value >= n*2 : (size_t) value == n*2) + return 1; + + /* If we have the privileges we will ignore the kernel limit. */ + r = setsockopt_int(fd, SOL_SOCKET, SO_RCVBUFFORCE, n); + if (r < 0) + return r; return 1; } diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h index 9e02e3988..1177ac1d8 100644 --- a/src/basic/socket-util.h +++ b/src/basic/socket-util.h @@ -118,8 +118,14 @@ int netlink_family_from_string(const char *s) _pure_; bool sockaddr_equal(const union sockaddr_union *a, const union sockaddr_union *b); -int fd_inc_sndbuf(int fd, size_t n); -int fd_inc_rcvbuf(int fd, size_t n); +int fd_set_sndbuf(int fd, size_t n, bool increase); +static inline int fd_inc_sndbuf(int fd, size_t n) { + return fd_set_sndbuf(fd, n, true); +} +int fd_set_rcvbuf(int fd, size_t n, bool increase); +static inline int fd_inc_rcvbuf(int fd, size_t n) { + return fd_set_rcvbuf(fd, n, true); +} int ip_tos_to_string_alloc(int i, char **s); int ip_tos_from_string(const char *s); diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c index a663fc5c2..3a80aafcc 100644 --- a/src/boot/bootctl.c +++ b/src/boot/bootctl.c @@ -1249,15 +1249,15 @@ static int verb_status(int argc, char *argv[], void *userdata) { printf(" Secure Boot: %sd\n", enable_disable(is_efi_secure_boot())); printf(" Setup Mode: %s\n", is_efi_secure_boot_setup_mode() ? "setup" : "user"); - r = efi_get_reboot_to_firmware(); - if (r > 0) + k = efi_get_reboot_to_firmware(); + if (k > 0) printf(" Boot into FW: %sactive%s\n", ansi_highlight_yellow(), ansi_normal()); - else if (r == 0) + else if (k == 0) printf(" Boot into FW: supported\n"); - else if (r == -EOPNOTSUPP) + else if (k == -EOPNOTSUPP) printf(" Boot into FW: not supported\n"); else { - errno = -r; + errno = -k; printf(" Boot into FW: %sfailed%s (%m)\n", ansi_highlight_red(), ansi_normal()); } printf("\n"); diff --git a/src/core/bpf-firewall.c b/src/core/bpf-firewall.c index bceb049b5..303751858 100644 --- a/src/core/bpf-firewall.c +++ b/src/core/bpf-firewall.c @@ -900,11 +900,11 @@ void emit_bpf_firewall_warning(Unit *u) { if (!warned) { bool quiet = bpf_firewall_unsupported_reason == -EPERM && detect_container(); - log_unit_full(u, quiet ? LOG_DEBUG : LOG_WARNING, bpf_firewall_unsupported_reason, - "unit configures an IP firewall, but %s.\n" - "(This warning is only shown for the first unit using IP firewalling.)", - getuid() != 0 ? "not running as root" : - "the local system does not support BPF/cgroup firewalling"); + log_unit_full_errno(u, quiet ? LOG_DEBUG : LOG_WARNING, bpf_firewall_unsupported_reason, + "unit configures an IP firewall, but %s.\n" + "(This warning is only shown for the first unit using IP firewalling.)", + getuid() != 0 ? "not running as root" : + "the local system does not support BPF/cgroup firewalling"); warned = true; } } diff --git a/src/core/cgroup.c b/src/core/cgroup.c index 031b28a68..1f9ba6ca8 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -78,8 +78,8 @@ static int set_attribute_and_warn(Unit *u, const char *controller, const char *a r = cg_set_attribute(controller, u->cgroup_path, attribute, value); if (r < 0) - log_unit_full(u, LOG_LEVEL_CGROUP_WRITE(r), r, "Failed to set '%s' attribute on '%s' to '%.*s': %m", - strna(attribute), isempty(u->cgroup_path) ? "/" : u->cgroup_path, (int) strcspn(value, NEWLINE), value); + log_unit_full_errno(u, LOG_LEVEL_CGROUP_WRITE(r), r, "Failed to set '%s' attribute on '%s' to '%.*s': %m", + strna(attribute), isempty(u->cgroup_path) ? "/" : u->cgroup_path, (int) strcspn(value, NEWLINE), value); return r; } @@ -724,7 +724,7 @@ static usec_t cgroup_cpu_adjust_period_and_log(Unit *u, usec_t period, usec_t qu if (new_period != period) { char v[FORMAT_TIMESPAN_MAX]; - log_unit_full(u, u->warned_clamping_cpu_quota_period ? LOG_DEBUG : LOG_WARNING, 0, + log_unit_full(u, u->warned_clamping_cpu_quota_period ? LOG_DEBUG : LOG_WARNING, "Clamping CPU interval for cpu.max: period is now %s", format_timespan(v, sizeof(v), new_period, 1)); u->warned_clamping_cpu_quota_period = true; @@ -986,8 +986,8 @@ static int cgroup_apply_devices(Unit *u) { else r = cg_set_attribute("devices", path, "devices.allow", "a"); if (r < 0) - log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EINVAL, -EACCES, -EPERM) ? LOG_DEBUG : LOG_WARNING, r, - "Failed to reset devices.allow/devices.deny: %m"); + log_unit_full_errno(u, IN_SET(r, -ENOENT, -EROFS, -EINVAL, -EACCES, -EPERM) ? LOG_DEBUG : LOG_WARNING, r, + "Failed to reset devices.allow/devices.deny: %m"); } bool allow_list_static = policy == CGROUP_DEVICE_POLICY_CLOSED || @@ -1351,8 +1351,8 @@ static void cgroup_context_apply( else r = 0; if (r < 0) - log_unit_full(u, LOG_LEVEL_CGROUP_WRITE(r), r, - "Failed to write to tasks limit sysctls: %m"); + log_unit_full_errno(u, LOG_LEVEL_CGROUP_WRITE(r), r, + "Failed to write to tasks limit sysctls: %m"); } /* The attribute itself is not available on the host root cgroup, and in the container case we want to @@ -2436,7 +2436,7 @@ void unit_prune_cgroup(Unit *u) { * the containing slice is stopped. So even if we failed now, this unit shouldn't assume * that the cgroup is still realized the next time it is started. Do not return early * on error, continue cleanup. */ - log_unit_full(u, r == -EBUSY ? LOG_DEBUG : LOG_WARNING, r, "Failed to destroy cgroup %s, ignoring: %m", u->cgroup_path); + log_unit_full_errno(u, r == -EBUSY ? LOG_DEBUG : LOG_WARNING, r, "Failed to destroy cgroup %s, ignoring: %m", u->cgroup_path); if (is_root_slice) return; diff --git a/src/core/execute.c b/src/core/execute.c index 2a4840a3a..7b3de2576 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -1072,26 +1072,42 @@ static int enforce_groups(gid_t gid, const gid_t *supplementary_gids, int ngids) return 0; } +static int set_securebits(int bits, int mask) { + int current, applied; + current = prctl(PR_GET_SECUREBITS); + if (current < 0) + return -errno; + /* Clear all securebits defined in mask and set bits */ + applied = (current & ~mask) | bits; + if (current == applied) + return 0; + if (prctl(PR_SET_SECUREBITS, applied) < 0) + return -errno; + return 1; +} + static int enforce_user(const ExecContext *context, uid_t uid) { assert(context); + int r; if (!uid_is_valid(uid)) return 0; /* Sets (but doesn't look up) the uid and make sure we keep the - * capabilities while doing so. */ + * capabilities while doing so. For setting secure bits the capability CAP_SETPCAP is + * required, so we also need keep-caps in this case. + */ - if (context->capability_ambient_set != 0) { + if (context->capability_ambient_set != 0 || context->secure_bits != 0) { /* First step: If we need to keep capabilities but * drop privileges we need to make sure we keep our * caps, while we drop privileges. */ if (uid != 0) { - int sb = context->secure_bits | 1<capability_ambient_set, true); if (r < 0) { @@ -3806,21 +3830,12 @@ static int exec_child( if (!needs_ambient_hack && context->capability_ambient_set != 0) { - /* Fix the ambient capabilities after user change. */ + /* Raise the ambient capabilities after user change. */ r = capability_ambient_set_apply(context->capability_ambient_set, false); if (r < 0) { *exit_status = EXIT_CAPABILITIES; return log_unit_error_errno(unit, r, "Failed to apply ambient capabilities (after UID change): %m"); } - - /* If we were asked to change user and ambient capabilities - * were requested, we had to add keep-caps to the securebits - * so that we would maintain the inherited capability set - * through the setresuid(). Make sure that the bit is added - * also to the context secure_bits so that we don't try to - * drop the bit away next. */ - - secure_bits |= 1<control_pid) { - log_unit_full(UNIT(s), prio, 0, "New main PID "PID_FMT" is the control process, refusing.", pid); + log_unit_full(UNIT(s), prio, "New main PID "PID_FMT" is the control process, refusing.", pid); return -EPERM; } if (!pid_is_alive(pid)) { - log_unit_full(UNIT(s), prio, 0, "New main PID "PID_FMT" does not exist or is a zombie.", pid); + log_unit_full(UNIT(s), prio, "New main PID "PID_FMT" does not exist or is a zombie.", pid); return -ESRCH; } @@ -958,16 +958,16 @@ static int service_load_pid_file(Service *s, bool may_warn) { r = chase_symlinks(s->pid_file, NULL, CHASE_SAFE, NULL, &fd); if (r == -ENOLINK) { - log_unit_full(UNIT(s), LOG_DEBUG, r, - "Potentially unsafe symlink chain, will now retry with relaxed checks: %s", s->pid_file); + log_unit_debug_errno(UNIT(s), r, + "Potentially unsafe symlink chain, will now retry with relaxed checks: %s", s->pid_file); questionable_pid_file = true; r = chase_symlinks(s->pid_file, NULL, 0, NULL, &fd); } if (r < 0) - return log_unit_full(UNIT(s), prio, fd, - "Can't open PID file %s (yet?) after %s: %m", s->pid_file, service_state_to_string(s->state)); + return log_unit_full_errno(UNIT(s), prio, fd, + "Can't open PID file %s (yet?) after %s: %m", s->pid_file, service_state_to_string(s->state)); /* Let's read the PID file now that we chased it down. But we need to convert the O_PATH fd * chase_symlinks() returned us into a proper fd first. */ @@ -980,7 +980,7 @@ static int service_load_pid_file(Service *s, bool may_warn) { r = parse_pid(k, &pid); if (r < 0) - return log_unit_full(UNIT(s), prio, r, "Failed to parse PID from file %s: %m", s->pid_file); + return log_unit_full_errno(UNIT(s), prio, r, "Failed to parse PID from file %s: %m", s->pid_file); if (s->main_pid_known && pid == s->main_pid) return 0; diff --git a/src/core/slice.c b/src/core/slice.c index f4f63fcb5..c6884d8c3 100644 --- a/src/core/slice.c +++ b/src/core/slice.c @@ -383,8 +383,10 @@ static int slice_freezer_action(Unit *s, FreezerAction action) { assert(s); assert(IN_SET(action, FREEZER_FREEZE, FREEZER_THAW)); - if (!slice_freezer_action_supported_by_children(s)) - return log_unit_warning(s, "Requested freezer operation is not supported by all children of the slice"); + if (!slice_freezer_action_supported_by_children(s)) { + log_unit_warning(s, "Requested freezer operation is not supported by all children of the slice"); + return 0; + } HASHMAP_FOREACH_KEY(v, member, s->dependencies[UNIT_BEFORE], i) { if (UNIT_DEREF(member->slice) != s) diff --git a/src/core/socket.c b/src/core/socket.c index 127195c9f..809cac68a 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -18,6 +18,7 @@ #include "dbus-socket.h" #include "dbus-unit.h" #include "def.h" +#include "errno-list.h" #include "exit-status.h" #include "fd-util.h" #include "format-util.h" @@ -1072,20 +1073,17 @@ static void socket_apply_socket_options(Socket *s, int fd) { } if (s->receive_buffer > 0) { - /* We first try with SO_RCVBUFFORCE, in case we have the perms for that */ - if (setsockopt_int(fd, SOL_SOCKET, SO_RCVBUFFORCE, s->receive_buffer) < 0) { - r = setsockopt_int(fd, SOL_SOCKET, SO_RCVBUF, s->receive_buffer); - if (r < 0) - log_unit_warning_errno(UNIT(s), r, "SO_RCVBUF failed: %m"); - } + r = fd_set_rcvbuf(fd, s->receive_buffer, false); + if (r < 0) + log_unit_full_errno(UNIT(s), ERRNO_IS_PRIVILEGE(r) ? LOG_DEBUG : LOG_WARNING, r, + "SO_RCVBUF/SO_RCVBUFFORCE failed: %m"); } if (s->send_buffer > 0) { - if (setsockopt_int(fd, SOL_SOCKET, SO_SNDBUFFORCE, s->send_buffer) < 0) { - r = setsockopt_int(fd, SOL_SOCKET, SO_SNDBUF, s->send_buffer); - if (r < 0) - log_unit_warning_errno(UNIT(s), r, "SO_SNDBUF failed: %m"); - } + r = fd_set_sndbuf(fd, s->send_buffer, false); + if (r < 0) + log_unit_full_errno(UNIT(s), ERRNO_IS_PRIVILEGE(r) ? LOG_DEBUG : LOG_WARNING, r, + "SO_SNDBUF/SO_SNDBUFFORCE failed: %m"); } if (s->mark >= 0) { @@ -1418,11 +1416,12 @@ int socket_load_service_unit(Socket *s, int cfd, Unit **ret) { if (cfd >= 0) { r = instance_from_socket(cfd, s->n_accepted, &instance); - if (r == -ENOTCONN) - /* ENOTCONN is legitimate if TCP RST was received. - * This connection is over, but the socket unit lives on. */ + if (ERRNO_IS_DISCONNECT(r)) + /* ENOTCONN is legitimate if TCP RST was received. Other socket families might return + * different errors. This connection is over, but the socket unit lives on. */ return log_unit_debug_errno(UNIT(s), r, - "Got ENOTCONN on incoming socket, assuming aborted connection attempt, ignoring."); + "Got %s on incoming socket, assuming aborted connection attempt, ignoring.", + errno_to_name(r)); if (r < 0) return r; } @@ -2359,8 +2358,8 @@ static void socket_enter_running(Socket *s, int cfd) { if (!pending) { if (!UNIT_ISSET(s->service)) { - log_unit_error(UNIT(s), "Service to activate vanished, refusing activation."); - r = -ENOENT; + r = log_unit_error_errno(UNIT(s), SYNTHETIC_ERRNO(ENOENT), + "Service to activate vanished, refusing activation."); goto fail; } @@ -2382,8 +2381,10 @@ static void socket_enter_running(Socket *s, int cfd) { if (s->max_connections_per_source > 0) { r = socket_acquire_peer(s, cfd, &p); - if (r < 0) - goto refuse; + if (ERRNO_IS_DISCONNECT(r)) + goto notconn; + if (r < 0) /* We didn't have enough resources to acquire peer information, let's fail. */ + goto fail; if (r > 0 && p->n_ref > s->max_connections_per_source) { _cleanup_free_ char *t = NULL; @@ -2397,6 +2398,8 @@ static void socket_enter_running(Socket *s, int cfd) { } r = socket_instantiate_service(s, cfd); + if (ERRNO_IS_DISCONNECT(r)) + goto notconn; if (r < 0) goto fail; @@ -2406,6 +2409,8 @@ static void socket_enter_running(Socket *s, int cfd) { s->n_accepted++; r = service_set_socket_fd(service, cfd, s, s->selinux_context_from_net); + if (ERRNO_IS_DISCONNECT(r)) + goto notconn; if (r < 0) goto fail; @@ -2430,13 +2435,18 @@ static void socket_enter_running(Socket *s, int cfd) { refuse: s->n_refused++; +notconn: safe_close(cfd); return; fail: - log_unit_warning(UNIT(s), "Failed to queue service startup job (Maybe the service file is missing or not a %s unit?): %s", - cfd >= 0 ? "template" : "non-template", - bus_error_message(&error, r)); + if (ERRNO_IS_RESOURCE(r)) + log_unit_warning(UNIT(s), "Failed to queue service startup job: %s", + bus_error_message(&error, r)); + else + log_unit_warning(UNIT(s), "Failed to queue service startup job (Maybe the service file is missing or not a %s unit?): %s", + cfd >= 0 ? "template" : "non-template", + bus_error_message(&error, r)); socket_enter_stop_pre(s, SOCKET_FAILURE_RESOURCES); safe_close(cfd); diff --git a/src/core/swap.c b/src/core/swap.c index 20179de2d..f2a1eb460 100644 --- a/src/core/swap.c +++ b/src/core/swap.c @@ -284,8 +284,8 @@ static int swap_load_devnode(Swap *s) { r = device_new_from_stat_rdev(&d, &st); if (r < 0) { - log_unit_full(UNIT(s), r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r, - "Failed to allocate device for swap %s: %m", s->what); + log_unit_full_errno(UNIT(s), r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r, + "Failed to allocate device for swap %s: %m", s->what); return 0; } diff --git a/src/core/transaction.c b/src/core/transaction.c index 0fa419787..402577298 100644 --- a/src/core/transaction.c +++ b/src/core/transaction.c @@ -1009,10 +1009,9 @@ int transaction_add_job_and_dependencies( SET_FOREACH(dep, following, i) { r = transaction_add_job_and_dependencies(tr, type, dep, ret, false, false, false, ignore_order, e); if (r < 0) { - log_unit_full(dep, - r == -ERFKILL ? LOG_INFO : LOG_WARNING, - r, "Cannot add dependency job, ignoring: %s", - bus_error_message(e, r)); + log_unit_full_errno(dep, r == -ERFKILL ? LOG_INFO : LOG_WARNING, r, + "Cannot add dependency job, ignoring: %s", + bus_error_message(e, r)); sd_bus_error_free(e); } } @@ -1046,10 +1045,10 @@ int transaction_add_job_and_dependencies( r = transaction_add_job_and_dependencies(tr, JOB_START, dep, ret, false, false, false, ignore_order, e); if (r < 0) { /* unit masked, job type not applicable and unit not found are not considered as errors. */ - log_unit_full(dep, - IN_SET(r, -ERFKILL, -EBADR, -ENOENT) ? LOG_DEBUG : LOG_WARNING, - r, "Cannot add dependency job, ignoring: %s", - bus_error_message(e, r)); + log_unit_full_errno(dep, + IN_SET(r, -ERFKILL, -EBADR, -ENOENT) ? LOG_DEBUG : LOG_WARNING, + r, "Cannot add dependency job, ignoring: %s", + bus_error_message(e, r)); sd_bus_error_free(e); } } diff --git a/src/core/unit.h b/src/core/unit.h index 4130cd50a..4fdd2e28d 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -896,7 +896,7 @@ int unit_thaw_vtable_common(Unit *u); /* Macros which append UNIT= or USER_UNIT= to the message */ -#define log_unit_full(unit, level, error, ...) \ +#define log_unit_full_errno(unit, level, error, ...) \ ({ \ const Unit *_u = (unit); \ (log_get_max_level() < LOG_PRI(level)) ? -ERRNO_VALUE(error) : \ @@ -904,17 +904,19 @@ int unit_thaw_vtable_common(Unit *u); log_internal(level, error, PROJECT_FILE, __LINE__, __func__, ##__VA_ARGS__); \ }) -#define log_unit_debug(unit, ...) log_unit_full(unit, LOG_DEBUG, 0, ##__VA_ARGS__) -#define log_unit_info(unit, ...) log_unit_full(unit, LOG_INFO, 0, ##__VA_ARGS__) -#define log_unit_notice(unit, ...) log_unit_full(unit, LOG_NOTICE, 0, ##__VA_ARGS__) -#define log_unit_warning(unit, ...) log_unit_full(unit, LOG_WARNING, 0, ##__VA_ARGS__) -#define log_unit_error(unit, ...) log_unit_full(unit, LOG_ERR, 0, ##__VA_ARGS__) +#define log_unit_full(unit, level, ...) (void) log_unit_full_errno(unit, level, 0, __VA_ARGS__) -#define log_unit_debug_errno(unit, error, ...) log_unit_full(unit, LOG_DEBUG, error, ##__VA_ARGS__) -#define log_unit_info_errno(unit, error, ...) log_unit_full(unit, LOG_INFO, error, ##__VA_ARGS__) -#define log_unit_notice_errno(unit, error, ...) log_unit_full(unit, LOG_NOTICE, error, ##__VA_ARGS__) -#define log_unit_warning_errno(unit, error, ...) log_unit_full(unit, LOG_WARNING, error, ##__VA_ARGS__) -#define log_unit_error_errno(unit, error, ...) log_unit_full(unit, LOG_ERR, error, ##__VA_ARGS__) +#define log_unit_debug(unit, ...) log_unit_full_errno(unit, LOG_DEBUG, 0, __VA_ARGS__) +#define log_unit_info(unit, ...) log_unit_full(unit, LOG_INFO, __VA_ARGS__) +#define log_unit_notice(unit, ...) log_unit_full(unit, LOG_NOTICE, __VA_ARGS__) +#define log_unit_warning(unit, ...) log_unit_full(unit, LOG_WARNING, __VA_ARGS__) +#define log_unit_error(unit, ...) log_unit_full(unit, LOG_ERR, __VA_ARGS__) + +#define log_unit_debug_errno(unit, error, ...) log_unit_full_errno(unit, LOG_DEBUG, error, __VA_ARGS__) +#define log_unit_info_errno(unit, error, ...) log_unit_full_errno(unit, LOG_INFO, error, __VA_ARGS__) +#define log_unit_notice_errno(unit, error, ...) log_unit_full_errno(unit, LOG_NOTICE, error, __VA_ARGS__) +#define log_unit_warning_errno(unit, error, ...) log_unit_full_errno(unit, LOG_WARNING, error, __VA_ARGS__) +#define log_unit_error_errno(unit, error, ...) log_unit_full_errno(unit, LOG_ERR, error, __VA_ARGS__) #define LOG_UNIT_MESSAGE(unit, fmt, ...) "MESSAGE=%s: " fmt, (unit)->id, ##__VA_ARGS__ #define LOG_UNIT_ID(unit) (unit)->manager->unit_log_format_string, (unit)->id diff --git a/src/escape/escape.c b/src/escape/escape.c index 0c543a90f..3f3dc0a89 100644 --- a/src/escape/escape.c +++ b/src/escape/escape.c @@ -211,14 +211,16 @@ static int run(int argc, char *argv[]) { if (r < 0) return log_error_errno(r, "Failed to extract instance: %m"); if (isempty(name)) - return log_error("Unit %s is missing the instance name.", *i); + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unit %s is missing the instance name.", *i); r = unit_name_template(*i, &template); if (r < 0) return log_error_errno(r, "Failed to extract template: %m"); if (arg_template && !streq(arg_template, template)) - return log_error("Unit %s template %s does not match specified template %s.", - *i, template, arg_template); + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unit %s template %s does not match specified template %s.", + *i, template, arg_template); } else { name = strdup(*i); if (!name) diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c index a9478b9db..24d28afc2 100644 --- a/src/gpt-auto-generator/gpt-auto-generator.c +++ b/src/gpt-auto-generator/gpt-auto-generator.c @@ -729,10 +729,14 @@ static int add_mounts(void) { int r; r = get_block_device_harder("/", &devno); + if (r == -EUCLEAN) + return btrfs_log_dev_root(LOG_ERR, r, "root file system"); if (r < 0) return log_error_errno(r, "Failed to determine block device of root file system: %m"); - if (r == 0) { + if (r == 0) { /* Not backed by block device */ r = get_block_device_harder("/usr", &devno); + if (r == -EUCLEAN) + return btrfs_log_dev_root(LOG_ERR, r, "/usr"); if (r < 0) return log_error_errno(r, "Failed to determine block device of /usr file system: %m"); if (r == 0) { diff --git a/src/home/homed-home.c b/src/home/homed-home.c index 35b325413..a87fd9a5d 100644 --- a/src/home/homed-home.c +++ b/src/home/homed-home.c @@ -1112,7 +1112,7 @@ static int home_fixate_internal( if (r < 0) return r; - if (for_state == HOME_FIXATING_FOR_ACTIVATION) { + if (IN_SET(for_state, HOME_FIXATING_FOR_ACTIVATION, HOME_FIXATING_FOR_ACQUIRE)) { /* Remember the secret data, since we need it for the activation again, later on. */ user_record_unref(h->secret); h->secret = user_record_ref(secret); diff --git a/src/libsystemd/sd-device/device-monitor.c b/src/libsystemd/sd-device/device-monitor.c index bed45da8e..1d24af069 100644 --- a/src/libsystemd/sd-device/device-monitor.c +++ b/src/libsystemd/sd-device/device-monitor.c @@ -91,18 +91,9 @@ int device_monitor_allow_unicast_sender(sd_device_monitor *m, sd_device_monitor } _public_ int sd_device_monitor_set_receive_buffer_size(sd_device_monitor *m, size_t size) { - int r, n = (int) size; - assert_return(m, -EINVAL); - assert_return((size_t) n == size, -EINVAL); - 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; - } - - return 0; + return fd_set_rcvbuf(m->sock, size, false); } int device_monitor_disconnect(sd_device_monitor *m) { diff --git a/src/libsystemd/sd-device/device-util.h b/src/libsystemd/sd-device/device-util.h index 1a1795d97..431d4a1b4 100644 --- a/src/libsystemd/sd-device/device-util.h +++ b/src/libsystemd/sd-device/device-util.h @@ -31,7 +31,7 @@ device; \ device = sd_device_enumerator_get_subsystem_next(enumerator)) -#define log_device_full(device, level, error, ...) \ +#define log_device_full_errno(device, level, error, ...) \ ({ \ const char *_sysname = NULL; \ sd_device *_d = (device); \ @@ -41,17 +41,19 @@ (void) sd_device_get_sysname(_d, &_sysname); \ log_object_internal(_level, _error, PROJECT_FILE, __LINE__, __func__, \ _sysname ? "DEVICE=" : NULL, _sysname, \ - NULL, NULL, ##__VA_ARGS__); \ + NULL, NULL, __VA_ARGS__); \ }) -#define log_device_debug(device, ...) log_device_full(device, LOG_DEBUG, 0, ##__VA_ARGS__) -#define log_device_info(device, ...) log_device_full(device, LOG_INFO, 0, ##__VA_ARGS__) -#define log_device_notice(device, ...) log_device_full(device, LOG_NOTICE, 0, ##__VA_ARGS__) -#define log_device_warning(device, ...) log_device_full(device, LOG_WARNING, 0, ##__VA_ARGS__) -#define log_device_error(device, ...) log_device_full(device, LOG_ERR, 0, ##__VA_ARGS__) +#define log_device_full(device, level, ...) (void) log_device_full_errno(device, level, 0, __VA_ARGS__) -#define log_device_debug_errno(device, error, ...) log_device_full(device, LOG_DEBUG, error, ##__VA_ARGS__) -#define log_device_info_errno(device, error, ...) log_device_full(device, LOG_INFO, error, ##__VA_ARGS__) -#define log_device_notice_errno(device, error, ...) log_device_full(device, LOG_NOTICE, error, ##__VA_ARGS__) -#define log_device_warning_errno(device, error, ...) log_device_full(device, LOG_WARNING, error, ##__VA_ARGS__) -#define log_device_error_errno(device, error, ...) log_device_full(device, LOG_ERR, error, ##__VA_ARGS__) +#define log_device_debug(device, ...) log_device_full_errno(device, LOG_DEBUG, 0, __VA_ARGS__) +#define log_device_info(device, ...) log_device_full(device, LOG_INFO, __VA_ARGS__) +#define log_device_notice(device, ...) log_device_full(device, LOG_NOTICE, __VA_ARGS__) +#define log_device_warning(device, ...) log_device_full(device, LOG_WARNING, __VA_ARGS__) +#define log_device_error(device, ...) log_device_full(device, LOG_ERR, __VA_ARGS__) + +#define log_device_debug_errno(device, error, ...) log_device_full_errno(device, LOG_DEBUG, error, __VA_ARGS__) +#define log_device_info_errno(device, error, ...) log_device_full_errno(device, LOG_INFO, error, __VA_ARGS__) +#define log_device_notice_errno(device, error, ...) log_device_full_errno(device, LOG_NOTICE, error, __VA_ARGS__) +#define log_device_warning_errno(device, error, ...) log_device_full_errno(device, LOG_WARNING, error, __VA_ARGS__) +#define log_device_error_errno(device, error, ...) log_device_full_errno(device, LOG_ERR, error, __VA_ARGS__) diff --git a/src/libsystemd/sd-path/sd-path.c b/src/libsystemd/sd-path/sd-path.c index 736795d1d..3f6e70d09 100644 --- a/src/libsystemd/sd-path/sd-path.c +++ b/src/libsystemd/sd-path/sd-path.c @@ -321,7 +321,7 @@ static int get_path(uint64_t type, char **buffer, const char **ret) { return from_user_dir("XDG_DESKTOP_DIR", buffer, ret); case SD_PATH_SYSTEMD_UTIL: - *ret = ROOTPREFIX "/lib/systemd"; + *ret = ROOTPREFIX_NOSLASH "/lib/systemd"; return 0; case SD_PATH_SYSTEMD_SYSTEM_UNIT: @@ -329,7 +329,7 @@ static int get_path(uint64_t type, char **buffer, const char **ret) { return 0; case SD_PATH_SYSTEMD_SYSTEM_PRESET: - *ret = ROOTPREFIX "/lib/systemd/system-preset"; + *ret = ROOTPREFIX_NOSLASH "/lib/systemd/system-preset"; return 0; case SD_PATH_SYSTEMD_USER_UNIT: @@ -337,7 +337,7 @@ static int get_path(uint64_t type, char **buffer, const char **ret) { return 0; case SD_PATH_SYSTEMD_USER_PRESET: - *ret = ROOTPREFIX "/lib/systemd/user-preset"; + *ret = ROOTPREFIX_NOSLASH "/lib/systemd/user-preset"; return 0; case SD_PATH_SYSTEMD_SYSTEM_CONF: @@ -357,11 +357,11 @@ static int get_path(uint64_t type, char **buffer, const char **ret) { return 0; case SD_PATH_SYSTEMD_SLEEP: - *ret = ROOTPREFIX "/lib/systemd/system-sleep"; + *ret = ROOTPREFIX_NOSLASH "/lib/systemd/system-sleep"; return 0; case SD_PATH_SYSTEMD_SHUTDOWN: - *ret = ROOTPREFIX "/lib/systemd/system-shutdown"; + *ret = ROOTPREFIX_NOSLASH "/lib/systemd/system-shutdown"; return 0; /* FIXME: systemd.pc uses ${prefix}, but CONF_PATHS_NULSTR doesn't. @@ -371,19 +371,19 @@ static int get_path(uint64_t type, char **buffer, const char **ret) { return 0; case SD_PATH_SYSUSERS: - *ret = ROOTPREFIX "/lib/sysusers.d"; + *ret = ROOTPREFIX_NOSLASH "/lib/sysusers.d"; return 0; case SD_PATH_SYSCTL: - *ret = ROOTPREFIX "/lib/sysctl.d"; + *ret = ROOTPREFIX_NOSLASH "/lib/sysctl.d"; return 0; case SD_PATH_BINFMT: - *ret = ROOTPREFIX "/lib/binfmt.d"; + *ret = ROOTPREFIX_NOSLASH "/lib/binfmt.d"; return 0; case SD_PATH_MODULES_LOAD: - *ret = ROOTPREFIX "/lib/modules-load.d"; + *ret = ROOTPREFIX_NOSLASH "/lib/modules-load.d"; return 0; case SD_PATH_CATALOG: diff --git a/src/network/netdev/macsec.c b/src/network/netdev/macsec.c index 2ffa5ec8c..de21ecece 100644 --- a/src/network/netdev/macsec.c +++ b/src/network/netdev/macsec.c @@ -852,10 +852,12 @@ int config_parse_macsec_key_id( log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse KeyId \"%s\": %m", rvalue); return 0; } - if (l > MACSEC_KEYID_LEN) - return log_syntax(unit, LOG_WARNING, filename, line, 0, - "Specified KeyId is larger then the allowed maximum (%zu > %u), ignoring: %s", - l, MACSEC_KEYID_LEN, rvalue); + if (l > MACSEC_KEYID_LEN) { + log_syntax(unit, LOG_WARNING, filename, line, 0, + "Specified KeyId is larger then the allowed maximum (%zu > %u), ignoring: %s", + l, MACSEC_KEYID_LEN, rvalue); + return 0; + } dest = a ? a->sa.key_id : b->sa.key_id; memcpy_safe(dest, p, l); diff --git a/src/network/netdev/wireguard.c b/src/network/netdev/wireguard.c index 6812b07bf..df6d9feae 100644 --- a/src/network/netdev/wireguard.c +++ b/src/network/netdev/wireguard.c @@ -493,13 +493,17 @@ static int wireguard_decode_key_and_warn( (void) warn_file_is_world_accessible(filename, NULL, unit, line); r = unbase64mem_full(rvalue, strlen(rvalue), true, &key, &len); - if (r < 0) - return log_syntax(unit, LOG_WARNING, filename, line, r, + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to decode wireguard key provided by %s=, ignoring assignment: %m", lvalue); - if (len != WG_KEY_LEN) - return log_syntax(unit, LOG_WARNING, filename, line, SYNTHETIC_ERRNO(EINVAL), + return 0; + } + if (len != WG_KEY_LEN) { + log_syntax(unit, LOG_WARNING, filename, line, 0, "Wireguard key provided by %s= has invalid length (%zu bytes), ignoring assignment.", lvalue, len); + return 0; + } memcpy(ret, key, WG_KEY_LEN); return 0; diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 0349ca6f9..b193a8f00 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -10,6 +10,7 @@ #include "netlink-util.h" #include "networkd-address.h" #include "networkd-manager.h" +#include "networkd-ndisc.h" #include "parse-util.h" #include "set.h" #include "socket-util.h" @@ -123,6 +124,9 @@ void address_free(Address *address) { } if (address->link && !address->acd) { + NDiscAddress *n; + Iterator i; + set_remove(address->link->addresses, address); set_remove(address->link->addresses_foreign, address); set_remove(address->link->static_addresses, address); @@ -134,8 +138,9 @@ void address_free(Address *address) { set_remove(address->link->dhcp6_addresses_old, address); set_remove(address->link->dhcp6_pd_addresses, address); set_remove(address->link->dhcp6_pd_addresses_old, address); - set_remove(address->link->ndisc_addresses, address); - set_remove(address->link->ndisc_addresses_old, address); + SET_FOREACH(n, address->link->ndisc_addresses, i) + if (n->address == address) + free(set_remove(address->link->ndisc_addresses, n)); if (in_addr_equal(AF_INET6, &address->in_addr, (const union in_addr_union *) &address->link->ipv6ll_address)) memzero(&address->link->ipv6ll_address, sizeof(struct in6_addr)); @@ -162,7 +167,7 @@ static uint32_t address_prefix(const Address *a) { return be32toh(a->in_addr.in.s_addr) >> (32 - a->prefixlen); } -static void address_hash_func(const Address *a, struct siphash *state) { +void address_hash_func(const Address *a, struct siphash *state) { assert(a); siphash24_compress(&a->family, sizeof(a->family), state); @@ -187,7 +192,7 @@ static void address_hash_func(const Address *a, struct siphash *state) { } } -static int address_compare_func(const Address *a1, const Address *a2) { +int address_compare_func(const Address *a1, const Address *a2) { int r; r = CMP(a1->family, a2->family); diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h index 3fc9935d1..1378901b8 100644 --- a/src/network/networkd-address.h +++ b/src/network/networkd-address.h @@ -75,6 +75,8 @@ int generate_ipv6_eui_64_address(Link *link, struct in6_addr *ret); DEFINE_NETWORK_SECTION_FUNCTIONS(Address, address_free); +void address_hash_func(const Address *a, struct siphash *state); +int address_compare_func(const Address *a1, const Address *a2); extern const struct hash_ops address_hash_ops; CONFIG_PARSER_PROTOTYPE(config_parse_address); diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index d28c3e380..ba03d36f2 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -251,11 +251,10 @@ static int dhcp_prefix_route_from_lease( static int link_set_dhcp_routes(Link *link) { _cleanup_free_ sd_dhcp_route **static_routes = NULL; bool classless_route = false, static_route = false; - const struct in_addr *router; struct in_addr address; - int r, n, i; uint32_t table; Route *rt; + int r, n; assert(link); @@ -298,9 +297,9 @@ static int link_set_dhcp_routes(Link *link) { if (n == -ENODATA) log_link_debug_errno(link, n, "DHCP: No routes received from DHCP server: %m"); else if (n < 0) - log_link_debug_errno(link, n, "DHCP: could not get routes: %m"); + return log_link_error_errno(link, n, "DHCP: could not get routes: %m"); - for (i = 0; i < n; i++) { + for (int i = 0; i < n; i++) { switch (sd_dhcp_route_get_option(static_routes[i])) { case SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE: classless_route = true; @@ -312,11 +311,14 @@ static int link_set_dhcp_routes(Link *link) { } if (link->network->dhcp_use_routes) { - for (i = 0; i < n; i++) { + /* if the DHCP server returns both a Classless Static Routes option and a Static Routes option, + * the DHCP client MUST ignore the Static Routes option. */ + if (classless_route && static_route) + log_link_warning(link, "Classless static routes received from DHCP server: ignoring static-route option"); + + for (int i = 0; i < n; i++) { _cleanup_(route_freep) Route *route = NULL; - /* if the DHCP server returns both a Classless Static Routes option and a Static Routes option, - the DHCP client MUST ignore the Static Routes option. */ if (classless_route && sd_dhcp_route_get_option(static_routes[i]) != SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE) continue; @@ -347,20 +349,20 @@ static int link_set_dhcp_routes(Link *link) { } if (link->network->dhcp_use_gateway) { + const struct in_addr *router; + r = sd_dhcp_lease_get_router(link->dhcp_lease, &router); if (IN_SET(r, 0, -ENODATA)) log_link_info(link, "DHCP: No gateway received from DHCP server."); else if (r < 0) - log_link_warning_errno(link, r, "DHCP error: could not get gateway: %m"); + return log_link_error_errno(link, r, "DHCP error: could not get gateway: %m"); else if (in4_addr_is_null(&router[0])) log_link_info(link, "DHCP: Received gateway is null."); - - /* According to RFC 3442: If the DHCP server returns both a Classless Static Routes option and - a Router option, the DHCP client MUST ignore the Router option. */ - if (classless_route && static_route) - log_link_warning(link, "Classless static routes received from DHCP server: ignoring static-route option and router option"); - - if (r > 0 && !classless_route && !in4_addr_is_null(&router[0])) { + else if (classless_route) + /* According to RFC 3442: If the DHCP server returns both a Classless Static Routes option and + * a Router option, the DHCP client MUST ignore the Router option. */ + log_link_warning(link, "Classless static routes received from DHCP server: ignoring router option"); + else { _cleanup_(route_freep) Route *route = NULL, *route_gw = NULL; r = route_new(&route_gw); @@ -399,20 +401,20 @@ static int link_set_dhcp_routes(Link *link) { r = dhcp_route_configure(route, link); if (r < 0) return log_link_error_errno(link, r, "Could not set router: %m"); - } - LIST_FOREACH(routes, rt, link->network->static_routes) { - if (!rt->gateway_from_dhcp) - continue; + LIST_FOREACH(routes, rt, link->network->static_routes) { + if (!rt->gateway_from_dhcp) + continue; - if (rt->family != AF_INET) - continue; + if (rt->family != AF_INET) + continue; - rt->gw.in = router[0]; + rt->gw.in = router[0]; - r = dhcp_route_configure(rt, link); - if (r < 0) - return log_link_error_errno(link, r, "Could not set gateway: %m"); + r = dhcp_route_configure(rt, link); + if (r < 0) + return log_link_error_errno(link, r, "Could not set gateway: %m"); + } } } diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index d969995ea..675f19c92 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -160,7 +160,8 @@ static int dhcp6_pd_remove_old(Link *link, bool force) { if (k < 0) r = k; - (void) sd_radv_remove_prefix(link->radv, &route->dst.in6, 64); + if (link->radv) + (void) sd_radv_remove_prefix(link->radv, &route->dst.in6, 64); dhcp6_pd_free(hashmap_get(link->manager->dhcp6_prefixes, &route->dst.in6)); } @@ -201,7 +202,8 @@ int dhcp6_pd_remove(Link *link) { if (k < 0) r = k; - (void) sd_radv_remove_prefix(link->radv, &route->dst.in6, 64); + if (link->radv) + (void) sd_radv_remove_prefix(link->radv, &route->dst.in6, 64); dhcp6_pd_free(hashmap_get(link->manager->dhcp6_prefixes, &route->dst.in6)); } @@ -992,7 +994,7 @@ static int dhcp6_update_address( addr->cinfo.ifa_valid = lifetime_valid; (void) in_addr_to_string(addr->family, &addr->in_addr, &buffer); - log_link_full(link, set_contains(link->dhcp6_addresses, addr) ? LOG_DEBUG : LOG_INFO, 0, + log_link_full(link, set_contains(link->dhcp6_addresses, addr) ? LOG_DEBUG : LOG_INFO, "DHCPv6 address %s/%u timeout preferred %d valid %d", strna(buffer), addr->prefixlen, lifetime_preferred, lifetime_valid); diff --git a/src/network/networkd-fdb.c b/src/network/networkd-fdb.c index 833d13cf0..6a0afeac3 100644 --- a/src/network/networkd-fdb.c +++ b/src/network/networkd-fdb.c @@ -292,10 +292,12 @@ int config_parse_fdb_destination( return log_oom(); r = in_addr_from_string_auto(rvalue, &fdb_entry->family, &fdb_entry->destination_addr); - if (r < 0) - return log_syntax(unit, LOG_WARNING, filename, line, r, - "FDB destination IP address is invalid, ignoring assignment: %s", - rvalue); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "FDB destination IP address is invalid, ignoring assignment: %s", + rvalue); + return 0; + } fdb_entry = NULL; diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 1597f1ed5..ea3ff55b4 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -720,7 +720,6 @@ static Link *link_free(Link *link) { link->dhcp6_pd_routes = set_free(link->dhcp6_pd_routes); link->dhcp6_pd_routes_old = set_free(link->dhcp6_pd_routes_old); link->ndisc_routes = set_free(link->ndisc_routes); - link->ndisc_routes_old = set_free(link->ndisc_routes_old); link->nexthops = set_free(link->nexthops); link->nexthops_foreign = set_free(link->nexthops_foreign); @@ -736,7 +735,6 @@ static Link *link_free(Link *link) { link->dhcp6_pd_addresses = set_free(link->dhcp6_pd_addresses); link->dhcp6_pd_addresses_old = set_free(link->dhcp6_pd_addresses_old); link->ndisc_addresses = set_free(link->ndisc_addresses); - link->ndisc_addresses_old = set_free(link->ndisc_addresses_old); while ((address = link->pool_addresses)) { LIST_REMOVE(addresses, link->pool_addresses, address); @@ -1163,6 +1161,8 @@ void link_check_ready(Link *link) { } if (link_has_carrier(link) || !link->network->configure_without_carrier) { + bool has_ndisc_address = false; + NDiscAddress *n; if (link_ipv4ll_enabled(link, ADDRESS_FAMILY_IPV4) && !link->ipv4ll_address_configured) { log_link_debug(link, "%s(): IPv4LL is not configured.", __func__); @@ -1175,8 +1175,14 @@ void link_check_ready(Link *link) { return; } + SET_FOREACH(n, link->ndisc_addresses, i) + if (!n->marked) { + has_ndisc_address = true; + break; + } + if ((link_dhcp4_enabled(link) || link_dhcp6_enabled(link)) && - !link->dhcp_address && set_isempty(link->dhcp6_addresses) && set_isempty(link->ndisc_addresses) && + !link->dhcp_address && set_isempty(link->dhcp6_addresses) && !has_ndisc_address && !(link_ipv4ll_enabled(link, ADDRESS_FAMILY_FALLBACK_IPV4) && link->ipv4ll_address_configured)) { log_link_debug(link, "%s(): DHCP4 or DHCP6 is enabled but no dynamic address is assigned yet.", __func__); return; @@ -4674,10 +4680,10 @@ int log_link_message_full_errno(Link *link, sd_netlink_message *m, int level, in const char *err_msg = NULL; (void) sd_netlink_message_read_string(m, NLMSGERR_ATTR_MSG, &err_msg); - return log_link_full(link, level, err, - "%s: %s%s%s%m", - msg, - strempty(err_msg), - err_msg && !endswith(err_msg, ".") ? "." : "", - err_msg ? " " : ""); + return log_link_full_errno(link, level, err, + "%s: %s%s%s%m", + msg, + strempty(err_msg), + err_msg && !endswith(err_msg, ".") ? "." : "", + err_msg ? " " : ""); } diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index ab5c3fd26..a0c566114 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -132,8 +132,8 @@ typedef struct Link { sd_ndisc *ndisc; Set *ndisc_rdnss; Set *ndisc_dnssl; - Set *ndisc_addresses, *ndisc_addresses_old; - Set *ndisc_routes, *ndisc_routes_old; + Set *ndisc_addresses; + Set *ndisc_routes; unsigned ndisc_addresses_messages; unsigned ndisc_routes_messages; bool ndisc_addresses_configured:1; diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index a6c1a39e2..b1c68dbfd 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -36,11 +36,11 @@ #include "path-util.h" #include "set.h" #include "signal-util.h" +#include "stat-util.h" #include "strv.h" #include "sysctl-util.h" #include "tmpfile-util.h" #include "udev-util.h" -#include "virt.h" /* use 128 MB for receive socket kernel queue. */ #define RCVBUF_SIZE (128*1024*1024) @@ -260,16 +260,19 @@ static int manager_udev_process_link(sd_device_monitor *monitor, sd_device *devi static int manager_connect_udev(Manager *m) { int r; - /* udev does not initialize devices inside containers, - * so we rely on them being already initialized before - * entering the container */ - if (detect_container() > 0) + /* udev does not initialize devices inside containers, so we rely on them being already + * initialized before entering the container. */ + if (path_is_read_only_fs("/sys") > 0) return 0; r = sd_device_monitor_new(&m->device_monitor); if (r < 0) return log_error_errno(r, "Failed to initialize device monitor: %m"); + r = sd_device_monitor_set_receive_buffer_size(m->device_monitor, RCVBUF_SIZE); + if (r < 0) + log_warning_errno(r, "Failed to increase buffer size for device monitor, ignoring: %m"); + r = sd_device_monitor_filter_add_match_subsystem_devtype(m->device_monitor, "net", NULL); if (r < 0) return log_error_errno(r, "Could not add device monitor filter: %m"); @@ -1346,7 +1349,7 @@ static int manager_connect_genl(Manager *m) { r = sd_netlink_inc_rcvbuf(m->genl, RCVBUF_SIZE); if (r < 0) - return r; + log_warning_errno(r, "Failed to increase receive buffer size for general netlink socket, ignoring: %m"); r = sd_netlink_attach_event(m->genl, m->event, 0); if (r < 0) @@ -1368,9 +1371,14 @@ static int manager_connect_rtnl(Manager *m) { if (r < 0) return r; - r = sd_netlink_inc_rcvbuf(m->rtnl, RCVBUF_SIZE); - if (r < 0) - return r; + /* Bump receiver buffer, but only if we are not called via socket activation, as in that + * case systemd sets the receive buffer size for us, and the value in the .socket unit + * should take full effect. */ + if (fd < 0) { + r = sd_netlink_inc_rcvbuf(m->rtnl, RCVBUF_SIZE); + if (r < 0) + log_warning_errno(r, "Failed to increase receive buffer size for rtnl socket, ignoring: %m"); + } r = sd_netlink_attach_event(m->rtnl, m->event, 0); if (r < 0) diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index 349f0548a..bcea91c69 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -35,79 +35,218 @@ #define NDISC_APP_ID SD_ID128_MAKE(13,ac,81,a7,d5,3f,49,78,92,79,5d,0c,29,3a,bc,7e) -static int ndisc_remove_old(Link *link, bool force); +static int ndisc_remove_old_one(Link *link, const struct in6_addr *router, bool force); static int ndisc_address_callback(Address *address) { - Address *a; + struct in6_addr router = {}; + NDiscAddress *n; Iterator i; assert(address); assert(address->link); - /* Make this called only once */ - SET_FOREACH(a, address->link->ndisc_addresses, i) - a->callback = NULL; + SET_FOREACH(n, address->link->ndisc_addresses, i) + if (n->address == address) { + router = n->router; + break; + } - return ndisc_remove_old(address->link, true); + if (IN6_IS_ADDR_UNSPECIFIED(&router)) { + _cleanup_free_ char *buf = NULL; + + (void) in_addr_to_string(address->family, &address->in_addr, &buf); + log_link_debug(address->link, "%s is called for %s/%u, but it is already removed, ignoring.", + __func__, strna(buf), address->prefixlen); + return 0; + } + + /* Make this called only once */ + SET_FOREACH(n, address->link->ndisc_addresses, i) + if (IN6_ARE_ADDR_EQUAL(&n->router, &router)) + n->address->callback = NULL; + + return ndisc_remove_old_one(address->link, &router, true); } -static int ndisc_remove_old(Link *link, bool force) { - Address *address; - Route *route; +static int ndisc_remove_old_one(Link *link, const struct in6_addr *router, bool force) { + NDiscAddress *na; + NDiscRoute *nr; NDiscDNSSL *dnssl; NDiscRDNSS *rdnss; Iterator i; int k, r = 0; assert(link); + assert(router); if (!force) { - bool set_callback = !set_isempty(link->ndisc_addresses); + bool set_callback = false; if (!link->ndisc_addresses_configured || !link->ndisc_routes_configured) return 0; - SET_FOREACH(address, link->ndisc_addresses, i) - if (address_is_ready(address)) { - set_callback = false; + SET_FOREACH(na, link->ndisc_addresses, i) + if (!na->marked && IN6_ARE_ADDR_EQUAL(&na->router, router)) { + set_callback = true; break; } + if (set_callback) + SET_FOREACH(na, link->ndisc_addresses, i) + if (!na->marked && address_is_ready(na->address)) { + set_callback = false; + break; + } + if (set_callback) { - SET_FOREACH(address, link->ndisc_addresses, i) - address->callback = ndisc_address_callback; + SET_FOREACH(na, link->ndisc_addresses, i) + if (!na->marked && IN6_ARE_ADDR_EQUAL(&na->router, router)) + na->address->callback = ndisc_address_callback; + + if (DEBUG_LOGGING) { + _cleanup_free_ char *buf = NULL; + + (void) in_addr_to_string(AF_INET6, (union in_addr_union *) router, &buf); + log_link_debug(link, "No SLAAC address obtained from %s is ready. " + "The old NDisc information will be removed later.", + strna(buf)); + } return 0; } } - if (!set_isempty(link->ndisc_addresses_old) || !set_isempty(link->ndisc_routes_old)) - log_link_debug(link, "Removing old NDisc addresses and routes."); + if (DEBUG_LOGGING) { + _cleanup_free_ char *buf = NULL; + + (void) in_addr_to_string(AF_INET6, (union in_addr_union *) router, &buf); + log_link_debug(link, "Removing old NDisc information obtained from %s.", strna(buf)); + } link_dirty(link); - SET_FOREACH(address, link->ndisc_addresses_old, i) { - k = address_remove(address, link, NULL); - if (k < 0) - r = k; - } + SET_FOREACH(na, link->ndisc_addresses, i) + if (na->marked && IN6_ARE_ADDR_EQUAL(&na->router, router)) { + k = address_remove(na->address, link, NULL); + if (k < 0) + r = k; + } - SET_FOREACH(route, link->ndisc_routes_old, i) { - k = route_remove(route, link, NULL); - if (k < 0) - r = k; - } + SET_FOREACH(nr, link->ndisc_routes, i) + if (nr->marked && IN6_ARE_ADDR_EQUAL(&nr->router, router)) { + k = route_remove(nr->route, link, NULL); + if (k < 0) + r = k; + } SET_FOREACH(rdnss, link->ndisc_rdnss, i) - if (rdnss->marked) + if (rdnss->marked && IN6_ARE_ADDR_EQUAL(&rdnss->router, router)) free(set_remove(link->ndisc_rdnss, rdnss)); SET_FOREACH(dnssl, link->ndisc_dnssl, i) - if (dnssl->marked) + if (dnssl->marked && IN6_ARE_ADDR_EQUAL(&dnssl->router, router)) free(set_remove(link->ndisc_dnssl, dnssl)); return r; } +static int ndisc_remove_old(Link *link) { + _cleanup_set_free_free_ Set *routers = NULL; + _cleanup_free_ struct in6_addr *router = NULL; + struct in6_addr *a; + NDiscAddress *na; + NDiscRoute *nr; + NDiscDNSSL *dnssl; + NDiscRDNSS *rdnss; + Iterator i; + int k, r; + + assert(link); + + routers = set_new(&in6_addr_hash_ops); + if (!routers) + return -ENOMEM; + + SET_FOREACH(na, link->ndisc_addresses, i) + if (!set_contains(routers, &na->router)) { + router = newdup(struct in6_addr, &na->router, 1); + if (!router) + return -ENOMEM; + + r = set_put(routers, router); + if (r < 0) + return r; + + assert(r > 0); + TAKE_PTR(router); + } + + SET_FOREACH(nr, link->ndisc_routes, i) + if (!set_contains(routers, &nr->router)) { + router = newdup(struct in6_addr, &nr->router, 1); + if (!router) + return -ENOMEM; + + r = set_put(routers, router); + if (r < 0) + return r; + + assert(r > 0); + TAKE_PTR(router); + } + + SET_FOREACH(rdnss, link->ndisc_rdnss, i) + if (!set_contains(routers, &rdnss->router)) { + router = newdup(struct in6_addr, &rdnss->router, 1); + if (!router) + return -ENOMEM; + + r = set_put(routers, router); + if (r < 0) + return r; + + assert(r > 0); + TAKE_PTR(router); + } + + SET_FOREACH(dnssl, link->ndisc_dnssl, i) + if (!set_contains(routers, &dnssl->router)) { + router = newdup(struct in6_addr, &dnssl->router, 1); + if (!router) + return -ENOMEM; + + r = set_put(routers, router); + if (r < 0) + return r; + + assert(r > 0); + TAKE_PTR(router); + } + + r = 0; + SET_FOREACH(a, routers, i) { + k = ndisc_remove_old_one(link, a, false); + if (k < 0) + r = k; + } + + return r; +} + +static void ndisc_route_hash_func(const NDiscRoute *x, struct siphash *state) { + route_hash_func(x->route, state); +} + +static int ndisc_route_compare_func(const NDiscRoute *a, const NDiscRoute *b) { + return route_compare_func(a->route, b->route); +} + +DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR( + ndisc_route_hash_ops, + NDiscRoute, + ndisc_route_hash_func, + ndisc_route_compare_func, + free); + static int ndisc_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { int r; @@ -130,7 +269,7 @@ static int ndisc_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *li log_link_debug(link, "NDisc routes set."); link->ndisc_routes_configured = true; - r = ndisc_remove_old(link, false); + r = ndisc_remove_old(link); if (r < 0) { link_enter_failed(link); return 1; @@ -142,6 +281,67 @@ static int ndisc_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *li return 1; } +static int ndisc_route_configure(Route *route, Link *link, sd_ndisc_router *rt) { + _cleanup_free_ NDiscRoute *nr = NULL; + NDiscRoute *nr_exist; + struct in6_addr router; + Route *ret; + int r; + + assert(route); + assert(link); + assert(rt); + + r = route_configure(route, link, ndisc_route_handler, &ret); + if (r < 0) + return log_link_error_errno(link, r, "Failed to set NDisc route: %m"); + + link->ndisc_routes_messages++; + + r = sd_ndisc_router_get_address(rt, &router); + if (r < 0) + return log_link_error_errno(link, r, "Failed to get router address from RA: %m"); + + nr = new(NDiscRoute, 1); + if (!nr) + return log_oom(); + + *nr = (NDiscRoute) { + .router = router, + .route = ret, + }; + + nr_exist = set_get(link->ndisc_routes, nr); + if (nr_exist) { + nr_exist->marked = false; + nr_exist->router = router; + return 0; + } + + r = set_ensure_put(&link->ndisc_routes, &ndisc_route_hash_ops, nr); + if (r < 0) + return log_link_error_errno(link, r, "Failed to store NDisc SLAAC route: %m"); + assert(r > 0); + TAKE_PTR(nr); + + return 0; +} + +static void ndisc_address_hash_func(const NDiscAddress *x, struct siphash *state) { + address_hash_func(x->address, state); +} + +static int ndisc_address_compare_func(const NDiscAddress *a, const NDiscAddress *b) { + return address_compare_func(a->address, b->address); +} + +DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR( + ndisc_address_hash_ops, + NDiscAddress, + ndisc_address_hash_func, + ndisc_address_compare_func, + free); + static int ndisc_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { int r; @@ -165,7 +365,7 @@ static int ndisc_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link * log_link_debug(link, "NDisc SLAAC addresses set."); link->ndisc_addresses_configured = true; - r = ndisc_remove_old(link, false); + r = ndisc_remove_old(link); if (r < 0) { link_enter_failed(link); return 1; @@ -181,34 +381,16 @@ static int ndisc_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link * return 1; } -static int ndisc_route_configure(Route *route, Link *link) { - Route *ret; - int r; - - assert(route); - assert(link); - - r = route_configure(route, link, ndisc_route_handler, &ret); - if (r < 0) - return log_link_error_errno(link, r, "Failed to set NDisc route: %m"); - - link->ndisc_routes_messages++; - - r = set_ensure_put(&link->ndisc_routes, &route_hash_ops, ret); - if (r < 0) - return log_link_error_errno(link, r, "Failed to store NDisc route: %m"); - - (void) set_remove(link->ndisc_routes_old, ret); - - return 0; -} - -static int ndisc_address_configure(Address *address, Link *link) { +static int ndisc_address_configure(Address *address, Link *link, sd_ndisc_router *rt) { + _cleanup_free_ NDiscAddress *na = NULL; + NDiscAddress *na_exist; + struct in6_addr router; Address *ret; int r; assert(address); assert(link); + assert(rt); r = address_configure(address, link, ndisc_address_handler, true, &ret); if (r < 0) @@ -216,11 +398,31 @@ static int ndisc_address_configure(Address *address, Link *link) { link->ndisc_addresses_messages++; - r = set_ensure_put(&link->ndisc_addresses, &address_hash_ops, ret); + r = sd_ndisc_router_get_address(rt, &router); + if (r < 0) + return log_link_error_errno(link, r, "Failed to get router address from RA: %m"); + + na = new(NDiscAddress, 1); + if (!na) + return log_oom(); + + *na = (NDiscAddress) { + .router = router, + .address = ret, + }; + + na_exist = set_get(link->ndisc_addresses, na); + if (na_exist) { + na_exist->marked = false; + na_exist->router = router; + return 0; + } + + r = set_ensure_put(&link->ndisc_addresses, &ndisc_address_hash_ops, na); if (r < 0) return log_link_error_errno(link, r, "Failed to store NDisc SLAAC address: %m"); - - (void) set_remove(link->ndisc_addresses_old, ret); + assert(r > 0); + TAKE_PTR(na); return 0; } @@ -286,7 +488,7 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) { route->lifetime = time_now + lifetime * USEC_PER_SEC; route->mtu = mtu; - r = ndisc_route_configure(route, link); + r = ndisc_route_configure(route, link, rt); if (r < 0) return log_link_error_errno(link, r, "Could not set default route: %m"); @@ -300,7 +502,7 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) { route_gw->gw = gateway; - r = ndisc_route_configure(route_gw, link); + r = ndisc_route_configure(route_gw, link, rt); if (r < 0) return log_link_error_errno(link, r, "Could not set gateway: %m"); } @@ -514,7 +716,7 @@ static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *r address->in_addr.in6 = *a; - r = ndisc_address_configure(address, link); + r = ndisc_address_configure(address, link, rt); if (r < 0) return log_link_error_errno(link, r, "Could not set SLAAC address: %m"); } @@ -560,7 +762,7 @@ static int ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) { if (r < 0) return log_link_error_errno(link, r, "Failed to get prefix address: %m"); - r = ndisc_route_configure(route, link); + r = ndisc_route_configure(route, link, rt); if (r < 0) return log_link_error_errno(link, r, "Could not set prefix route: %m");; @@ -617,7 +819,7 @@ static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) { if (r < 0) return log_link_error_errno(link, r, "Failed to get route address: %m"); - r = ndisc_route_configure(route, link); + r = ndisc_route_configure(route, link, rt); if (r < 0) return log_link_error_errno(link, r, "Could not set additional route: %m"); @@ -642,6 +844,7 @@ DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR( static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) { uint32_t lifetime; const struct in6_addr *a; + struct in6_addr router; NDiscRDNSS *rdnss; usec_t time_now; Iterator i; @@ -650,6 +853,10 @@ static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) { assert(link); assert(rt); + r = sd_ndisc_router_get_address(rt, &router); + if (r < 0) + return log_link_error_errno(link, r, "Failed to get router address from RA: %m"); + r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now); if (r < 0) return log_link_error_errno(link, r, "Failed to get RA timestamp: %m"); @@ -663,7 +870,8 @@ static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) { return log_link_error_errno(link, n, "Failed to get RDNSS addresses: %m"); SET_FOREACH(rdnss, link->ndisc_rdnss, i) - rdnss->marked = true; + if (IN6_ARE_ADDR_EQUAL(&rdnss->router, &router)) + rdnss->marked = true; if (lifetime == 0) return 0; @@ -682,6 +890,7 @@ static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) { rdnss = set_get(link->ndisc_rdnss, &d); if (rdnss) { rdnss->marked = false; + rdnss->router = router; rdnss->valid_until = time_now + lifetime * USEC_PER_SEC; continue; } @@ -692,6 +901,7 @@ static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) { *x = (NDiscRDNSS) { .address = a[j], + .router = router, .valid_until = time_now + lifetime * USEC_PER_SEC, }; @@ -721,6 +931,7 @@ DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR( static int ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) { _cleanup_strv_free_ char **l = NULL; + struct in6_addr router; uint32_t lifetime; usec_t time_now; NDiscDNSSL *dnssl; @@ -731,6 +942,10 @@ static int ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) { assert(link); assert(rt); + r = sd_ndisc_router_get_address(rt, &router); + if (r < 0) + return log_link_error_errno(link, r, "Failed to get router address from RA: %m"); + r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now); if (r < 0) return log_link_error_errno(link, r, "Failed to get RA timestamp: %m"); @@ -744,7 +959,8 @@ static int ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) { return log_link_error_errno(link, r, "Failed to get DNSSL addresses: %m"); SET_FOREACH(dnssl, link->ndisc_dnssl, i) - dnssl->marked = true; + if (IN6_ARE_ADDR_EQUAL(&dnssl->router, &router)) + dnssl->marked = true; if (lifetime == 0) return 0; @@ -767,10 +983,12 @@ static int ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) { dnssl = set_get(link->ndisc_dnssl, s); if (dnssl) { dnssl->marked = false; + dnssl->router = router; dnssl->valid_until = time_now + lifetime * USEC_PER_SEC; continue; } + s->router = router; s->valid_until = time_now + lifetime * USEC_PER_SEC; r = set_ensure_consume(&link->ndisc_dnssl, &ndisc_dnssl_hash_ops, TAKE_PTR(s)); @@ -865,9 +1083,11 @@ static int ndisc_router_process_options(Link *link, sd_ndisc_router *rt) { } static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) { - Address *address; - Route *route; + struct in6_addr router; uint64_t flags; + NDiscAddress *na; + NDiscRoute *nr; + Iterator i; int r; assert(link); @@ -880,17 +1100,17 @@ static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) { link_dirty(link); - while ((address = set_steal_first(link->ndisc_addresses))) { - r = set_ensure_put(&link->ndisc_addresses_old, &address_hash_ops, address); - if (r < 0) - return log_link_error_errno(link, r, "Failed to store old NDisc SLAAC address: %m"); - } + r = sd_ndisc_router_get_address(rt, &router); + if (r < 0) + return log_link_error_errno(link, r, "Failed to get router address from RA: %m"); - while ((route = set_steal_first(link->ndisc_routes))) { - r = set_ensure_put(&link->ndisc_routes_old, &route_hash_ops, route); - if (r < 0) - return log_link_error_errno(link, r, "Failed to store old NDisc route: %m"); - } + SET_FOREACH(na, link->ndisc_addresses, i) + if (IN6_ARE_ADDR_EQUAL(&na->router, &router)) + na->marked = true; + + SET_FOREACH(nr, link->ndisc_routes, i) + if (IN6_ARE_ADDR_EQUAL(&nr->router, &router)) + nr->marked = true; r = sd_ndisc_router_get_flags(rt, &flags); if (r < 0) @@ -933,7 +1153,7 @@ static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) { else log_link_debug(link, "Setting NDisc routes."); - r = ndisc_remove_old(link, false); + r = ndisc_remove_old(link); if (r < 0) return r; diff --git a/src/network/networkd-ndisc.h b/src/network/networkd-ndisc.h index c459f4245..927f555bc 100644 --- a/src/network/networkd-ndisc.h +++ b/src/network/networkd-ndisc.h @@ -2,7 +2,9 @@ #pragma once #include "conf-parser.h" +#include "networkd-address.h" #include "networkd-link.h" +#include "networkd-route.h" #include "time-util.h" typedef struct IPv6Token IPv6Token; @@ -23,9 +25,24 @@ typedef enum IPv6AcceptRAStartDHCP6Client { _IPV6_ACCEPT_RA_START_DHCP6_CLIENT_INVALID = -1, } IPv6AcceptRAStartDHCP6Client; +typedef struct NDiscAddress { + /* Used when GC'ing old DNS servers when configuration changes. */ + bool marked; + struct in6_addr router; + Address *address; +} NDiscAddress; + +typedef struct NDiscRoute { + /* Used when GC'ing old DNS servers when configuration changes. */ + bool marked; + struct in6_addr router; + Route *route; +} NDiscRoute; + typedef struct NDiscRDNSS { /* Used when GC'ing old DNS servers when configuration changes. */ bool marked; + struct in6_addr router; usec_t valid_until; struct in6_addr address; } NDiscRDNSS; @@ -33,6 +50,7 @@ typedef struct NDiscRDNSS { typedef struct NDiscDNSSL { /* Used when GC'ing old domains when configuration changes. */ bool marked; + struct in6_addr router; usec_t valid_until; /* The domain name follows immediately. */ } NDiscDNSSL; diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c index e0c490bab..003a50b68 100644 --- a/src/network/networkd-radv.c +++ b/src/network/networkd-radv.c @@ -681,7 +681,9 @@ int radv_add_prefix(Link *link, const struct in6_addr *prefix, uint8_t prefix_le int r; assert(link); - assert(link->radv); + + if (!link->radv) + return 0; r = sd_radv_prefix_new(&p); if (r < 0) diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index 541bf1e79..28c0f3b89 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -9,6 +9,7 @@ #include "netlink-util.h" #include "networkd-ipv4ll.h" #include "networkd-manager.h" +#include "networkd-ndisc.h" #include "networkd-route.h" #include "parse-util.h" #include "set.h" @@ -142,6 +143,9 @@ void route_free(Route *route) { network_config_section_free(route->section); if (route->link) { + NDiscRoute *n; + Iterator i; + set_remove(route->link->routes, route); set_remove(route->link->routes_foreign, route); set_remove(route->link->dhcp_routes, route); @@ -150,8 +154,9 @@ void route_free(Route *route) { set_remove(route->link->dhcp6_routes_old, route); set_remove(route->link->dhcp6_pd_routes, route); set_remove(route->link->dhcp6_pd_routes_old, route); - set_remove(route->link->ndisc_routes, route); - set_remove(route->link->ndisc_routes_old, route); + SET_FOREACH(n, route->link->ndisc_routes, i) + if (n->route == route) + free(set_remove(route->link->ndisc_routes, n)); } ordered_set_free_free(route->multipath_routes); @@ -161,7 +166,7 @@ void route_free(Route *route) { free(route); } -static void route_hash_func(const Route *route, struct siphash *state) { +void route_hash_func(const Route *route, struct siphash *state) { assert(route); siphash24_compress(&route->family, sizeof(route->family), state); @@ -196,7 +201,7 @@ static void route_hash_func(const Route *route, struct siphash *state) { } } -static int route_compare_func(const Route *a, const Route *b) { +int route_compare_func(const Route *a, const Route *b) { int r; r = CMP(a->family, b->family); diff --git a/src/network/networkd-route.h b/src/network/networkd-route.h index 3beee9b03..75651fa51 100644 --- a/src/network/networkd-route.h +++ b/src/network/networkd-route.h @@ -62,6 +62,8 @@ struct Route { LIST_FIELDS(Route, routes); }; +void route_hash_func(const Route *route, struct siphash *state); +int route_compare_func(const Route *a, const Route *b); extern const struct hash_ops route_hash_ops; int route_new(Route **ret); diff --git a/src/partition/growfs.c b/src/partition/growfs.c index 98a7e4d31..8f5448937 100644 --- a/src/partition/growfs.c +++ b/src/partition/growfs.c @@ -11,6 +11,7 @@ #include #include "blockdev-util.h" +#include "btrfs-util.h" #include "crypt-util.h" #include "device-nodes.h" #include "dissect-image.h" @@ -94,6 +95,8 @@ static int maybe_resize_underlying_device(const char *mountpath, dev_t main_devn if (r < 0) return log_error_errno(r, "Failed to determine underlying block device of \"%s\": %m", mountpath); + if (devno == 0) + return log_error_errno(SYNTHETIC_ERRNO(ENODEV), "File system \"%s\" not backed by block device.", arg_target); log_debug("Underlying device %d:%d, main dev %d:%d, %s", major(devno), minor(devno), @@ -210,8 +213,12 @@ static int run(int argc, char *argv[]) { return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "\"%s\" is not a mount point: %m", arg_target); r = get_block_device(arg_target, &devno); + if (r == -EUCLEAN) + return btrfs_log_dev_root(LOG_ERR, r, arg_target); if (r < 0) return log_error_errno(r, "Failed to determine block device of \"%s\": %m", arg_target); + if (devno == 0) + return log_error_errno(SYNTHETIC_ERRNO(ENODEV), "File system \"%s\" not backed by block device.", arg_target); r = maybe_resize_underlying_device(arg_target, devno); if (r < 0) diff --git a/src/partition/repart.c b/src/partition/repart.c index 2e5f5d134..9a35e9b73 100644 --- a/src/partition/repart.c +++ b/src/partition/repart.c @@ -2734,6 +2734,8 @@ static int context_open_copy_block_paths(Context *context) { /* Special support for btrfs */ r = btrfs_get_block_device_fd(source_fd, &devt); + if (r == -EUCLEAN) + return btrfs_log_dev_root(LOG_ERR, r, p->copy_blocks_path); if (r < 0) return log_error_errno(r, "Unable to determine backing block device of '%s': %m", p->copy_blocks_path); @@ -3150,6 +3152,8 @@ static int find_root(char **ret, int *ret_fd) { } r = acquire_root_devno(arg_node, O_RDONLY|O_CLOEXEC, ret, ret_fd); + if (r == -EUCLEAN) + return btrfs_log_dev_root(LOG_ERR, r, arg_node); if (r < 0) return log_error_errno(r, "Failed to determine backing device of %s: %m", arg_node); @@ -3177,6 +3181,8 @@ static int find_root(char **ret, int *ret_fd) { r = acquire_root_devno(p, O_RDONLY|O_DIRECTORY|O_CLOEXEC, ret, ret_fd); if (r < 0) { + if (r == -EUCLEAN) + return btrfs_log_dev_root(LOG_ERR, r, p); if (r != -ENODEV) return log_error_errno(r, "Failed to determine backing device of %s: %m", p); } else diff --git a/src/resolve/resolvectl.c b/src/resolve/resolvectl.c index 3072b984e..8378ff591 100644 --- a/src/resolve/resolvectl.c +++ b/src/resolve/resolvectl.c @@ -2545,6 +2545,7 @@ static int native_help(void) { " dnssec [LINK [MODE]] Get/set per-interface DNSSEC mode\n" " nta [LINK [DOMAIN...]] Get/set per-interface DNSSEC NTA\n" " revert LINK Revert per-interface configuration\n" + " log-level [LEVEL] Get/set logging threshold for systemd-resolved\n" "\nOptions:\n" " -h --help Show this help\n" " --version Show package version\n" diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c index 1da590b68..b1974579a 100644 --- a/src/resolve/resolved-manager.c +++ b/src/resolve/resolved-manager.c @@ -349,7 +349,8 @@ static int determine_hostname(char **full_hostname, char **llmnr_hostname, char #if HAVE_LIBIDN2 r = idn2_to_unicode_8z8z(label, &utf8, 0); if (r != IDN2_OK) - return log_error("Failed to undo IDNA: %s", idn2_strerror(r)); + return log_error_errno(SYNTHETIC_ERRNO(EUCLEAN), + "Failed to undo IDNA: %s", idn2_strerror(r)); assert(utf8_is_valid(utf8)); r = strlen(utf8); diff --git a/src/shared/ethtool-util.c b/src/shared/ethtool-util.c index 3bb12f922..14e91e3e4 100644 --- a/src/shared/ethtool-util.c +++ b/src/shared/ethtool-util.c @@ -943,7 +943,7 @@ int config_parse_channel(const char *unit, } if (k < 1) { - log_syntax(unit, LOG_ERR, filename, line, -EINVAL, "Invalid %s value, ignoring: %s", lvalue, rvalue); + log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid %s value, ignoring: %s", lvalue, rvalue); return 0; } diff --git a/src/shared/log-link.h b/src/shared/log-link.h index 2d0380269..b844f9ef8 100644 --- a/src/shared/log-link.h +++ b/src/shared/log-link.h @@ -14,24 +14,26 @@ * See, network/networkd-link.h for example. */ -#define log_link_full(link, level, error, ...) \ +#define log_link_full_errno(link, level, error, ...) \ ({ \ const Link *_l = (link); \ (_l && _l->ifname) ? log_object_internal(level, error, PROJECT_FILE, __LINE__, __func__, "INTERFACE=", _l->ifname, NULL, NULL, ##__VA_ARGS__) : \ log_internal(level, error, PROJECT_FILE, __LINE__, __func__, ##__VA_ARGS__); \ }) \ -#define log_link_debug(link, ...) log_link_full(link, LOG_DEBUG, 0, ##__VA_ARGS__) -#define log_link_info(link, ...) log_link_full(link, LOG_INFO, 0, ##__VA_ARGS__) -#define log_link_notice(link, ...) log_link_full(link, LOG_NOTICE, 0, ##__VA_ARGS__) -#define log_link_warning(link, ...) log_link_full(link, LOG_WARNING, 0, ##__VA_ARGS__) -#define log_link_error(link, ...) log_link_full(link, LOG_ERR, 0, ##__VA_ARGS__) +#define log_link_full(link, level, ...) (void) log_link_full_errno(link, level, 0, __VA_ARGS__) -#define log_link_debug_errno(link, error, ...) log_link_full(link, LOG_DEBUG, error, ##__VA_ARGS__) -#define log_link_info_errno(link, error, ...) log_link_full(link, LOG_INFO, error, ##__VA_ARGS__) -#define log_link_notice_errno(link, error, ...) log_link_full(link, LOG_NOTICE, error, ##__VA_ARGS__) -#define log_link_warning_errno(link, error, ...) log_link_full(link, LOG_WARNING, error, ##__VA_ARGS__) -#define log_link_error_errno(link, error, ...) log_link_full(link, LOG_ERR, error, ##__VA_ARGS__) +#define log_link_debug(link, ...) log_link_full_errno(link, LOG_DEBUG, 0, __VA_ARGS__) +#define log_link_info(link, ...) log_link_full(link, LOG_INFO, __VA_ARGS__) +#define log_link_notice(link, ...) log_link_full(link, LOG_NOTICE, __VA_ARGS__) +#define log_link_warning(link, ...) log_link_full(link, LOG_WARNING, __VA_ARGS__) +#define log_link_error(link, ...) log_link_full(link, LOG_ERR, __VA_ARGS__) + +#define log_link_debug_errno(link, error, ...) log_link_full_errno(link, LOG_DEBUG, error, __VA_ARGS__) +#define log_link_info_errno(link, error, ...) log_link_full_errno(link, LOG_INFO, error, __VA_ARGS__) +#define log_link_notice_errno(link, error, ...) log_link_full_errno(link, LOG_NOTICE, error, __VA_ARGS__) +#define log_link_warning_errno(link, error, ...) log_link_full_errno(link, LOG_WARNING, error, __VA_ARGS__) +#define log_link_error_errno(link, error, ...) log_link_full_errno(link, LOG_ERR, error, __VA_ARGS__) #define LOG_LINK_MESSAGE(link, fmt, ...) "MESSAGE=%s: " fmt, (link)->ifname, ##__VA_ARGS__ #define LOG_LINK_INTERFACE(link) "INTERFACE=%s", (link)->ifname diff --git a/src/shared/pkcs11-util.c b/src/shared/pkcs11-util.c index 632964df4..4088439f9 100644 --- a/src/shared/pkcs11-util.c +++ b/src/shared/pkcs11-util.c @@ -212,13 +212,15 @@ int pkcs11_token_login( "Failed to log into security token '%s': %s", token_label, p11_kit_strerror(rv)); log_info("Successfully logged into security token '%s' via protected authentication path.", token_label); - *ret_used_pin = NULL; + if (ret_used_pin) + *ret_used_pin = NULL; return 0; } if (!FLAGS_SET(token_info->flags, CKF_LOGIN_REQUIRED)) { log_info("No login into security token '%s' required.", token_label); - *ret_used_pin = NULL; + if (ret_used_pin) + *ret_used_pin = NULL; return 0; } diff --git a/src/shared/sleep-config.c b/src/shared/sleep-config.c index 0dccc8f97..96c125b99 100644 --- a/src/shared/sleep-config.c +++ b/src/shared/sleep-config.c @@ -403,6 +403,8 @@ int find_hibernate_location(HibernateLocation **ret_hibernate_location) { r = swap_device_to_device_id(swap, &swap_device); if (r < 0) return log_debug_errno(r, "%s: failed to query device number: %m", swap->device); + if (swap_device == 0) + return log_debug_errno(SYNTHETIC_ERRNO(ENODEV), "%s: not backed by block device.", swap->device); hibernate_location = hibernate_location_free(hibernate_location); hibernate_location = new(HibernateLocation, 1); diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index eafae6e4f..ddcf3bb9a 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -2085,8 +2085,10 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat if (streq(key, "systemd.unit")) { if (proc_cmdline_value_missing(key, value)) return 0; - if (!unit_name_is_valid(value, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE)) - return log_warning("Unit name specified on %s= is not valid, ignoring: %s", key, value); + if (!unit_name_is_valid(value, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE)) { + log_warning("Unit name specified on %s= is not valid, ignoring: %s", key, value); + return 0; + } return free_and_strdup_warn(ret, key); diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index 2404e36bf..2db3773fc 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -773,6 +773,7 @@ static int fd_set_perms(Item *i, int fd, const char *path, const struct stat *st struct stat stbuf; mode_t new_mode; bool do_chown; + int r; assert(i); assert(fd); @@ -818,8 +819,9 @@ static int fd_set_perms(Item *i, int fd, const char *path, const struct stat *st log_debug("\"%s\" matches temporary mode %o already.", path, m); else { log_debug("Temporarily changing \"%s\" to mode %o.", path, m); - if (fchmod_opath(fd, m) < 0) - return log_error_errno(errno, "fchmod() of %s failed: %m", path); + r = fchmod_opath(fd, m); + if (r < 0) + return log_error_errno(r, "fchmod() of %s failed: %m", path); } } } @@ -850,8 +852,9 @@ static int fd_set_perms(Item *i, int fd, const char *path, const struct stat *st log_debug("\"%s\" matches mode %o already.", path, new_mode); else { log_debug("Changing \"%s\" to mode %o.", path, new_mode); - if (fchmod_opath(fd, new_mode) < 0) - return log_error_errno(errno, "fchmod() of %s failed: %m", path); + r = fchmod_opath(fd, new_mode); + if (r < 0) + return log_error_errno(r, "fchmod() of %s failed: %m", path); } } } diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c index 72ef0c56b..03fd429b2 100644 --- a/src/udev/net/link-config.c +++ b/src/udev/net/link-config.c @@ -320,7 +320,8 @@ static int get_mac(sd_device *device, MACAddressPolicy policy, struct ether_addr case NET_ADDR_PERM: break; default: - return log_device_warning(device, "Unknown addr_assign_type %u, ignoring", addr_type); + log_device_warning(device, "Unknown addr_assign_type %u, ignoring", addr_type); + return 0; } if (want_random == (addr_type == NET_ADDR_RANDOM)) diff --git a/src/udev/udev-builtin-keyboard.c b/src/udev/udev-builtin-keyboard.c index bb82e8ae9..eb980cb98 100644 --- a/src/udev/udev-builtin-keyboard.c +++ b/src/udev/udev-builtin-keyboard.c @@ -87,7 +87,7 @@ static int map_keycode(sd_device *dev, int fd, int scancode, const char *keycode return 0; } -static char* parse_token(const char *current, int32_t *val_out) { +static const char* parse_token(const char *current, int32_t *val_out) { char *next; int32_t val; @@ -109,7 +109,7 @@ static char* parse_token(const char *current, int32_t *val_out) { static int override_abs(sd_device *dev, int fd, unsigned evcode, const char *value) { struct input_absinfo absinfo; - char *next; + const char *next; int r; r = ioctl(fd, EVIOCGABS(evcode), &absinfo); @@ -122,7 +122,7 @@ static int override_abs(sd_device *dev, int fd, unsigned evcode, const char *val next = parse_token(next, &absinfo.fuzz); next = parse_token(next, &absinfo.flat); if (!next) - return log_device_error(dev, "Failed to parse EV_ABS override '%s'", value); + return log_device_error_errno(dev, SYNTHETIC_ERRNO(EINVAL), "Failed to parse EV_ABS override '%s'", value); log_device_debug(dev, "keyboard: %x overridden with %"PRIi32"/%"PRIi32"/%"PRIi32"/%"PRIi32"/%"PRIi32, evcode, absinfo.minimum, absinfo.maximum, absinfo.resolution, absinfo.fuzz, absinfo.flat); diff --git a/src/udev/udev-builtin-uaccess.c b/src/udev/udev-builtin-uaccess.c index 63401a570..d552316ee 100644 --- a/src/udev/udev-builtin-uaccess.c +++ b/src/udev/udev-builtin-uaccess.c @@ -50,7 +50,7 @@ static int builtin_uaccess(sd_device *dev, int argc, char *argv[], bool test) { r = devnode_acl(path, true, false, 0, true, uid); if (r < 0) { - log_device_full(dev, r == -ENOENT ? LOG_DEBUG : LOG_ERR, r, "Failed to apply ACL: %m"); + log_device_full_errno(dev, r == -ENOENT ? LOG_DEBUG : LOG_ERR, r, "Failed to apply ACL: %m"); goto finish; } @@ -64,7 +64,7 @@ finish: /* Better be safe than sorry and reset ACL */ k = devnode_acl(path, true, false, 0, false, 0); if (k < 0) { - log_device_full(dev, k == -ENOENT ? LOG_DEBUG : LOG_ERR, k, "Failed to apply ACL: %m"); + log_device_full_errno(dev, k == -ENOENT ? LOG_DEBUG : LOG_ERR, k, "Failed to apply ACL: %m"); if (r >= 0) r = k; } diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c index e1c2baf7f..f27696430 100644 --- a/src/udev/udev-event.c +++ b/src/udev/udev-event.c @@ -633,7 +633,7 @@ static int on_spawn_sigchld(sd_event_source *s, const siginfo_t *si, void *userd if (si->si_status == 0) log_device_debug(spawn->device, "Process '%s' succeeded.", spawn->cmd); else - log_device_full(spawn->device, spawn->accept_failure ? LOG_DEBUG : LOG_WARNING, 0, + log_device_full(spawn->device, spawn->accept_failure ? LOG_DEBUG : LOG_WARNING, "Process '%s' failed with exit code %i.", spawn->cmd, si->si_status); ret = si->si_status; break; diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c index 31a340309..643d413ba 100644 --- a/src/udev/udev-node.c +++ b/src/udev/udev-node.c @@ -325,13 +325,13 @@ static int node_permissions_apply(sd_device *dev, bool apply_mac, r = chmod_and_chown(devnode, mode, uid, gid); if (r < 0) - log_device_full(dev, r == -ENOENT ? LOG_DEBUG : LOG_ERR, r, - "Failed to set owner/mode of %s to uid=" UID_FMT - ", gid=" GID_FMT ", mode=%#o: %m", - devnode, - uid_is_valid(uid) ? uid : stats.st_uid, - gid_is_valid(gid) ? gid : stats.st_gid, - mode != MODE_INVALID ? mode & 0777 : stats.st_mode & 0777); + log_device_full_errno(dev, r == -ENOENT ? LOG_DEBUG : LOG_ERR, r, + "Failed to set owner/mode of %s to uid=" UID_FMT + ", gid=" GID_FMT ", mode=%#o: %m", + devnode, + uid_is_valid(uid) ? uid : stats.st_uid, + gid_is_valid(gid) ? gid : stats.st_gid, + mode != MODE_INVALID ? mode & 0777 : stats.st_mode & 0777); } else log_device_debug(dev, "Preserve permissions of %s, uid=" UID_FMT ", gid=" GID_FMT ", mode=%#o", devnode, @@ -348,8 +348,8 @@ static int node_permissions_apply(sd_device *dev, bool apply_mac, q = mac_selinux_apply(devnode, label); if (q < 0) - log_device_full(dev, q == -ENOENT ? LOG_DEBUG : LOG_ERR, q, - "SECLABEL: failed to set SELinux label '%s': %m", label); + log_device_full_errno(dev, q == -ENOENT ? LOG_DEBUG : LOG_ERR, q, + "SECLABEL: failed to set SELinux label '%s': %m", label); else log_device_debug(dev, "SECLABEL: set SELinux label '%s'", label); @@ -358,8 +358,8 @@ static int node_permissions_apply(sd_device *dev, bool apply_mac, q = mac_smack_apply(devnode, SMACK_ATTR_ACCESS, label); if (q < 0) - log_device_full(dev, q == -ENOENT ? LOG_DEBUG : LOG_ERR, q, - "SECLABEL: failed to set SMACK label '%s': %m", label); + log_device_full_errno(dev, q == -ENOENT ? LOG_DEBUG : LOG_ERR, q, + "SECLABEL: failed to set SMACK label '%s': %m", label); else log_device_debug(dev, "SECLABEL: set SMACK label '%s'", label); diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c index c36f032f6..9d6dc4244 100644 --- a/src/udev/udev-rules.c +++ b/src/udev/udev-rules.c @@ -182,43 +182,46 @@ struct UdevRules { /*** Logging helpers ***/ -#define log_rule_full(device, rules, level, error, fmt, ...) \ +#define log_rule_full_errno(device, rules, level, error, fmt, ...) \ ({ \ UdevRules *_r = (rules); \ UdevRuleFile *_f = _r ? _r->current_file : NULL; \ UdevRuleLine *_l = _f ? _f->current_line : NULL; \ const char *_n = _f ? _f->filename : NULL; \ \ - log_device_full(device, level, error, "%s:%u " fmt, \ - strna(_n), _l ? _l->line_number : 0, \ - ##__VA_ARGS__); \ + log_device_full_errno(device, level, error, "%s:%u " fmt, \ + strna(_n), _l ? _l->line_number : 0, \ + ##__VA_ARGS__); \ }) -#define log_rule_debug(device, rules, ...) log_rule_full(device, rules, LOG_DEBUG, 0, ##__VA_ARGS__) -#define log_rule_info(device, rules, ...) log_rule_full(device, rules, LOG_INFO, 0, ##__VA_ARGS__) -#define log_rule_notice(device, rules, ...) log_rule_full(device, rules, LOG_NOTICE, 0, ##__VA_ARGS__) -#define log_rule_warning(device, rules, ...) log_rule_full(device, rules, LOG_WARNING, 0, ##__VA_ARGS__) -#define log_rule_error(device, rules, ...) log_rule_full(device, rules, LOG_ERR, 0, ##__VA_ARGS__) +#define log_rule_full(device, rules, level, ...) (void) log_rule_full_errno(device, rules, level, 0, __VA_ARGS__) -#define log_rule_debug_errno(device, rules, error, ...) log_rule_full(device, rules, LOG_DEBUG, error, ##__VA_ARGS__) -#define log_rule_info_errno(device, rules, error, ...) log_rule_full(device, rules, LOG_INFO, error, ##__VA_ARGS__) -#define log_rule_notice_errno(device, rules, error, ...) log_rule_full(device, rules, LOG_NOTICE, error, ##__VA_ARGS__) -#define log_rule_warning_errno(device, rules, error, ...) log_rule_full(device, rules, LOG_WARNING, error, ##__VA_ARGS__) -#define log_rule_error_errno(device, rules, error, ...) log_rule_full(device, rules, LOG_ERR, error, ##__VA_ARGS__) +#define log_rule_debug(device, rules, ...) log_rule_full_errno(device, rules, LOG_DEBUG, 0, __VA_ARGS__) +#define log_rule_info(device, rules, ...) log_rule_full(device, rules, LOG_INFO, __VA_ARGS__) +#define log_rule_notice(device, rules, ...) log_rule_full(device, rules, LOG_NOTICE, __VA_ARGS__) +#define log_rule_warning(device, rules, ...) log_rule_full(device, rules, LOG_WARNING, __VA_ARGS__) +#define log_rule_error(device, rules, ...) log_rule_full(device, rules, LOG_ERR, __VA_ARGS__) -#define log_token_full(rules, ...) log_rule_full(NULL, rules, ##__VA_ARGS__) +#define log_rule_debug_errno(device, rules, error, ...) log_rule_full_errno(device, rules, LOG_DEBUG, error, __VA_ARGS__) +#define log_rule_info_errno(device, rules, error, ...) log_rule_full_errno(device, rules, LOG_INFO, error, __VA_ARGS__) +#define log_rule_notice_errno(device, rules, error, ...) log_rule_full_errno(device, rules, LOG_NOTICE, error, __VA_ARGS__) +#define log_rule_warning_errno(device, rules, error, ...) log_rule_full_errno(device, rules, LOG_WARNING, error, __VA_ARGS__) +#define log_rule_error_errno(device, rules, error, ...) log_rule_full_errno(device, rules, LOG_ERR, error, __VA_ARGS__) -#define log_token_debug(rules, ...) log_token_full(rules, LOG_DEBUG, 0, ##__VA_ARGS__) -#define log_token_info(rules, ...) log_token_full(rules, LOG_INFO, 0, ##__VA_ARGS__) -#define log_token_notice(rules, ...) log_token_full(rules, LOG_NOTICE, 0, ##__VA_ARGS__) -#define log_token_warning(rules, ...) log_token_full(rules, LOG_WARNING, 0, ##__VA_ARGS__) -#define log_token_error(rules, ...) log_token_full(rules, LOG_ERR, 0, ##__VA_ARGS__) +#define log_token_full_errno(rules, level, error, ...) log_rule_full_errno(NULL, rules, level, error, __VA_ARGS__) +#define log_token_full(rules, level, ...) (void) log_token_full_errno(rules, level, 0, __VA_ARGS__) -#define log_token_debug_errno(rules, error, ...) log_token_full(rules, LOG_DEBUG, error, ##__VA_ARGS__) -#define log_token_info_errno(rules, error, ...) log_token_full(rules, LOG_INFO, error, ##__VA_ARGS__) -#define log_token_notice_errno(rules, error, ...) log_token_full(rules, LOG_NOTICE, error, ##__VA_ARGS__) -#define log_token_warning_errno(rules, error, ...) log_token_full(rules, LOG_WARNING, error, ##__VA_ARGS__) -#define log_token_error_errno(rules, error, ...) log_token_full(rules, LOG_ERR, error, ##__VA_ARGS__) +#define log_token_debug(rules, ...) log_token_full_errno(rules, LOG_DEBUG, 0, __VA_ARGS__) +#define log_token_info(rules, ...) log_token_full(rules, LOG_INFO, __VA_ARGS__) +#define log_token_notice(rules, ...) log_token_full(rules, LOG_NOTICE, __VA_ARGS__) +#define log_token_warning(rules, ...) log_token_full(rules, LOG_WARNING, __VA_ARGS__) +#define log_token_error(rules, ...) log_token_full(rules, LOG_ERR, __VA_ARGS__) + +#define log_token_debug_errno(rules, error, ...) log_token_full_errno(rules, LOG_DEBUG, error, __VA_ARGS__) +#define log_token_info_errno(rules, error, ...) log_token_full_errno(rules, LOG_INFO, error, __VA_ARGS__) +#define log_token_notice_errno(rules, error, ...) log_token_full_errno(rules, LOG_NOTICE, error, __VA_ARGS__) +#define log_token_warning_errno(rules, error, ...) log_token_full_errno(rules, LOG_WARNING, error, __VA_ARGS__) +#define log_token_error_errno(rules, error, ...) log_token_full_errno(rules, LOG_ERR, error, __VA_ARGS__) #define _log_token_invalid(rules, key, type) \ log_token_error_errno(rules, SYNTHETIC_ERRNO(EINVAL), \ diff --git a/src/udev/udev-watch.c b/src/udev/udev-watch.c index 96a25ddf7..d87a43537 100644 --- a/src/udev/udev-watch.c +++ b/src/udev/udev-watch.c @@ -97,10 +97,8 @@ int udev_watch_begin(sd_device *dev) { log_device_debug(dev, "Adding watch on '%s'", devnode); wd = inotify_add_watch(inotify_fd, devnode, IN_CLOSE_WRITE); if (wd < 0) - return log_device_full(dev, - errno == ENOENT ? LOG_DEBUG : LOG_ERR, - errno, - "Failed to add device '%s' to watch: %m", devnode); + return log_device_full_errno(dev, errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno, + "Failed to add device '%s' to watch: %m", devnode); device_set_watch_handle(dev, wd); diff --git a/src/udev/udevd.c b/src/udev/udevd.c index f3236dedf..0551d2738 100644 --- a/src/udev/udevd.c +++ b/src/udev/udevd.c @@ -1685,8 +1685,11 @@ static int manager_new(Manager **ret, int fd_ctrl, int fd_uevent, const char *cg /* Bump receiver buffer, but only if we are not called via socket activation, as in that * case systemd sets the receive buffer size for us, and the value in the .socket unit * should take full effect. */ - if (fd_uevent < 0) - (void) sd_device_monitor_set_receive_buffer_size(manager->monitor, 128 * 1024 * 1024); + if (fd_uevent < 0) { + r = sd_device_monitor_set_receive_buffer_size(manager->monitor, 128 * 1024 * 1024); + if (r < 0) + log_warning_errno(r, "Failed to set receive buffer size for device monitor, ignoring: %m"); + } r = device_monitor_enable_receiving(manager->monitor); if (r < 0) diff --git a/src/update-done/update-done.c b/src/update-done/update-done.c index c001802dc..e9d589e0e 100644 --- a/src/update-done/update-done.c +++ b/src/update-done/update-done.c @@ -31,7 +31,7 @@ static int apply_timestamp(const char *path, struct timespec *ts) { r = write_string_file_atomic_label_ts(path, message, ts); if (r == -EROFS) - return log_debug("Cannot create \"%s\", file system is read-only.", path); + return log_debug_errno(r, "Cannot create \"%s\", file system is read-only.", path); if (r < 0) return log_error_errno(r, "Failed to write \"%s\": %m", path); return 0; diff --git a/src/update-utmp/update-utmp.c b/src/update-utmp/update-utmp.c index 47354d501..4ab90a63e 100644 --- a/src/update-utmp/update-utmp.c +++ b/src/update-utmp/update-utmp.c @@ -187,8 +187,10 @@ static int on_runlevel(Context *c) { runlevel = get_current_runlevel(c); if (runlevel < 0) return runlevel; - if (runlevel == 0) - return log_warning("Failed to get new runlevel, utmp update skipped."); + if (runlevel == 0) { + log_warning("Failed to get new runlevel, utmp update skipped."); + return 0; + } if (previous == runlevel) return 0; diff --git a/src/volatile-root/volatile-root.c b/src/volatile-root/volatile-root.c index e55864d6c..6a0846424 100644 --- a/src/volatile-root/volatile-root.c +++ b/src/volatile-root/volatile-root.c @@ -175,7 +175,7 @@ static int run(int argc, char *argv[]) { r = get_block_device_harder(path, &devt); if (r < 0) return log_error_errno(r, "Failed to determine device major/minor of %s: %m", path); - else if (r > 0) { + else if (r > 0) { /* backed by block device */ _cleanup_free_ char *dn = NULL; r = device_path_make_major_minor(S_IFBLK, devt, &dn); diff --git a/test/test-execute/exec-dynamicuser-statedir.service b/test/test-execute/exec-dynamicuser-statedir.service index ca40934de..6103193ba 100644 --- a/test/test-execute/exec-dynamicuser-statedir.service +++ b/test/test-execute/exec-dynamicuser-statedir.service @@ -10,10 +10,10 @@ ExecStart=test -f /var/lib/waldo/yay ExecStart=test -f /var/lib/quux/pief/yayyay ExecStart=test -f /var/lib/private/waldo/yay ExecStart=test -f /var/lib/private/quux/pief/yayyay -ExecStart=/bin/sh -x -c 'test "$$STATE_DIRECTORY" = "%S/waldo:%S/quux/pief"' +ExecStart=sh -x -c 'test "$$STATE_DIRECTORY" = "%S/waldo:%S/quux/pief"' # Make sure that /var/lib/private/waldo is really the only writable directory besides the obvious candidates -ExecStart=sh -x -c 'test $$(find / \( -path /var/tmp -o -path /tmp -o -path /proc -o -path /dev/mqueue -o -path /dev/shm -o -path /sys/fs/bpf -o -path /dev/.lxc \) -prune -o -type d -writable -print 2>/dev/null | sort -u | tr -d '\\\\n') = /var/lib/private/quux/pief/var/lib/private/waldo' +ExecStart=sh -x -c 'test $$(find / \\( -path /var/tmp -o -path /tmp -o -path /proc -o -path /dev/mqueue -o -path /dev/shm -o -path /sys/fs/bpf -o -path /dev/.lxc \\) -prune -o -type d -writable -print 2>/dev/null | sort -u | tr -d "\\\\n") = /var/lib/private/quux/pief/var/lib/private/waldo' Type=oneshot DynamicUser=yes diff --git a/test/test-network/conf/25-address-static.network b/test/test-network/conf/25-address-static.network index e9780f2ee..f8119d13e 100644 --- a/test/test-network/conf/25-address-static.network +++ b/test/test-network/conf/25-address-static.network @@ -51,3 +51,261 @@ Peer=2001:db8:0:f103::10/128 [Address] Address=::/64 + +# test for ENOBUFS issue #17012 +[Network] +Address=10.3.3.1/16 +Address=10.3.3.2/16 +Address=10.3.3.3/16 +Address=10.3.3.4/16 +Address=10.3.3.5/16 +Address=10.3.3.6/16 +Address=10.3.3.7/16 +Address=10.3.3.8/16 +Address=10.3.3.9/16 +Address=10.3.3.10/16 +Address=10.3.3.11/16 +Address=10.3.3.12/16 +Address=10.3.3.13/16 +Address=10.3.3.14/16 +Address=10.3.3.15/16 +Address=10.3.3.16/16 +Address=10.3.3.17/16 +Address=10.3.3.18/16 +Address=10.3.3.19/16 +Address=10.3.3.20/16 +Address=10.3.3.21/16 +Address=10.3.3.22/16 +Address=10.3.3.23/16 +Address=10.3.3.24/16 +Address=10.3.3.25/16 +Address=10.3.3.26/16 +Address=10.3.3.27/16 +Address=10.3.3.28/16 +Address=10.3.3.29/16 +Address=10.3.3.30/16 +Address=10.3.3.31/16 +Address=10.3.3.32/16 +Address=10.3.3.33/16 +Address=10.3.3.34/16 +Address=10.3.3.35/16 +Address=10.3.3.36/16 +Address=10.3.3.37/16 +Address=10.3.3.38/16 +Address=10.3.3.39/16 +Address=10.3.3.40/16 +Address=10.3.3.41/16 +Address=10.3.3.42/16 +Address=10.3.3.43/16 +Address=10.3.3.44/16 +Address=10.3.3.45/16 +Address=10.3.3.46/16 +Address=10.3.3.47/16 +Address=10.3.3.48/16 +Address=10.3.3.49/16 +Address=10.3.3.50/16 +Address=10.3.3.51/16 +Address=10.3.3.52/16 +Address=10.3.3.53/16 +Address=10.3.3.54/16 +Address=10.3.3.55/16 +Address=10.3.3.56/16 +Address=10.3.3.57/16 +Address=10.3.3.58/16 +Address=10.3.3.59/16 +Address=10.3.3.60/16 +Address=10.3.3.61/16 +Address=10.3.3.62/16 +Address=10.3.3.63/16 +Address=10.3.3.64/16 +Address=10.3.3.65/16 +Address=10.3.3.66/16 +Address=10.3.3.67/16 +Address=10.3.3.68/16 +Address=10.3.3.69/16 +Address=10.3.3.70/16 +Address=10.3.3.71/16 +Address=10.3.3.72/16 +Address=10.3.3.73/16 +Address=10.3.3.74/16 +Address=10.3.3.75/16 +Address=10.3.3.76/16 +Address=10.3.3.77/16 +Address=10.3.3.78/16 +Address=10.3.3.79/16 +Address=10.3.3.80/16 +Address=10.3.3.81/16 +Address=10.3.3.82/16 +Address=10.3.3.83/16 +Address=10.3.3.84/16 +Address=10.3.3.85/16 +Address=10.3.3.86/16 +Address=10.3.3.87/16 +Address=10.3.3.88/16 +Address=10.3.3.89/16 +Address=10.3.3.90/16 +Address=10.3.3.91/16 +Address=10.3.3.92/16 +Address=10.3.3.93/16 +Address=10.3.3.94/16 +Address=10.3.3.95/16 +Address=10.3.3.96/16 +Address=10.3.3.97/16 +Address=10.3.3.98/16 +Address=10.3.3.99/16 +Address=10.3.3.100/16 +Address=10.3.3.101/16 +Address=10.3.3.101/16 +Address=10.3.3.102/16 +Address=10.3.3.103/16 +Address=10.3.3.104/16 +Address=10.3.3.105/16 +Address=10.3.3.106/16 +Address=10.3.3.107/16 +Address=10.3.3.108/16 +Address=10.3.3.109/16 +Address=10.3.3.110/16 +Address=10.3.3.111/16 +Address=10.3.3.112/16 +Address=10.3.3.113/16 +Address=10.3.3.114/16 +Address=10.3.3.115/16 +Address=10.3.3.116/16 +Address=10.3.3.117/16 +Address=10.3.3.118/16 +Address=10.3.3.119/16 +Address=10.3.3.120/16 +Address=10.3.3.121/16 +Address=10.3.3.122/16 +Address=10.3.3.123/16 +Address=10.3.3.124/16 +Address=10.3.3.125/16 +Address=10.3.3.126/16 +Address=10.3.3.127/16 +Address=10.3.3.128/16 +Address=10.3.3.129/16 +Address=10.3.3.130/16 +Address=10.3.3.131/16 +Address=10.3.3.132/16 +Address=10.3.3.133/16 +Address=10.3.3.134/16 +Address=10.3.3.135/16 +Address=10.3.3.136/16 +Address=10.3.3.137/16 +Address=10.3.3.138/16 +Address=10.3.3.139/16 +Address=10.3.3.140/16 +Address=10.3.3.141/16 +Address=10.3.3.142/16 +Address=10.3.3.143/16 +Address=10.3.3.144/16 +Address=10.3.3.145/16 +Address=10.3.3.146/16 +Address=10.3.3.147/16 +Address=10.3.3.148/16 +Address=10.3.3.149/16 +Address=10.3.3.150/16 +Address=10.3.3.151/16 +Address=10.3.3.152/16 +Address=10.3.3.153/16 +Address=10.3.3.154/16 +Address=10.3.3.155/16 +Address=10.3.3.156/16 +Address=10.3.3.157/16 +Address=10.3.3.158/16 +Address=10.3.3.159/16 +Address=10.3.3.160/16 +Address=10.3.3.161/16 +Address=10.3.3.162/16 +Address=10.3.3.163/16 +Address=10.3.3.164/16 +Address=10.3.3.165/16 +Address=10.3.3.166/16 +Address=10.3.3.167/16 +Address=10.3.3.168/16 +Address=10.3.3.169/16 +Address=10.3.3.170/16 +Address=10.3.3.171/16 +Address=10.3.3.172/16 +Address=10.3.3.173/16 +Address=10.3.3.174/16 +Address=10.3.3.175/16 +Address=10.3.3.176/16 +Address=10.3.3.177/16 +Address=10.3.3.178/16 +Address=10.3.3.179/16 +Address=10.3.3.180/16 +Address=10.3.3.181/16 +Address=10.3.3.182/16 +Address=10.3.3.183/16 +Address=10.3.3.184/16 +Address=10.3.3.185/16 +Address=10.3.3.186/16 +Address=10.3.3.187/16 +Address=10.3.3.188/16 +Address=10.3.3.189/16 +Address=10.3.3.190/16 +Address=10.3.3.191/16 +Address=10.3.3.192/16 +Address=10.3.3.193/16 +Address=10.3.3.194/16 +Address=10.3.3.195/16 +Address=10.3.3.196/16 +Address=10.3.3.197/16 +Address=10.3.3.198/16 +Address=10.3.3.199/16 +Address=10.3.3.200/16 +Address=10.3.3.201/16 +Address=10.3.3.202/16 +Address=10.3.3.203/16 +Address=10.3.3.204/16 +Address=10.3.3.205/16 +Address=10.3.3.206/16 +Address=10.3.3.207/16 +Address=10.3.3.208/16 +Address=10.3.3.209/16 +Address=10.3.3.210/16 +Address=10.3.3.211/16 +Address=10.3.3.212/16 +Address=10.3.3.213/16 +Address=10.3.3.214/16 +Address=10.3.3.215/16 +Address=10.3.3.216/16 +Address=10.3.3.217/16 +Address=10.3.3.218/16 +Address=10.3.3.219/16 +Address=10.3.3.220/16 +Address=10.3.3.221/16 +Address=10.3.3.222/16 +Address=10.3.3.223/16 +Address=10.3.3.224/16 +Address=10.3.3.225/16 +Address=10.3.3.226/16 +Address=10.3.3.227/16 +Address=10.3.3.228/16 +Address=10.3.3.229/16 +Address=10.3.3.230/16 +Address=10.3.3.231/16 +Address=10.3.3.232/16 +Address=10.3.3.233/16 +Address=10.3.3.234/16 +Address=10.3.3.235/16 +Address=10.3.3.236/16 +Address=10.3.3.237/16 +Address=10.3.3.238/16 +Address=10.3.3.239/16 +Address=10.3.3.240/16 +Address=10.3.3.241/16 +Address=10.3.3.242/16 +Address=10.3.3.243/16 +Address=10.3.3.244/16 +Address=10.3.3.245/16 +Address=10.3.3.246/16 +Address=10.3.3.247/16 +Address=10.3.3.248/16 +Address=10.3.3.249/16 +Address=10.3.3.250/16 +Address=10.3.3.251/16 +Address=10.3.3.252/16 +Address=10.3.3.253/16 +Address=10.3.3.254/16 diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index 0ca1fb3bf..d528fa8ad 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -1764,6 +1764,10 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): self.assertRegex(output, 'inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98') self.assertRegex(output, 'inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98') + # test for ENOBUFS issue #17012 + for i in range(1,254): + self.assertRegex(output, f'inet 10.3.3.{i}/16 brd 10.3.255.255') + # invalid sections self.assertNotRegex(output, '10.10.0.1/16') self.assertNotRegex(output, '10.10.0.2/16') @@ -1789,6 +1793,14 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): self.assertRegex(output, 'inet6 2001:db8:0:f103::20 peer 2001:db8:0:f103::10/128 scope global') self.assertRegex(output, 'inet6 fd[0-9a-f:]*1/64 scope global') + restart_networkd() + self.wait_online(['dummy98:routable']) + + # test for ENOBUFS issue #17012 + output = check_output('ip -4 address show dev dummy98') + for i in range(1,254): + self.assertRegex(output, f'inet 10.3.3.{i}/16 brd 10.3.255.255') + def test_address_preferred_lifetime_zero_ipv6(self): copy_unit_to_networkd_unit_path('25-address-preferred-lifetime-zero.network', '12-dummy.netdev') start_networkd(5)