diff options
author | Thomas Haller <thaller@redhat.com> | 2018-11-23 09:12:56 +0100 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2018-11-23 10:53:12 +0100 |
commit | 48d64de1776660eb06fde77078507d25b0d5b40a (patch) | |
tree | 28cf9603bcfd394ddd27c5a306bbcb502fda5edf | |
parent | 5437448a6404376f2e8fdadff329682bfe9c992e (diff) |
systemd: update code from upstream (2018-11-23)
This is a direct dump from systemd git.
======
SYSTEMD_DIR=../systemd
COMMIT=91540eaa5c636f4073955f025c4e72b1bbb4f2e9
(
cd "$SYSTEMD_DIR"
git checkout "$COMMIT"
git reset --hard
git clean -fdx
)
git ls-files :/src/systemd/src/ \
:/shared/nm-utils/unaligned.h | \
xargs -d '\n' rm -f
nm_copy_sd() {
mkdir -p "./src/systemd/$(dirname "$1")"
cp "$SYSTEMD_DIR/$1" "./src/systemd/$1"
}
nm_copy_sd_shared() {
mkdir -p "./shared/nm-utils/"
cp "$SYSTEMD_DIR/$1" "./shared/nm-utils/${1##*/}"
}
nm_copy_sd "src/basic/alloc-util.c"
nm_copy_sd "src/basic/alloc-util.h"
nm_copy_sd "src/basic/async.h"
nm_copy_sd "src/basic/env-util.c"
nm_copy_sd "src/basic/env-util.h"
nm_copy_sd "src/basic/escape.c"
nm_copy_sd "src/basic/escape.h"
nm_copy_sd "src/basic/ether-addr-util.c"
nm_copy_sd "src/basic/ether-addr-util.h"
nm_copy_sd "src/basic/extract-word.c"
nm_copy_sd "src/basic/extract-word.h"
nm_copy_sd "src/basic/fileio.c"
nm_copy_sd "src/basic/fileio.h"
nm_copy_sd "src/basic/fd-util.c"
nm_copy_sd "src/basic/fd-util.h"
nm_copy_sd "src/basic/fs-util.c"
nm_copy_sd "src/basic/fs-util.h"
nm_copy_sd "src/basic/hash-funcs.c"
nm_copy_sd "src/basic/hash-funcs.h"
nm_copy_sd "src/basic/hashmap.c"
nm_copy_sd "src/basic/hashmap.h"
nm_copy_sd "src/basic/hexdecoct.c"
nm_copy_sd "src/basic/hexdecoct.h"
nm_copy_sd "src/basic/hostname-util.c"
nm_copy_sd "src/basic/hostname-util.h"
nm_copy_sd "src/basic/in-addr-util.c"
nm_copy_sd "src/basic/in-addr-util.h"
nm_copy_sd "src/basic/io-util.c"
nm_copy_sd "src/basic/io-util.h"
nm_copy_sd "src/basic/list.h"
nm_copy_sd "src/basic/log.h"
nm_copy_sd "src/basic/macro.h"
nm_copy_sd "src/basic/mempool.h"
nm_copy_sd "src/basic/mempool.c"
nm_copy_sd "src/basic/parse-util.c"
nm_copy_sd "src/basic/parse-util.h"
nm_copy_sd "src/basic/path-util.c"
nm_copy_sd "src/basic/path-util.h"
nm_copy_sd "src/basic/prioq.h"
nm_copy_sd "src/basic/prioq.c"
nm_copy_sd "src/basic/process-util.h"
nm_copy_sd "src/basic/process-util.c"
nm_copy_sd "src/basic/random-util.c"
nm_copy_sd "src/basic/random-util.h"
nm_copy_sd "src/basic/refcnt.h"
nm_copy_sd "src/basic/set.h"
nm_copy_sd "src/basic/signal-util.h"
nm_copy_sd "src/basic/siphash24.h"
nm_copy_sd "src/basic/socket-util.c"
nm_copy_sd "src/basic/socket-util.h"
nm_copy_sd "src/basic/sparse-endian.h"
nm_copy_sd "src/basic/stat-util.c"
nm_copy_sd "src/basic/stat-util.h"
nm_copy_sd "src/basic/stdio-util.h"
nm_copy_sd "src/basic/string-table.c"
nm_copy_sd "src/basic/string-table.h"
nm_copy_sd "src/basic/string-util.c"
nm_copy_sd "src/basic/string-util.h"
nm_copy_sd "src/basic/strv.c"
nm_copy_sd "src/basic/strv.h"
nm_copy_sd "src/basic/time-util.c"
nm_copy_sd "src/basic/time-util.h"
nm_copy_sd "src/basic/umask-util.h"
nm_copy_sd_shared "src/basic/unaligned.h"
nm_copy_sd "src/basic/utf8.c"
nm_copy_sd "src/basic/utf8.h"
nm_copy_sd "src/basic/util.c"
nm_copy_sd "src/basic/util.h"
nm_copy_sd "src/libsystemd-network/arp-util.c"
nm_copy_sd "src/libsystemd-network/arp-util.h"
nm_copy_sd "src/libsystemd-network/dhcp6-internal.h"
nm_copy_sd "src/libsystemd-network/dhcp6-lease-internal.h"
nm_copy_sd "src/libsystemd-network/dhcp6-network.c"
nm_copy_sd "src/libsystemd-network/dhcp6-option.c"
nm_copy_sd "src/libsystemd-network/dhcp6-protocol.h"
nm_copy_sd "src/libsystemd-network/dhcp-identifier.c"
nm_copy_sd "src/libsystemd-network/dhcp-identifier.h"
nm_copy_sd "src/libsystemd-network/dhcp-internal.h"
nm_copy_sd "src/libsystemd-network/dhcp-lease-internal.h"
nm_copy_sd "src/libsystemd-network/dhcp-network.c"
nm_copy_sd "src/libsystemd-network/dhcp-option.c"
nm_copy_sd "src/libsystemd-network/dhcp-packet.c"
nm_copy_sd "src/libsystemd-network/dhcp-protocol.h"
nm_copy_sd "src/libsystemd-network/lldp-internal.h"
nm_copy_sd "src/libsystemd-network/lldp-neighbor.c"
nm_copy_sd "src/libsystemd-network/lldp-neighbor.h"
nm_copy_sd "src/libsystemd-network/lldp-network.c"
nm_copy_sd "src/libsystemd-network/lldp-network.h"
nm_copy_sd "src/libsystemd-network/network-internal.c"
nm_copy_sd "src/libsystemd-network/network-internal.h"
nm_copy_sd "src/libsystemd-network/sd-dhcp6-client.c"
nm_copy_sd "src/libsystemd-network/sd-dhcp6-lease.c"
nm_copy_sd "src/libsystemd-network/sd-dhcp-client.c"
nm_copy_sd "src/libsystemd-network/sd-dhcp-lease.c"
nm_copy_sd "src/libsystemd-network/sd-ipv4acd.c"
nm_copy_sd "src/libsystemd-network/sd-ipv4ll.c"
nm_copy_sd "src/libsystemd-network/sd-lldp.c"
nm_copy_sd "src/libsystemd/sd-event/event-source.h"
nm_copy_sd "src/libsystemd/sd-event/event-util.c"
nm_copy_sd "src/libsystemd/sd-event/event-util.h"
nm_copy_sd "src/libsystemd/sd-event/sd-event.c"
nm_copy_sd "src/libsystemd/sd-id128/id128-util.c"
nm_copy_sd "src/libsystemd/sd-id128/id128-util.h"
nm_copy_sd "src/libsystemd/sd-id128/sd-id128.c"
nm_copy_sd "src/shared/dns-domain.c"
nm_copy_sd "src/shared/dns-domain.h"
nm_copy_sd "src/systemd/_sd-common.h"
nm_copy_sd "src/systemd/sd-dhcp6-client.h"
nm_copy_sd "src/systemd/sd-dhcp6-lease.h"
nm_copy_sd "src/systemd/sd-dhcp-client.h"
nm_copy_sd "src/systemd/sd-dhcp-lease.h"
nm_copy_sd "src/systemd/sd-event.h"
nm_copy_sd "src/systemd/sd-ndisc.h"
nm_copy_sd "src/systemd/sd-id128.h"
nm_copy_sd "src/systemd/sd-ipv4acd.h"
nm_copy_sd "src/systemd/sd-ipv4ll.h"
nm_copy_sd "src/systemd/sd-lldp.h"
39 files changed, 924 insertions, 834 deletions
diff --git a/shared/nm-utils/unaligned.h b/shared/nm-utils/unaligned.h index e62188d1a..00c17f876 100644 --- a/shared/nm-utils/unaligned.h +++ b/shared/nm-utils/unaligned.h @@ -7,37 +7,37 @@ /* BE */ static inline uint16_t unaligned_read_be16(const void *_u) { - const struct __attribute__((packed, may_alias)) { uint16_t x; } *u = _u; + const struct __attribute__((__packed__, __may_alias__)) { uint16_t x; } *u = _u; return be16toh(u->x); } static inline uint32_t unaligned_read_be32(const void *_u) { - const struct __attribute__((packed, may_alias)) { uint32_t x; } *u = _u; + const struct __attribute__((__packed__, __may_alias__)) { uint32_t x; } *u = _u; return be32toh(u->x); } static inline uint64_t unaligned_read_be64(const void *_u) { - const struct __attribute__((packed, may_alias)) { uint64_t x; } *u = _u; + const struct __attribute__((__packed__, __may_alias__)) { uint64_t x; } *u = _u; return be64toh(u->x); } static inline void unaligned_write_be16(void *_u, uint16_t a) { - struct __attribute__((packed, may_alias)) { uint16_t x; } *u = _u; + struct __attribute__((__packed__, __may_alias__)) { uint16_t x; } *u = _u; u->x = be16toh(a); } static inline void unaligned_write_be32(void *_u, uint32_t a) { - struct __attribute__((packed, may_alias)) { uint32_t x; } *u = _u; + struct __attribute__((__packed__, __may_alias__)) { uint32_t x; } *u = _u; u->x = be32toh(a); } static inline void unaligned_write_be64(void *_u, uint64_t a) { - struct __attribute__((packed, may_alias)) { uint64_t x; } *u = _u; + struct __attribute__((__packed__, __may_alias__)) { uint64_t x; } *u = _u; u->x = be64toh(a); } @@ -45,37 +45,37 @@ static inline void unaligned_write_be64(void *_u, uint64_t a) { /* LE */ static inline uint16_t unaligned_read_le16(const void *_u) { - const struct __attribute__((packed, may_alias)) { uint16_t x; } *u = _u; + const struct __attribute__((__packed__, __may_alias__)) { uint16_t x; } *u = _u; return le16toh(u->x); } static inline uint32_t unaligned_read_le32(const void *_u) { - const struct __attribute__((packed, may_alias)) { uint32_t x; } *u = _u; + const struct __attribute__((__packed__, __may_alias__)) { uint32_t x; } *u = _u; return le32toh(u->x); } static inline uint64_t unaligned_read_le64(const void *_u) { - const struct __attribute__((packed, may_alias)) { uint64_t x; } *u = _u; + const struct __attribute__((__packed__, __may_alias__)) { uint64_t x; } *u = _u; return le64toh(u->x); } static inline void unaligned_write_le16(void *_u, uint16_t a) { - struct __attribute__((packed, may_alias)) { uint16_t x; } *u = _u; + struct __attribute__((__packed__, __may_alias__)) { uint16_t x; } *u = _u; u->x = le16toh(a); } static inline void unaligned_write_le32(void *_u, uint32_t a) { - struct __attribute__((packed, may_alias)) { uint32_t x; } *u = _u; + struct __attribute__((__packed__, __may_alias__)) { uint32_t x; } *u = _u; u->x = le32toh(a); } static inline void unaligned_write_le64(void *_u, uint64_t a) { - struct __attribute__((packed, may_alias)) { uint64_t x; } *u = _u; + struct __attribute__((__packed__, __may_alias__)) { uint64_t x; } *u = _u; u->x = le64toh(a); } diff --git a/src/systemd/src/basic/escape.c b/src/systemd/src/basic/escape.c index 5004763d9..5f715156f 100644 --- a/src/systemd/src/basic/escape.c +++ b/src/systemd/src/basic/escape.c @@ -106,7 +106,6 @@ int cunescape_one(const char *p, size_t length, char32_t *ret, bool *eight_bit) int r = 1; assert(p); - assert(*p); assert(ret); /* Unescapes C style. Returns the unescaped character in ret. diff --git a/src/systemd/src/basic/fileio.c b/src/systemd/src/basic/fileio.c index f14afa5dc..5e771a0aa 100644 --- a/src/systemd/src/basic/fileio.c +++ b/src/systemd/src/basic/fileio.c @@ -15,7 +15,6 @@ #include "alloc-util.h" #include "ctype.h" -#include "def.h" #include "env-util.h" #include "escape.h" #include "fd-util.h" @@ -160,7 +159,7 @@ int write_string_file_ts( /* We manually build our own version of fopen(..., "we") that * works without O_CREAT */ - fd = open(fn, O_WRONLY|O_CLOEXEC|O_NOCTTY); + fd = open(fn, O_WRONLY|O_CLOEXEC|O_NOCTTY | ((flags & WRITE_STRING_FILE_NOFOLLOW) ? O_NOFOLLOW : 0)); if (fd < 0) { r = -errno; goto fail; @@ -368,7 +367,6 @@ int read_full_file(const char *fn, char **contents, size_t *size) { static int parse_env_file_internal( FILE *f, const char *fname, - const char *newline, int (*push) (const char *filename, unsigned line, const char *key, char *value, void *userdata, int *n_pushed), void *userdata, @@ -394,8 +392,6 @@ static int parse_env_file_internal( COMMENT_ESCAPE } state = PRE_KEY; - assert(newline); - if (f) r = read_full_stream(f, &contents, NULL); else @@ -423,7 +419,7 @@ static int parse_env_file_internal( break; case KEY: - if (strchr(newline, c)) { + if (strchr(NEWLINE, c)) { state = PRE_KEY; line++; n_key = 0; @@ -445,7 +441,7 @@ static int parse_env_file_internal( break; case PRE_VALUE: - if (strchr(newline, c)) { + if (strchr(NEWLINE, c)) { state = PRE_KEY; line++; key[n_key] = 0; @@ -483,7 +479,7 @@ static int parse_env_file_internal( break; case VALUE: - if (strchr(newline, c)) { + if (strchr(NEWLINE, c)) { state = PRE_KEY; line++; @@ -528,7 +524,7 @@ static int parse_env_file_internal( case VALUE_ESCAPE: state = VALUE; - if (!strchr(newline, c)) { + if (!strchr(NEWLINE, c)) { /* Escaped newlines we eat up entirely */ if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) return -ENOMEM; @@ -554,7 +550,7 @@ static int parse_env_file_internal( case SINGLE_QUOTE_VALUE_ESCAPE: state = SINGLE_QUOTE_VALUE; - if (!strchr(newline, c)) { + if (!strchr(NEWLINE, c)) { if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) return -ENOMEM; @@ -579,7 +575,7 @@ static int parse_env_file_internal( case DOUBLE_QUOTE_VALUE_ESCAPE: state = DOUBLE_QUOTE_VALUE; - if (!strchr(newline, c)) { + if (!strchr(NEWLINE, c)) { if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) return -ENOMEM; @@ -590,7 +586,7 @@ static int parse_env_file_internal( case COMMENT: if (c == '\\') state = COMMENT_ESCAPE; - else if (strchr(newline, c)) { + else if (strchr(NEWLINE, c)) { state = PRE_KEY; line++; } @@ -642,16 +638,18 @@ static int check_utf8ness_and_warn( _cleanup_free_ char *p = NULL; p = utf8_escape_invalid(key); - log_error("%s:%u: invalid UTF-8 in key '%s', ignoring.", strna(filename), line, p); - return -EINVAL; + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "%s:%u: invalid UTF-8 in key '%s', ignoring.", + strna(filename), line, p); } if (value && !utf8_is_valid(value)) { _cleanup_free_ char *p = NULL; p = utf8_escape_invalid(value); - log_error("%s:%u: invalid UTF-8 value for key %s: '%s', ignoring.", strna(filename), line, key, p); - return -EINVAL; + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "%s:%u: invalid UTF-8 value for key %s: '%s', ignoring.", + strna(filename), line, key, p); } return 0; @@ -699,17 +697,13 @@ static int parse_env_file_push( int parse_env_filev( FILE *f, const char *fname, - const char *newline, va_list ap) { int r, n_pushed = 0; va_list aq; - if (!newline) - newline = NEWLINE; - va_copy(aq, ap); - r = parse_env_file_internal(f, fname, newline, parse_env_file_push, &aq, &n_pushed); + r = parse_env_file_internal(f, fname, parse_env_file_push, &aq, &n_pushed); va_end(aq); if (r < 0) return r; @@ -717,17 +711,16 @@ int parse_env_filev( return n_pushed; } -int parse_env_file( +int parse_env_file_sentinel( FILE *f, const char *fname, - const char *newline, ...) { va_list ap; int r; - va_start(ap, newline); - r = parse_env_filev(f, fname, newline, ap); + va_start(ap, fname); + r = parse_env_filev(f, fname, ap); va_end(ap); return r; @@ -763,14 +756,11 @@ static int load_env_file_push( return 0; } -int load_env_file(FILE *f, const char *fname, const char *newline, char ***rl) { +int load_env_file(FILE *f, const char *fname, char ***rl) { char **m = NULL; int r; - if (!newline) - newline = NEWLINE; - - r = parse_env_file_internal(f, fname, newline, load_env_file_push, &m, NULL); + r = parse_env_file_internal(f, fname, load_env_file_push, &m, NULL); if (r < 0) { strv_free(m); return r; @@ -812,14 +802,11 @@ static int load_env_file_push_pairs( return 0; } -int load_env_file_pairs(FILE *f, const char *fname, const char *newline, char ***rl) { +int load_env_file_pairs(FILE *f, const char *fname, char ***rl) { char **m = NULL; int r; - if (!newline) - newline = NEWLINE; - - r = parse_env_file_internal(f, fname, newline, load_env_file_push_pairs, &m, NULL); + r = parse_env_file_internal(f, fname, load_env_file_push_pairs, &m, NULL); if (r < 0) { strv_free(m); return r; @@ -872,7 +859,7 @@ int merge_env_file( * plus "extended" substitutions, unlike other exported parsing functions. */ - return parse_env_file_internal(f, fname, NEWLINE, merge_env_file_push, env, NULL); + return parse_env_file_internal(f, fname, merge_env_file_push, env, NULL); } static void write_env_var(FILE *f, const char *v) { diff --git a/src/systemd/src/basic/fileio.h b/src/systemd/src/basic/fileio.h index 102d33d75..dae115e3b 100644 --- a/src/systemd/src/basic/fileio.h +++ b/src/systemd/src/basic/fileio.h @@ -10,6 +10,8 @@ #include "macro.h" #include "time-util.h" +#define LONG_LINE_MAX (1U*1024U*1024U) + typedef enum { WRITE_STRING_FILE_CREATE = 1 << 0, WRITE_STRING_FILE_ATOMIC = 1 << 1, @@ -17,6 +19,7 @@ typedef enum { WRITE_STRING_FILE_VERIFY_ON_FAILURE = 1 << 3, WRITE_STRING_FILE_SYNC = 1 << 4, WRITE_STRING_FILE_DISABLE_BUFFER = 1 << 5, + WRITE_STRING_FILE_NOFOLLOW = 1 << 6, /* And before you wonder, why write_string_file_atomic_label_ts() is a separate function instead of just one more flag here: it's about linking: we don't want to pull -lselinux into all users of write_string_file() @@ -41,10 +44,11 @@ int read_full_stream(FILE *f, char **contents, size_t *size); int verify_file(const char *fn, const char *blob, bool accept_extra_nl); -int parse_env_filev(FILE *f, const char *fname, const char *separator, va_list ap); -int parse_env_file(FILE *f, const char *fname, const char *separator, ...) _sentinel_; -int load_env_file(FILE *f, const char *fname, const char *separator, char ***l); -int load_env_file_pairs(FILE *f, const char *fname, const char *separator, char ***l); +int parse_env_filev(FILE *f, const char *fname, va_list ap); +int parse_env_file_sentinel(FILE *f, const char *fname, ...) _sentinel_; +#define parse_env_file(f, fname, ...) parse_env_file_sentinel(f, fname, __VA_ARGS__, NULL) +int load_env_file(FILE *f, const char *fname, char ***l); +int load_env_file_pairs(FILE *f, const char *fname, char ***l); int merge_env_file(char ***env, FILE *f, const char *fname); diff --git a/src/systemd/src/basic/hostname-util.c b/src/systemd/src/basic/hostname-util.c index 09fabe077..3a3479910 100644 --- a/src/systemd/src/basic/hostname-util.c +++ b/src/systemd/src/basic/hostname-util.c @@ -8,7 +8,6 @@ #include <unistd.h> #include "alloc-util.h" -#include "def.h" #include "fd-util.h" #include "fileio.h" #include "hostname-util.h" diff --git a/src/systemd/src/basic/in-addr-util.c b/src/systemd/src/basic/in-addr-util.c index d83658eaa..6a00de2ef 100644 --- a/src/systemd/src/basic/in-addr-util.c +++ b/src/systemd/src/basic/in-addr-util.c @@ -314,6 +314,7 @@ int in_addr_from_string_auto(const char *s, int *ret_family, union in_addr_union } int in_addr_ifindex_from_string_auto(const char *s, int *family, union in_addr_union *ret, int *ifindex) { + _cleanup_free_ char *buf = NULL; const char *suffix; int r, ifi = 0; @@ -341,7 +342,11 @@ int in_addr_ifindex_from_string_auto(const char *s, int *family, union in_addr_u } } - s = strndupa(s, suffix - s); + buf = strndup(s, suffix - s); + if (!buf) + return -ENOMEM; + + s = buf; } r = in_addr_from_string_auto(s, family, ret); @@ -490,12 +495,14 @@ int in_addr_parse_prefixlen(int family, const char *p, unsigned char *ret) { return 0; } -int in_addr_prefix_from_string( +int in_addr_prefix_from_string_internal( const char *p, + bool use_default_prefixlen, int family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen) { + _cleanup_free_ char *str = NULL; union in_addr_union buffer; const char *e, *l; unsigned char k; @@ -507,9 +514,13 @@ int in_addr_prefix_from_string( return -EAFNOSUPPORT; e = strchr(p, '/'); - if (e) - l = strndupa(p, e - p); - else + if (e) { + str = strndup(p, e - p); + if (!str) + return -ENOMEM; + + l = str; + } else l = p; r = in_addr_from_string(family, l, &buffer); @@ -520,6 +531,13 @@ int in_addr_prefix_from_string( r = in_addr_parse_prefixlen(family, e+1, &k); if (r < 0) return r; + } else if (use_default_prefixlen) { + if (family == AF_INET) { + r = in4_addr_default_prefixlen(&buffer.in, &k); + if (r < 0) + return r; + } else + k = 0; } else k = FAMILY_ADDRESS_SIZE(family) * 8; @@ -531,12 +549,14 @@ int in_addr_prefix_from_string( return 0; } -int in_addr_prefix_from_string_auto( +int in_addr_prefix_from_string_auto_internal( const char *p, + bool use_default_prefixlen, int *ret_family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen) { + _cleanup_free_ char *str = NULL; union in_addr_union buffer; const char *e, *l; unsigned char k; @@ -545,9 +565,13 @@ int in_addr_prefix_from_string_auto( assert(p); e = strchr(p, '/'); - if (e) - l = strndupa(p, e - p); - else + if (e) { + str = strndup(p, e - p); + if (!str) + return -ENOMEM; + + l = str; + } else l = p; r = in_addr_from_string_auto(l, &family, &buffer); @@ -558,6 +582,13 @@ int in_addr_prefix_from_string_auto( r = in_addr_parse_prefixlen(family, e+1, &k); if (r < 0) return r; + } else if (use_default_prefixlen) { + if (family == AF_INET) { + r = in4_addr_default_prefixlen(&buffer.in, &k); + if (r < 0) + return r; + } else + k = 0; } else k = FAMILY_ADDRESS_SIZE(family) * 8; diff --git a/src/systemd/src/basic/in-addr-util.h b/src/systemd/src/basic/in-addr-util.h index e4be30dc0..2f64c31f9 100644 --- a/src/systemd/src/basic/in-addr-util.h +++ b/src/systemd/src/basic/in-addr-util.h @@ -45,15 +45,29 @@ int in4_addr_default_subnet_mask(const struct in_addr *addr, struct in_addr *mas int in_addr_mask(int family, union in_addr_union *addr, unsigned char prefixlen); int in_addr_prefix_covers(int family, const union in_addr_union *prefix, unsigned char prefixlen, const union in_addr_union *address); int in_addr_parse_prefixlen(int family, const char *p, unsigned char *ret); -int in_addr_prefix_from_string(const char *p, int family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen); -int in_addr_prefix_from_string_auto(const char *p, int *ret_family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen); +int in_addr_prefix_from_string_internal(const char *p, bool use_default_prefixlen, int family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen); +int in_addr_prefix_from_string_auto_internal(const char *p, bool use_default_prefixlen, int *ret_family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen); +static inline int in_addr_prefix_from_string(const char *p, int family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen) { + return in_addr_prefix_from_string_internal(p, false, family, ret_prefix, ret_prefixlen); +} +static inline int in_addr_prefix_from_string_auto(const char *p, int *ret_family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen) { + return in_addr_prefix_from_string_auto_internal(p, false, ret_family, ret_prefix, ret_prefixlen); +} +static inline int in_addr_default_prefix_from_string(const char *p, int family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen) { + return in_addr_prefix_from_string_internal(p, true, family, ret_prefix, ret_prefixlen); +} +static inline int in_addr_default_prefix_from_string_auto(const char *p, int *ret_family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen) { + return in_addr_prefix_from_string_auto_internal(p, true, ret_family, ret_prefix, ret_prefixlen); +} static inline size_t FAMILY_ADDRESS_SIZE(int family) { assert(IN_SET(family, AF_INET, AF_INET6)); return family == AF_INET6 ? 16 : 4; } -#define IN_ADDR_NULL ((union in_addr_union) {}) +/* Workaround for clang, explicitly specify the maximum-size element here. + * See also oss-fuzz#11344. */ +#define IN_ADDR_NULL ((union in_addr_union) { .in6 = {} }) void in_addr_data_hash_func(const void *p, struct siphash *state); int in_addr_data_compare_func(const void *a, const void *b); diff --git a/src/systemd/src/basic/log.h b/src/systemd/src/basic/log.h index e1f5fd30c..17438d7ff 100644 --- a/src/systemd/src/basic/log.h +++ b/src/systemd/src/basic/log.h @@ -36,10 +36,12 @@ typedef enum LogTarget{ _LOG_TARGET_INVALID = -1 } LogTarget; -#define LOG_REALM_PLUS_LEVEL(realm, level) \ - ((realm) << 10 | (level)) -#define LOG_REALM_REMOVE_LEVEL(realm_level) \ - ((realm_level >> 10)) +/* Note to readers: << and >> have lower precedence than & and | */ +#define LOG_REALM_PLUS_LEVEL(realm, level) ((realm) << 10 | (level)) +#define LOG_REALM_REMOVE_LEVEL(realm_level) ((realm_level) >> 10) +#define SYNTHETIC_ERRNO(num) (1 << 30 | (num)) +#define IS_SYNTHETIC_ERRNO(val) ((val) >> 30 & 1) +#define ERRNO_VALUE(val) (abs(val) & 255) void log_set_target(LogTarget target); void log_set_max_level_realm(LogRealm realm, int level); @@ -201,10 +203,10 @@ void log_assert_failed_return_realm( #define log_full_errno_realm(realm, level, error, ...) \ ({ \ int _level = (level), _e = (error), _realm = (realm); \ - (log_get_max_level_realm(_realm) >= LOG_PRI(_level)) \ + (log_get_max_level_realm(_realm) >= LOG_PRI(_level)) \ ? log_internal_realm(LOG_REALM_PLUS_LEVEL(_realm, _level), _e, \ __FILE__, __LINE__, __func__, __VA_ARGS__) \ - : -abs(_e); \ + : -ERRNO_VALUE(_e); \ }) #define log_full_errno(level, error, ...) \ @@ -318,3 +320,5 @@ int log_syntax_invalid_utf8_internal( }) #define DEBUG_LOGGING _unlikely_(log_get_max_level() >= LOG_DEBUG) + +void log_setup_service(void); diff --git a/src/systemd/src/basic/macro.h b/src/systemd/src/basic/macro.h index ae88fa5b9..0a258cc61 100644 --- a/src/systemd/src/basic/macro.h +++ b/src/systemd/src/basic/macro.h @@ -8,30 +8,30 @@ #include <sys/sysmacros.h> #include <sys/types.h> -#define _printf_(a, b) __attribute__ ((format (printf, a, b))) +#define _printf_(a, b) __attribute__ ((__format__(printf, a, b))) #ifdef __clang__ # define _alloc_(...) #else -# define _alloc_(...) __attribute__ ((alloc_size(__VA_ARGS__))) +# define _alloc_(...) __attribute__ ((__alloc_size__(__VA_ARGS__))) #endif -#define _sentinel_ __attribute__ ((sentinel)) -#define _unused_ __attribute__ ((unused)) -#define _destructor_ __attribute__ ((destructor)) -#define _pure_ __attribute__ ((pure)) -#define _const_ __attribute__ ((const)) -#define _deprecated_ __attribute__ ((deprecated)) -#define _packed_ __attribute__ ((packed)) -#define _malloc_ __attribute__ ((malloc)) -#define _weak_ __attribute__ ((weak)) +#define _sentinel_ __attribute__ ((__sentinel__)) +#define _unused_ __attribute__ ((__unused__)) +#define _destructor_ __attribute__ ((__destructor__)) +#define _pure_ __attribute__ ((__pure__)) +#define _const_ __attribute__ ((__const__)) +#define _deprecated_ __attribute__ ((__deprecated__)) +#define _packed_ __attribute__ ((__packed__)) +#define _malloc_ __attribute__ ((__malloc__)) +#define _weak_ __attribute__ ((__weak__)) #define _likely_(x) (__builtin_expect(!!(x), 1)) #define _unlikely_(x) (__builtin_expect(!!(x), 0)) -#define _public_ __attribute__ ((visibility("default"))) -#define _hidden_ __attribute__ ((visibility("hidden"))) -#define _weakref_(x) __attribute__((weakref(#x))) -#define _alignas_(x) __attribute__((aligned(__alignof(x)))) -#define _cleanup_(x) __attribute__((cleanup(x))) +#define _public_ __attribute__ ((__visibility__("default"))) +#define _hidden_ __attribute__ ((__visibility__("hidden"))) +#define _weakref_(x) __attribute__((__weakref__(#x))) +#define _alignas_(x) __attribute__((__aligned__(__alignof(x)))) +#define _cleanup_(x) __attribute__((__cleanup__(x))) #if __GNUC__ >= 7 -#define _fallthrough_ __attribute__((fallthrough)) +#define _fallthrough_ __attribute__((__fallthrough__)) #else #define _fallthrough_ #endif @@ -41,7 +41,7 @@ #if __STDC_VERSION__ >= 201112L #define _noreturn_ _Noreturn #else -#define _noreturn_ __attribute__((noreturn)) +#define _noreturn_ __attribute__((__noreturn__)) #endif #endif @@ -334,6 +334,12 @@ static inline int __coverity_check__(int condition) { } \ } while (false) +#define return_with_errno(r, err) \ + do { \ + errno = abs(err); \ + return r; \ + } while (false) + #define PTR_TO_INT(p) ((int) ((intptr_t) (p))) #define INT_TO_PTR(u) ((void *) ((intptr_t) (u))) #define PTR_TO_UINT(p) ((unsigned) ((uintptr_t) (p))) @@ -383,7 +389,7 @@ static inline int __coverity_check__(int condition) { #define SET_FLAG(v, flag, b) \ (v) = (b) ? ((v) | (flag)) : ((v) & ~(flag)) #define FLAGS_SET(v, flags) \ - (((v) & (flags)) == (flags)) + ((~(v) & (flags)) == 0) #define CASE_F(X) case X: #define CASE_F_1(CASE, X) CASE_F(X) diff --git a/src/systemd/src/basic/process-util.c b/src/systemd/src/basic/process-util.c index b2aab853e..d1a34338f 100644 --- a/src/systemd/src/basic/process-util.c +++ b/src/systemd/src/basic/process-util.c @@ -25,7 +25,6 @@ #include "alloc-util.h" #include "architecture.h" -#include "def.h" #include "escape.h" #include "fd-util.h" #include "fileio.h" @@ -832,7 +831,7 @@ int wait_for_terminate_with_timeout(pid_t pid, usec_t timeout) { void sigkill_wait(pid_t pid) { assert(pid > 1); - if (kill(pid, SIGKILL) > 0) + if (kill(pid, SIGKILL) >= 0) (void) wait_for_terminate(pid, NULL); } @@ -850,7 +849,7 @@ void sigkill_waitp(pid_t *pid) { void sigterm_wait(pid_t pid) { assert(pid > 1); - if (kill_and_sigcont(pid, SIGTERM) > 0) + if (kill_and_sigcont(pid, SIGTERM) >= 0) (void) wait_for_terminate(pid, NULL); } @@ -1228,8 +1227,7 @@ int must_be_root(void) { if (geteuid() == 0) return 0; - log_error("Need to be root."); - return -EPERM; + return log_error_errno(SYNTHETIC_ERRNO(EPERM), "Need to be root."); } int safe_fork_full( @@ -1409,6 +1407,60 @@ int safe_fork_full( return 0; } +int namespace_fork( + const char *outer_name, + const char *inner_name, + const int except_fds[], + size_t n_except_fds, + ForkFlags flags, + int pidns_fd, + int mntns_fd, + int netns_fd, + int userns_fd, + int root_fd, + pid_t *ret_pid) { + + int r; + + /* This is much like safe_fork(), but forks twice, and joins the specified namespaces in the middle + * process. This ensures that we are fully a member of the destination namespace, with pidns an all, so that + * /proc/self/fd works correctly. */ + + r = safe_fork_full(outer_name, except_fds, n_except_fds, (flags|FORK_DEATHSIG) & ~(FORK_REOPEN_LOG|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE), ret_pid); + if (r < 0) + return r; + if (r == 0) { + pid_t pid; + + /* Child */ + + r = namespace_enter(pidns_fd, mntns_fd, netns_fd, userns_fd, root_fd); + if (r < 0) { + log_full_errno(FLAGS_SET(flags, FORK_LOG) ? LOG_ERR : LOG_DEBUG, r, "Failed to join namespace: %m"); + _exit(EXIT_FAILURE); + } + + /* We mask a few flags here that either make no sense for the grandchild, or that we don't have to do again */ + r = safe_fork_full(inner_name, except_fds, n_except_fds, flags & ~(FORK_WAIT|FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_NULL_STDIO), &pid); + if (r < 0) + _exit(EXIT_FAILURE); + if (r == 0) { + /* Child */ + if (ret_pid) + *ret_pid = pid; + return 0; + } + + r = wait_for_terminate_and_check(inner_name, pid, FLAGS_SET(flags, FORK_LOG) ? WAIT_LOG : 0); + if (r < 0) + _exit(EXIT_FAILURE); + + _exit(r); + } + + return 1; +} + int fork_agent(const char *name, const int except[], size_t n_except, pid_t *ret_pid, const char *path, ...) { bool stdout_is_tty, stderr_is_tty; size_t n, i; diff --git a/src/systemd/src/basic/process-util.h b/src/systemd/src/basic/process-util.h index ca4e4401a..af47513fa 100644 --- a/src/systemd/src/basic/process-util.h +++ b/src/systemd/src/basic/process-util.h @@ -159,6 +159,8 @@ static inline int safe_fork(const char *name, ForkFlags flags, pid_t *ret_pid) { return safe_fork_full(name, NULL, 0, flags, ret_pid); } +int namespace_fork(const char *outer_name, const char *inner_name, const int except_fds[], size_t n_except_fds, ForkFlags flags, int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd, pid_t *ret_pid); + int fork_agent(const char *name, const int except[], size_t n_except, pid_t *pid, const char *path, ...) _sentinel_; int set_oom_score_adjust(int value); diff --git a/src/systemd/src/basic/random-util.c b/src/systemd/src/basic/random-util.c index aa04cc231..4a36ad511 100644 --- a/src/systemd/src/basic/random-util.c +++ b/src/systemd/src/basic/random-util.c @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -#ifdef __x86_64__ +#if defined(__i386__) || defined(__x86_64__) #include <cpuid.h> #endif @@ -30,10 +30,13 @@ #include "random-util.h" #include "time-util.h" +#if HAS_FEATURE_MEMORY_SANITIZER +#include <sanitizer/msan_interface.h> +#endif -int rdrand64(uint64_t *ret) { +int rdrand(unsigned long *ret) { -#ifdef __x86_64__ +#if defined(__i386__) || defined(__x86_64__) static int have_rdrand = -1; unsigned char err; @@ -56,6 +59,11 @@ int rdrand64(uint64_t *ret) { "setc %1" : "=r" (*ret), "=qm" (err)); + +#if HAS_FEATURE_MEMORY_SANITIZER + __msan_unpoison(&err, sizeof(err)); +#endif + if (!err) return -EAGAIN; @@ -65,85 +73,132 @@ int rdrand64(uint64_t *ret) { #endif } -int acquire_random_bytes(void *p, size_t n, bool high_quality_required) { +int genuine_random_bytes(void *p, size_t n, RandomFlags flags) { static int have_syscall = -1; - _cleanup_close_ int fd = -1; - size_t already_done = 0; + bool got_some = false; int r; - /* Gathers some randomness from the kernel. This call will never block. If - * high_quality_required, it will always return some data from the kernel, - * regardless of whether the random pool is fully initialized or not. - * Otherwise, it will return success if at least some random bytes were - * successfully acquired, and an error if the kernel has no entropy whatsover - * for us. */ + /* Gathers some randomness from the kernel (or the CPU if the RANDOM_ALLOW_RDRAND flag is set). This call won't + * block, unless the RANDOM_BLOCK flag is set. If RANDOM_DONT_DRAIN is set, an error is returned if the random + * pool is not initialized. Otherwise it will always return some data from the kernel, regardless of whether + * the random pool is fully initialized or not. */ + + if (n == 0) + return 0; + + if (FLAGS_SET(flags, RANDOM_ALLOW_RDRAND)) + /* Try x86-64' RDRAND intrinsic if we have it. We only use it if high quality randomness is not + * required, as we don't trust it (who does?). Note that we only do a single iteration of RDRAND here, + * even though the Intel docs suggest calling this in a tight loop of 10 invocations or so. That's + * because we don't really care about the quality here. We generally prefer using RDRAND if the caller + * allows us too, since this way we won't drain the kernel randomness pool if we don't need it, as the + * pool's entropy is scarce. */ + for (;;) { + unsigned long u; + size_t m; + + if (rdrand(&u) < 0) { + if (got_some && FLAGS_SET(flags, RANDOM_EXTEND_WITH_PSEUDO)) { + /* Fill in the remaining bytes using pseudo-random values */ + pseudo_random_bytes(p, n); + return 0; + } + + /* OK, this didn't work, let's go to getrandom() + /dev/urandom instead */ + break; + } + + m = MIN(sizeof(u), n); + memcpy(p, &u, m); + + p = (uint8_t*) p + m; + n -= m; + + if (n == 0) + return 0; /* Yay, success! */ + + got_some = true; + } /* Use the getrandom() syscall unless we know we don't have it. */ if (have_syscall != 0 && !HAS_FEATURE_MEMORY_SANITIZER) { - r = getrandom(p, n, GRND_NONBLOCK); - if (r > 0) { - have_syscall = true; - if ((size_t) r == n) - return 0; - if (!high_quality_required) { - /* Fill in the remaining bytes using pseudorandom values */ - pseudorandom_bytes((uint8_t*) p + r, n - r); - return 0; - } - already_done = r; - } else if (errno == ENOSYS) - /* We lack the syscall, continue with reading from /dev/urandom. */ - have_syscall = false; - else if (errno == EAGAIN) { - /* The kernel has no entropy whatsoever. Let's remember to - * use the syscall the next time again though. - * - * If high_quality_required is false, return an error so that - * random_bytes() can produce some pseudorandom - * bytes. Otherwise, fall back to /dev/urandom, which we know - * is empty, but the kernel will produce some bytes for us on - * a best-effort basis. */ - have_syscall = true; - - if (!high_quality_required) { - uint64_t u; - size_t k; - - /* Try x86-64' RDRAND intrinsic if we have it. We only use it if high quality - * randomness is not required, as we don't trust it (who does?). Note that we only do a - * single iteration of RDRAND here, even though the Intel docs suggest calling this in - * a tight loop of 10 invocatins or so. That's because we don't really care about the - * quality here. */ - - if (rdrand64(&u) < 0) + for (;;) { + r = getrandom(p, n, FLAGS_SET(flags, RANDOM_BLOCK) ? 0 : GRND_NONBLOCK); + if (r > 0) { + have_syscall = true; + + if ((size_t) r == n) + return 0; /* Yay, success! */ + + assert((size_t) r < n); + p = (uint8_t*) p + r; + n -= r; + + if (FLAGS_SET(flags, RANDOM_EXTEND_WITH_PSEUDO)) { + /* Fill in the remaining bytes using pseudo-random values */ + pseudo_random_bytes(p, n); + return 0; + } + + got_some = true; + + /* Hmm, we didn't get enough good data but the caller insists on good data? Then try again */ + if (FLAGS_SET(flags, RANDOM_BLOCK)) + continue; + + /* Fill in the rest with /dev/urandom */ + break; + + } else if (r == 0) { + have_syscall = true; + return -EIO; + + } else if (errno == ENOSYS) { + /* We lack the syscall, continue with reading from /dev/urandom. */ + have_syscall = false; + break; + + } else if (errno == EAGAIN) { + /* The kernel has no entropy whatsoever. Let's remember to use the syscall the next + * time again though. + * + * If RANDOM_DONT_DRAIN is set, return an error so that random_bytes() can produce some + * pseudo-random bytes instead. Otherwise, fall back to /dev/urandom, which we know is empty, + * but the kernel will produce some bytes for us on a best-effort basis. */ + have_syscall = true; + + if (got_some && FLAGS_SET(flags, RANDOM_EXTEND_WITH_PSEUDO)) { + /* Fill in the remaining bytes using pseudorandom values */ + pseudo_random_bytes(p, n); + return 0; + } + + if (FLAGS_SET(flags, RANDOM_DONT_DRAIN)) return -ENODATA; - k = MIN(n, sizeof(u)); - memcpy(p, &u, k); - - /* We only get 64bit out of RDRAND, the rest let's fill up with pseudo-random crap. */ - pseudorandom_bytes((uint8_t*) p + k, n - k); - return 0; - } - } else - return -errno; + /* Use /dev/urandom instead */ + break; + } else + return -errno; + } } fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY); if (fd < 0) return errno == ENOENT ? -ENOSYS : -errno; - return loop_read_exact(fd, (uint8_t*) p + already_done, n - already_done, true); + return loop_read_exact(fd, p, n, true); } void initialize_srand(void) { static bool srand_called = false; unsigned x; #if HAVE_SYS_AUXV_H - void *auxv; + const void *auxv; #endif + unsigned long k; if (srand_called) return; @@ -153,7 +208,7 @@ void initialize_srand(void) { * try to make use of that to seed the pseudo-random generator. It's * better than nothing... */ - auxv = (void*) getauxval(AT_RANDOM); + auxv = (const void*) getauxval(AT_RANDOM); if (auxv) { assert_cc(sizeof(x) <= 16); memcpy(&x, auxv, sizeof(x)); @@ -164,6 +219,9 @@ void initialize_srand(void) { x ^= (unsigned) now(CLOCK_REALTIME); x ^= (unsigned) gettid(); + if (rdrand(&k) >= 0) + x ^= (unsigned) k; + srand(x); srand_called = true; } @@ -176,7 +234,7 @@ void initialize_srand(void) { # define RAND_STEP 1 #endif -void pseudorandom_bytes(void *p, size_t n) { +void pseudo_random_bytes(void *p, size_t n) { uint8_t *q; initialize_srand(); @@ -199,13 +257,10 @@ void pseudorandom_bytes(void *p, size_t n) { } void random_bytes(void *p, size_t n) { - int r; - r = acquire_random_bytes(p, n, false); - if (r >= 0) + if (genuine_random_bytes(p, n, RANDOM_EXTEND_WITH_PSEUDO|RANDOM_DONT_DRAIN|RANDOM_ALLOW_RDRAND) >= 0) return; - /* If some idiot made /dev/urandom unavailable to us, or the - * kernel has no entropy, use a PRNG instead. */ - return pseudorandom_bytes(p, n); + /* If for some reason some user made /dev/urandom unavailable to us, or the kernel has no entropy, use a PRNG instead. */ + pseudo_random_bytes(p, n); } diff --git a/src/systemd/src/basic/random-util.h b/src/systemd/src/basic/random-util.h index affcc9ac1..3e8c288d3 100644 --- a/src/systemd/src/basic/random-util.h +++ b/src/systemd/src/basic/random-util.h @@ -5,9 +5,17 @@ #include <stddef.h> #include <stdint.h> -int acquire_random_bytes(void *p, size_t n, bool high_quality_required); -void pseudorandom_bytes(void *p, size_t n); -void random_bytes(void *p, size_t n); +typedef enum RandomFlags { + RANDOM_EXTEND_WITH_PSEUDO = 1 << 0, /* If we can't get enough genuine randomness, but some, fill up the rest with pseudo-randomness */ + RANDOM_BLOCK = 1 << 1, /* Rather block than return crap randomness (only if the kernel supports that) */ + RANDOM_DONT_DRAIN = 1 << 2, /* If we can't get any randomness at all, return early with -EAGAIN */ + RANDOM_ALLOW_RDRAND = 1 << 3, /* Allow usage of the CPU RNG */ +} RandomFlags; + +int genuine_random_bytes(void *p, size_t n, RandomFlags flags); /* returns "genuine" randomness, optionally filled upwith pseudo random, if not enough is available */ +void pseudo_random_bytes(void *p, size_t n); /* returns only pseudo-randommess (but possibly seeded from something better) */ +void random_bytes(void *p, size_t n); /* returns genuine randomness if cheaply available, and pseudo randomness if not. */ + void initialize_srand(void); static inline uint64_t random_u64(void) { @@ -22,4 +30,4 @@ static inline uint32_t random_u32(void) { return u; } -int rdrand64(uint64_t *ret); +int rdrand(unsigned long *ret); diff --git a/src/systemd/src/basic/sparse-endian.h b/src/systemd/src/basic/sparse-endian.h index 8540ccd0b..9583dda9e 100644 --- a/src/systemd/src/basic/sparse-endian.h +++ b/src/systemd/src/basic/sparse-endian.h @@ -27,8 +27,8 @@ #include <stdint.h> #ifdef __CHECKER__ -#define __sd_bitwise __attribute__((bitwise)) -#define __sd_force __attribute__((force)) +#define __sd_bitwise __attribute__((__bitwise__)) +#define __sd_force __attribute__((__force__)) #else #define __sd_bitwise #define __sd_force diff --git a/src/systemd/src/basic/stat-util.c b/src/systemd/src/basic/stat-util.c index 762777e94..3bef0dfe4 100644 --- a/src/systemd/src/basic/stat-util.c +++ b/src/systemd/src/basic/stat-util.c @@ -47,10 +47,8 @@ int is_dir(const char* path, bool follow) { int is_dir_fd(int fd) { struct stat st; - int r; - r = fstat(fd, &st); - if (r < 0) + if (fstat(fd, &st) < 0) return -errno; return !!S_ISDIR(st.st_mode); @@ -215,15 +213,47 @@ int fd_is_network_fs(int fd) { } int fd_is_network_ns(int fd) { + struct statfs s; int r; - r = fd_is_fs_type(fd, NSFS_MAGIC); - if (r <= 0) - return r; + /* Checks whether the specified file descriptor refers to a network namespace. On old kernels there's no nice + * way to detect that, hence on those we'll return a recognizable error (EUCLEAN), so that callers can handle + * this somewhat nicely. + * + * This function returns > 0 if the fd definitely refers to a network namespace, 0 if it definitely does not + * refer to a network namespace, -EUCLEAN if we can't determine, and other negative error codes on error. */ + + if (fstatfs(fd, &s) < 0) + return -errno; + + if (!is_fs_type(&s, NSFS_MAGIC)) { + /* On really old kernels, there was no "nsfs", and network namespace sockets belonged to procfs + * instead. Handle that in a somewhat smart way. */ + + if (is_fs_type(&s, PROC_SUPER_MAGIC)) { + struct statfs t; + + /* OK, so it is procfs. Let's see if our own network namespace is procfs, too. If so, then the + * passed fd might refer to a network namespace, but we can't know for sure. In that case, + * return a recognizable error. */ + + if (statfs("/proc/self/ns/net", &t) < 0) + return -errno; + + if (s.f_type == t.f_type) + return -EUCLEAN; /* It's possible, we simply don't know */ + } + + return 0; /* No! */ + } r = ioctl(fd, NS_GET_NSTYPE); - if (r < 0) + if (r < 0) { + if (errno == ENOTTY) /* Old kernels didn't know this ioctl, let's also return a recognizable error in that case */ + return -EUCLEAN; + return -errno; + } return r == CLONE_NEWNET; } diff --git a/src/systemd/src/basic/stdio-util.h b/src/systemd/src/basic/stdio-util.h index 73c03274c..dc67b6e76 100644 --- a/src/systemd/src/basic/stdio-util.h +++ b/src/systemd/src/basic/stdio-util.h @@ -7,6 +7,7 @@ #include <sys/types.h> #include "macro.h" +#include "util.h" #define snprintf_ok(buf, len, fmt, ...) \ ((size_t) snprintf(buf, len, fmt, __VA_ARGS__) < (len)) @@ -18,6 +19,9 @@ do { \ int _argtypes[128]; \ size_t _i, _k; \ + /* See https://github.com/google/sanitizers/issues/992 */ \ + if (HAS_FEATURE_MEMORY_SANITIZER) \ + zero(_argtypes); \ _k = parse_printf_format((format), ELEMENTSOF(_argtypes), _argtypes); \ assert(_k < ELEMENTSOF(_argtypes)); \ for (_i = 0; _i < _k; _i++) { \ diff --git a/src/systemd/src/basic/strv.c b/src/systemd/src/basic/strv.c index 1bab723e8..3a62f25de 100644 --- a/src/systemd/src/basic/strv.c +++ b/src/systemd/src/basic/strv.c @@ -169,7 +169,7 @@ char **strv_new_ap(const char *x, va_list ap) { return TAKE_PTR(a); } -char **strv_new(const char *x, ...) { +char **strv_new_internal(const char *x, ...) { char **r; va_list ap; @@ -658,7 +658,7 @@ char **strv_split_nulstr(const char *s) { } if (!r) - return strv_new(NULL, NULL); + return strv_new(NULL); return r; } diff --git a/src/systemd/src/basic/strv.h b/src/systemd/src/basic/strv.h index e9e6063f5..5f1803d87 100644 --- a/src/systemd/src/basic/strv.h +++ b/src/systemd/src/basic/strv.h @@ -54,8 +54,9 @@ bool strv_equal(char **a, char **b); #define strv_contains(l, s) (!!strv_find((l), (s))) -char **strv_new(const char *x, ...) _sentinel_; +char **strv_new_internal(const char *x, ...) _sentinel_; char **strv_new_ap(const char *x, va_list ap); +#define strv_new(...) strv_new_internal(__VA_ARGS__, NULL) #define STRV_IGNORE ((const char *) -1) diff --git a/src/systemd/src/basic/time-util.c b/src/systemd/src/basic/time-util.c index e35168421..30ad83d0a 100644 --- a/src/systemd/src/basic/time-util.c +++ b/src/systemd/src/basic/time-util.c @@ -14,7 +14,6 @@ #include <unistd.h> #include "alloc-util.h" -#include "def.h" #include "fd-util.h" #include "fileio.h" #include "fs-util.h" @@ -868,7 +867,7 @@ int parse_timestamp(const char *t, usec_t *usec) { return tmp.return_value; } -static char* extract_multiplier(char *p, usec_t *multiplier) { +static const char* extract_multiplier(const char *p, usec_t *multiplier) { static const struct { const char *suffix; usec_t usec; @@ -942,8 +941,7 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) { for (;;) { usec_t multiplier = default_unit, k; - long long l, z = 0; - unsigned n = 0; + long long l; char *e; p += strspn(p, WHITESPACE); @@ -966,46 +964,47 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) { return -ERANGE; if (*e == '.') { - char *b = e + 1; - - /* Don't allow "0.-0", "3.+1" or "3. 1" */ - if (IN_SET(*b, '-', '+') || isspace(*b)) - return -EINVAL; - - errno = 0; - z = strtoll(b, &e, 10); - if (errno > 0) - return -errno; - if (z < 0) - return -ERANGE; - if (e == b) - return -EINVAL; - - n = e - b; - + p = e + 1; + p += strspn(p, DIGITS); } else if (e == p) return -EINVAL; + else + p = e; - e += strspn(e, WHITESPACE); - p = extract_multiplier(e, &multiplier); + s = extract_multiplier(p + strspn(p, WHITESPACE), &multiplier); + if (s == p && *s != '\0') + /* Don't allow '12.34.56', but accept '12.34 .56' or '12.34s.56'*/ + return -EINVAL; - something = true; + p = s; + if ((usec_t) l >= USEC_INFINITY / multiplier) + return -ERANGE; - k = ((usec_t) -1) / multiplier; - if ((usec_t) l + 1 >= k || (usec_t) z >= k) + k = (usec_t) l * multiplier; + if (k >= USEC_INFINITY - r) return -ERANGE; - k = (usec_t) z * multiplier; + r += k; - for (; n > 0; n--) - k /= 10; + something = true; - k += (usec_t) l * multiplier; - if (k >= ((usec_t) -1) - r) - return -ERANGE; + if (*e == '.') { + usec_t m = multiplier / 10; + const char *b; - r += k; + for (b = e + 1; *b >= '0' && *b <= '9'; b++, m /= 10) { + k = (usec_t) (*b - '0') * m; + if (k >= USEC_INFINITY - r) + return -ERANGE; + + r += k; + } + + /* Don't allow "0.-0", "3.+1", "3. 1", "3.sec" or "3.hoge"*/ + if (b == e + 1) + return -EINVAL; + } } *usec = r; @@ -1032,44 +1031,60 @@ int parse_sec_fix_0(const char *t, usec_t *ret) { return r; } -int parse_nsec(const char *t, nsec_t *nsec) { +static const char* extract_nsec_multiplier(const char *p, nsec_t *multiplier) { static const struct { const char *suffix; nsec_t nsec; } table[] = { - { "seconds", NSEC_PER_SEC }, - { "second", NSEC_PER_SEC }, - { "sec", NSEC_PER_SEC }, - { "s", NSEC_PER_SEC }, + { "seconds", NSEC_PER_SEC }, + { "second", NSEC_PER_SEC }, + { "sec", NSEC_PER_SEC }, + { "s", NSEC_PER_SEC }, { "minutes", NSEC_PER_MINUTE }, - { "minute", NSEC_PER_MINUTE }, - { "min", NSEC_PER_MINUTE }, - { "months", NSEC_PER_MONTH }, - { "month", NSEC_PER_MONTH }, - { "msec", NSEC_PER_MSEC }, - { "ms", NSEC_PER_MSEC }, - { "m", NSEC_PER_MINUTE }, - { "hours", NSEC_PER_HOUR }, - { "hour", NSEC_PER_HOUR }, - { "hr", NSEC_PER_HOUR }, - { "h", NSEC_PER_HOUR }, - { "days", NSEC_PER_DAY }, - { "day", NSEC_PER_DAY }, - { "d", NSEC_PER_DAY }, - { "weeks", NSEC_PER_WEEK }, - { "week", NSEC_PER_WEEK }, - { "w", NSEC_PER_WEEK }, - { "years", NSEC_PER_YEAR }, - { "year", NSEC_PER_YEAR }, - { "y", NSEC_PER_YEAR }, - { "usec", NSEC_PER_USEC }, - { "us", NSEC_PER_USEC }, - { "µs", NSEC_PER_USEC }, - { "nsec", 1ULL }, - { "ns", 1ULL }, - { "", 1ULL }, /* default is nsec */ + { "minute", NSEC_PER_MINUTE }, + { "min", NSEC_PER_MINUTE }, + { "months", NSEC_PER_MONTH }, + { "month", NSEC_PER_MONTH }, + { "M", NSEC_PER_MONTH }, + { "msec", NSEC_PER_MSEC }, + { "ms", NSEC_PER_MSEC }, + { "m", NSEC_PER_MINUTE }, + { "hours", NSEC_PER_HOUR }, + { "hour", NSEC_PER_HOUR }, + { "hr", NSEC_PER_HOUR }, + { "h", NSEC_PER_HOUR }, + { "days", NSEC_PER_DAY }, + { "day", NSEC_PER_DAY }, + { "d", NSEC_PER_DAY }, + { "weeks", NSEC_PER_WEEK }, + { "week", NSEC_PER_WEEK }, + { "w", NSEC_PER_WEEK }, + { "years", NSEC_PER_YEAR }, + { "year", NSEC_PER_YEAR }, + { "y", NSEC_PER_YEAR }, + { "usec", NSEC_PER_USEC }, + { "us", NSEC_PER_USEC }, + { "µs", NSEC_PER_USEC }, + { "nsec", 1ULL }, + { "ns", 1ULL }, + { "", 1ULL }, /* default is nsec */ }; + size_t i; + + for (i = 0; i < ELEMENTSOF(table); i++) { + char *e; + + e = startswith(p, table[i].suffix); + if (e) { + *multiplier = table[i].nsec; + return e; + } + } + + return p; +} +int parse_nsec(const char *t, nsec_t *nsec) { const char *p, *s; nsec_t r = 0; bool something = false; @@ -1091,8 +1106,8 @@ int parse_nsec(const char *t, nsec_t *nsec) { } for (;;) { - long long l, z = 0; - size_t n = 0, i; + nsec_t multiplier = 1, k; + long long l; char *e; p += strspn(p, WHITESPACE); @@ -1104,7 +1119,7 @@ int parse_nsec(const char *t, nsec_t *nsec) { break; } - if (*p == '-') + if (*p == '-') /* Don't allow "-0" */ return -ERANGE; errno = 0; @@ -1115,54 +1130,47 @@ int parse_nsec(const char *t, nsec_t *nsec) { return -ERANGE; if (*e == '.') { - char *b = e + 1; - - if (IN_SET(*b, '-', '+') || isspace(*b)) - return -EINVAL; - - errno = 0; - z = strtoll(b, &e, 10); - if (errno > 0) - return -errno; - if (z < 0) - return -ERANGE; - if (e == b) - return -EINVAL; - - n = e - b; - + p = e + 1; + p += strspn(p, DIGITS); } else if (e == p) return -EINVAL; + else + p = e; - e += strspn(e, WHITESPACE); + s = extract_nsec_multiplier(p + strspn(p, WHITESPACE), &multiplier); + if (s == p && *s != '\0') + /* Don't allow '12.34.56', but accept '12.34 .56' or '12.34s.56'*/ + return -EINVAL; - for (i = 0; i < ELEMENTSOF(table); i++) - if (startswith(e, table[i].suffix)) { - nsec_t k; + p = s; - k = ((nsec_t) -1) / table[i].nsec; - if ((nsec_t) l + 1 >= k || (nsec_t) z >= k) - return -ERANGE; + if ((nsec_t) l >= NSEC_INFINITY / multiplier) + return -ERANGE; + + k = (nsec_t) l * multiplier; + if (k >= NSEC_INFINITY - r) + return -ERANGE; - k = (nsec_t) z * table[i].nsec; + r += k; + + something = true; - for (; n > 0; n--) - k /= 10; + if (*e == '.') { + nsec_t m = multiplier / 10; + const char *b; - k += (nsec_t) l * table[i].nsec; - if (k >= ((nsec_t) -1) - r) + for (b = e + 1; *b >= '0' && *b <= '9'; b++, m /= 10) { + k = (nsec_t) (*b - '0') * m; + if (k >= NSEC_INFINITY - r) return -ERANGE; r += k; - p = e + strlen(table[i].suffix); - - something = true; - break; } - if (i >= ELEMENTSOF(table)) - return -EINVAL; - + /* Don't allow "0.-0", "3.+1", "3. 1", "3.sec" or "3.hoge"*/ + if (b == e + 1) + return -EINVAL; + } } *nsec = r; @@ -1190,7 +1198,7 @@ int get_timezones(char ***ret) { assert(ret); - zones = strv_new("UTC", NULL); + zones = strv_new("UTC"); if (!zones) return -ENOMEM; diff --git a/src/systemd/src/basic/util.c b/src/systemd/src/basic/util.c index 0da963f4a..00052c5e1 100644 --- a/src/systemd/src/basic/util.c +++ b/src/systemd/src/basic/util.c @@ -165,6 +165,28 @@ void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size, return NULL; } +bool memeqzero(const void *data, size_t length) { + /* Does the buffer consist entirely of NULs? + * Copied from https://github.com/systemd/casync/, copied in turn from + * https://github.com/rustyrussell/ccan/blob/master/ccan/mem/mem.c#L92, + * which is licensed CC-0. + */ + + const uint8_t *p = data; + size_t i; + + /* Check first 16 bytes manually */ + for (i = 0; i < 16; i++, length--) { + if (length == 0) + return true; + if (p[i]) + return false; + } + + /* Now we know first 16 bytes are NUL, memcmp with self. */ + return memcmp(data, p + i, length) == 0; +} + int on_ac_power(void) { bool found_offline = false, found_online = false; _cleanup_closedir_ DIR *d = NULL; @@ -248,7 +270,9 @@ int container_get_leader(const char *machine, pid_t *pid) { return -EINVAL; p = strjoina("/run/systemd/machines/", machine); - r = parse_env_file(NULL, p, NEWLINE, "LEADER", &s, "CLASS", &class, NULL); + r = parse_env_file(NULL, p, + "LEADER", &s, + "CLASS", &class); if (r == -ENOENT) return -EHOSTDOWN; if (r < 0) @@ -606,7 +630,7 @@ void disable_coredumps(void) { if (detect_container() > 0) return; - r = write_string_file("/proc/sys/kernel/core_pattern", "|/bin/false", 0); + r = write_string_file("/proc/sys/kernel/core_pattern", "|/bin/false", WRITE_STRING_FILE_DISABLE_BUFFER); if (r < 0) log_debug_errno(r, "Failed to turn off coredumps, ignoring: %m"); } diff --git a/src/systemd/src/basic/util.h b/src/systemd/src/basic/util.h index 8cba4ed72..2f3d1eeab 100644 --- a/src/systemd/src/basic/util.h +++ b/src/systemd/src/basic/util.h @@ -159,6 +159,10 @@ int on_ac_power(void); #define zero(x) (memzero(&(x), sizeof(x))) +bool memeqzero(const void *data, size_t length); + +#define eqzero(x) memeqzero(x, sizeof(x)) + static inline void *mempset(void *s, int c, size_t n) { memset(s, c, n); return (uint8_t*)s + n; @@ -168,7 +172,8 @@ static inline void _reset_errno_(int *saved_errno) { errno = *saved_errno; } -#define PROTECT_ERRNO _cleanup_(_reset_errno_) __attribute__((unused)) int _saved_errno_ = errno +#define PROTECT_ERRNO \ + _cleanup_(_reset_errno_) __attribute__((__unused__)) int _saved_errno_ = errno static inline int negative_errno(void) { /* This helper should be used to shut up gcc if you know 'errno' is diff --git a/src/systemd/src/libsystemd-network/dhcp-identifier.c b/src/systemd/src/libsystemd-network/dhcp-identifier.c index 77c584ee6..c768adeb6 100644 --- a/src/systemd/src/libsystemd-network/dhcp-identifier.c +++ b/src/systemd/src/libsystemd-network/dhcp-identifier.c @@ -148,24 +148,30 @@ int dhcp_identifier_set_duid_uuid(struct duid *duid, size_t *len) { return 0; } -int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, void *_id) { +int dhcp_identifier_set_iaid( + int ifindex, + const uint8_t *mac, + size_t mac_len, + bool legacy_unstable_byteorder, + void *_id) { /* name is a pointer to memory in the sd_device struct, so must * have the same scope */ _cleanup_(sd_device_unrefp) sd_device *device = NULL; const char *name = NULL; uint64_t id; + uint32_t id32; if (detect_container() <= 0) { /* not in a container, udev will be around */ char ifindex_str[2 + DECIMAL_STR_MAX(int)]; - int initialized, r; + int r; sprintf(ifindex_str, "n%d", ifindex); if (sd_device_new_from_device_id(&device, ifindex_str) >= 0) { - r = sd_device_get_is_initialized(device, &initialized); + r = sd_device_get_is_initialized(device); if (r < 0) return r; - if (!initialized) + if (r == 0) /* not yet ready */ return -EBUSY; @@ -179,10 +185,18 @@ int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, void *_i /* fall back to MAC address if no predictable name available */ id = siphash24(mac, mac_len, HASH_KEY.bytes); - id = htole64(id); + id32 = (id & 0xffffffff) ^ (id >> 32); - /* fold into 32 bits */ - unaligned_write_be32(_id, (id & 0xffffffff) ^ (id >> 32)); + if (legacy_unstable_byteorder) + /* for historical reasons (a bug), the bits were swapped and thus + * the result was endianness dependant. Preserve that behavior. */ + id32 = __bswap_32(id32); + else + /* the fixed behavior returns a stable byte order. Since LE is expected + * to be more common, swap the bytes on LE to give the same as legacy + * behavior. */ + id32 = be32toh(id32); + unaligned_write_ne32(_id, id32); return 0; } diff --git a/src/systemd/src/libsystemd-network/dhcp-identifier.h b/src/systemd/src/libsystemd-network/dhcp-identifier.h index 64315d3a3..a544f38ab 100644 --- a/src/systemd/src/libsystemd-network/dhcp-identifier.h +++ b/src/systemd/src/libsystemd-network/dhcp-identifier.h @@ -57,4 +57,4 @@ int dhcp_identifier_set_duid_llt(struct duid *duid, usec_t t, const uint8_t *add int dhcp_identifier_set_duid_ll(struct duid *duid, const uint8_t *addr, size_t addr_len, uint16_t arp_type, size_t *len); int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len); int dhcp_identifier_set_duid_uuid(struct duid *duid, size_t *len); -int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, void *_id); +int dhcp_identifier_set_iaid(int ifindex, const uint8_t *mac, size_t mac_len, bool legacy_unstable_byteorder, void *_id); diff --git a/src/systemd/src/libsystemd-network/dhcp-packet.c b/src/systemd/src/libsystemd-network/dhcp-packet.c index d29cd06cb..ad5f8e267 100644 --- a/src/systemd/src/libsystemd-network/dhcp-packet.c +++ b/src/systemd/src/libsystemd-network/dhcp-packet.c @@ -106,70 +106,62 @@ int dhcp_packet_verify_headers(DHCPPacket *packet, size_t len, bool checksum, ui /* IP */ - if (packet->ip.version != IPVERSION) { - log_debug("ignoring packet: not IPv4"); - return -EINVAL; - } + if (packet->ip.version != IPVERSION) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "ignoring packet: not IPv4"); - if (packet->ip.ihl < 5) { - log_debug("ignoring packet: IPv4 IHL (%u words) invalid", - packet->ip.ihl); - return -EINVAL; - } + if (packet->ip.ihl < 5) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "ignoring packet: IPv4 IHL (%u words) invalid", + packet->ip.ihl); hdrlen = packet->ip.ihl * 4; - if (hdrlen < 20) { - log_debug("ignoring packet: IPv4 IHL (%zu bytes) " - "smaller than minimum (20 bytes)", hdrlen); - return -EINVAL; - } - - if (len < hdrlen) { - log_debug("ignoring packet: packet (%zu bytes) " - "smaller than expected (%zu) by IP header", len, - hdrlen); - return -EINVAL; - } + if (hdrlen < 20) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "ignoring packet: IPv4 IHL (%zu bytes) " + "smaller than minimum (20 bytes)", + hdrlen); + + if (len < hdrlen) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "ignoring packet: packet (%zu bytes) " + "smaller than expected (%zu) by IP header", + len, hdrlen); /* UDP */ - if (packet->ip.protocol != IPPROTO_UDP) { - log_debug("ignoring packet: not UDP"); - return -EINVAL; - } + if (packet->ip.protocol != IPPROTO_UDP) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "ignoring packet: not UDP"); - if (len < hdrlen + be16toh(packet->udp.len)) { - log_debug("ignoring packet: packet (%zu bytes) " - "smaller than expected (%zu) by UDP header", len, - hdrlen + be16toh(packet->udp.len)); - return -EINVAL; - } + if (len < hdrlen + be16toh(packet->udp.len)) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "ignoring packet: packet (%zu bytes) " + "smaller than expected (%zu) by UDP header", + len, hdrlen + be16toh(packet->udp.len)); - if (be16toh(packet->udp.dest) != port) { - log_debug("ignoring packet: to port %u, which " - "is not the DHCP client port (%u)", - be16toh(packet->udp.dest), port); - return -EINVAL; - } + if (be16toh(packet->udp.dest) != port) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "ignoring packet: to port %u, which " + "is not the DHCP client port (%u)", + be16toh(packet->udp.dest), port); /* checksums - computing these is relatively expensive, so only do it if all the other checks have passed */ - if (dhcp_packet_checksum((uint8_t*)&packet->ip, hdrlen)) { - log_debug("ignoring packet: invalid IP checksum"); - return -EINVAL; - } + if (dhcp_packet_checksum((uint8_t*)&packet->ip, hdrlen)) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "ignoring packet: invalid IP checksum"); if (checksum && packet->udp.check) { packet->ip.check = packet->udp.len; packet->ip.ttl = 0; if (dhcp_packet_checksum((uint8_t*)&packet->ip.ttl, - be16toh(packet->udp.len) + 12)) { - log_debug("ignoring packet: invalid UDP checksum"); - return -EINVAL; - } + be16toh(packet->udp.len) + 12)) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "ignoring packet: invalid UDP checksum"); } return 0; diff --git a/src/systemd/src/libsystemd-network/lldp-internal.h b/src/systemd/src/libsystemd-network/lldp-internal.h index 328d51f8e..88b54933c 100644 --- a/src/systemd/src/libsystemd-network/lldp-internal.h +++ b/src/systemd/src/libsystemd-network/lldp-internal.h @@ -34,3 +34,6 @@ struct sd_lldp { #define log_lldp_errno(error, fmt, ...) log_internal(LOG_DEBUG, error, __FILE__, __LINE__, __func__, "LLDP: " fmt, ##__VA_ARGS__) #define log_lldp(fmt, ...) log_lldp_errno(0, fmt, ##__VA_ARGS__) + +const char* lldp_event_to_string(sd_lldp_event e) _const_; +sd_lldp_event lldp_event_from_string(const char *s) _pure_; diff --git a/src/systemd/src/libsystemd-network/network-internal.c b/src/systemd/src/libsystemd-network/network-internal.c index 949798a1d..d35e3e2ce 100644 --- a/src/systemd/src/libsystemd-network/network-internal.c +++ b/src/systemd/src/libsystemd-network/network-internal.c @@ -255,11 +255,10 @@ int config_parse_ifalias(const char *unit, return 0; } - free(*s); - if (*n) - *s = TAKE_PTR(n); + if (isempty(n)) + *s = mfree(*s); else - *s = NULL; + free_and_replace(*s, n); return 0; } @@ -294,7 +293,7 @@ int config_parse_hwaddr(const char *unit, return 0; } - *hwaddr = TAKE_PTR(n); + free_and_replace(*hwaddr, n); return 0; } diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-client.c b/src/systemd/src/libsystemd-network/sd-dhcp-client.c index dde2d0ceb..df9428518 100644 --- a/src/systemd/src/libsystemd-network/sd-dhcp-client.c +++ b/src/systemd/src/libsystemd-network/sd-dhcp-client.c @@ -21,6 +21,7 @@ #include "dhcp-lease-internal.h" #include "dhcp-protocol.h" #include "dns-domain.h" +#include "event-util.h" #include "hostname-util.h" #include "random-util.h" #include "string-util.h" @@ -371,6 +372,7 @@ static int dhcp_client_set_iaid_duid_internal( if (iaid == 0) { r = dhcp_identifier_set_iaid(client->ifindex, client->mac_addr, client->mac_addr_len, + true, &client->client_id.ns.iaid); if (r < 0) return r; @@ -545,11 +547,10 @@ static int client_initialize(sd_dhcp_client *client) { client->fd = asynchronous_close(client->fd); - client->timeout_resend = sd_event_source_unref(client->timeout_resend); - - client->timeout_t1 = sd_event_source_unref(client->timeout_t1); - client->timeout_t2 = sd_event_source_unref(client->timeout_t2); - client->timeout_expire = sd_event_source_unref(client->timeout_expire); + (void) event_source_disable(client->timeout_resend); + (void) event_source_disable(client->timeout_t1); + (void) event_source_disable(client->timeout_t2); + (void) event_source_disable(client->timeout_expire); client->attempt = 1; @@ -650,7 +651,8 @@ static int client_message_init( client->client_id.type = 255; - r = dhcp_identifier_set_iaid(client->ifindex, client->mac_addr, client->mac_addr_len, &client->client_id.ns.iaid); + r = dhcp_identifier_set_iaid(client->ifindex, client->mac_addr, client->mac_addr_len, + true, &client->client_id.ns.iaid); if (r < 0) return r; @@ -1063,22 +1065,11 @@ static int client_timeout_resend( next_timeout += (random_u32() & 0x1fffff); - client->timeout_resend = sd_event_source_unref(client->timeout_resend); - - r = sd_event_add_time(client->event, - &client->timeout_resend, - clock_boottime_or_monotonic(), - next_timeout, 10 * USEC_PER_MSEC, - client_timeout_resend, client); - if (r < 0) - goto error; - - r = sd_event_source_set_priority(client->timeout_resend, - client->event_priority); - if (r < 0) - goto error; - - r = sd_event_source_set_description(client->timeout_resend, "dhcp4-resend-timer"); + r = event_reset_time(client->event, &client->timeout_resend, + clock_boottime_or_monotonic(), + next_timeout, 10 * USEC_PER_MSEC, + client_timeout_resend, client, + client->event_priority, "dhcp4-resend-timer", true); if (r < 0) goto error; @@ -1175,31 +1166,16 @@ static int client_initialize_time_events(sd_dhcp_client *client) { assert(client); assert(client->event); - client->timeout_resend = sd_event_source_unref(client->timeout_resend); - if (client->start_delay) { assert_se(sd_event_now(client->event, clock_boottime_or_monotonic(), &usec) >= 0); usec += client->start_delay; } - r = sd_event_add_time(client->event, - &client->timeout_resend, - clock_boottime_or_monotonic(), - usec, 0, - client_timeout_resend, client); - if (r < 0) - goto error; - - r = sd_event_source_set_priority(client->timeout_resend, - client->event_priority); - if (r < 0) - goto error; - - r = sd_event_source_set_description(client->timeout_resend, "dhcp4-resend-timer"); - if (r < 0) - goto error; - -error: + r = event_reset_time(client->event, &client->timeout_resend, + clock_boottime_or_monotonic(), + usec, 0, + client_timeout_resend, client, + client->event_priority, "dhcp4-resend-timer", true); if (r < 0) client_stop(client, r); @@ -1457,13 +1433,14 @@ static int client_set_lease_timeouts(sd_dhcp_client *client) { assert(client->lease); assert(client->lease->lifetime); - client->timeout_t1 = sd_event_source_unref(client->timeout_t1); - client->timeout_t2 = sd_event_source_unref(client->timeout_t2); - client->timeout_expire = sd_event_source_unref(client->timeout_expire); - /* don't set timers for infinite leases */ - if (client->lease->lifetime == 0xffffffff) + if (client->lease->lifetime == 0xffffffff) { + (void) event_source_disable(client->timeout_t1); + (void) event_source_disable(client->timeout_t2); + (void) event_source_disable(client->timeout_expire); + return 0; + } r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now); if (r < 0) @@ -1515,19 +1492,11 @@ static int client_set_lease_timeouts(sd_dhcp_client *client) { } /* arm lifetime timeout */ - r = sd_event_add_time(client->event, &client->timeout_expire, - clock_boottime_or_monotonic(), - lifetime_timeout, 10 * USEC_PER_MSEC, - client_timeout_expire, client); - if (r < 0) - return r; - - r = sd_event_source_set_priority(client->timeout_expire, - client->event_priority); - if (r < 0) - return r; - - r = sd_event_source_set_description(client->timeout_expire, "dhcp4-lifetime"); + r = event_reset_time(client->event, &client->timeout_expire, + clock_boottime_or_monotonic(), + lifetime_timeout, 10 * USEC_PER_MSEC, + client_timeout_expire, client, + client->event_priority, "dhcp4-lifetime", true); if (r < 0) return r; @@ -1539,21 +1508,11 @@ static int client_set_lease_timeouts(sd_dhcp_client *client) { return 0; /* arm T2 timeout */ - r = sd_event_add_time(client->event, - &client->timeout_t2, - clock_boottime_or_monotonic(), - t2_timeout, - 10 * USEC_PER_MSEC, - client_timeout_t2, client); - if (r < 0) - return r; - - r = sd_event_source_set_priority(client->timeout_t2, - client->event_priority); - if (r < 0) - return r; - - r = sd_event_source_set_description(client->timeout_t2, "dhcp4-t2-timeout"); + r = event_reset_time(client->event, &client->timeout_t2, + clock_boottime_or_monotonic(), + t2_timeout, 10 * USEC_PER_MSEC, + client_timeout_t2, client, + client->event_priority, "dhcp4-t2-timeout", true); if (r < 0) return r; @@ -1565,20 +1524,11 @@ static int client_set_lease_timeouts(sd_dhcp_client *client) { return 0; /* arm T1 timeout */ - r = sd_event_add_time(client->event, - &client->timeout_t1, - clock_boottime_or_monotonic(), - t1_timeout, 10 * USEC_PER_MSEC, - client_timeout_t1, client); - if (r < 0) - return r; - - r = sd_event_source_set_priority(client->timeout_t1, - client->event_priority); - if (r < 0) - return r; - - r = sd_event_source_set_description(client->timeout_t1, "dhcp4-t1-timer"); + r = event_reset_time(client->event, &client->timeout_t1, + clock_boottime_or_monotonic(), + t1_timeout, 10 * USEC_PER_MSEC, + client_timeout_t1, client, + client->event_priority, "dhcp4-t1-timer", true); if (r < 0) return r; @@ -1603,26 +1553,14 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, i r = client_handle_offer(client, message, len); if (r >= 0) { - client->timeout_resend = - sd_event_source_unref(client->timeout_resend); - client->state = DHCP_STATE_REQUESTING; client->attempt = 1; - r = sd_event_add_time(client->event, - &client->timeout_resend, - clock_boottime_or_monotonic(), - 0, 0, - client_timeout_resend, client); - if (r < 0) - goto error; - - r = sd_event_source_set_priority(client->timeout_resend, - client->event_priority); - if (r < 0) - goto error; - - r = sd_event_source_set_description(client->timeout_resend, "dhcp4-resend-timer"); + r = event_reset_time(client->event, &client->timeout_resend, + clock_boottime_or_monotonic(), + 0, 0, + client_timeout_resend, client, + client->event_priority, "dhcp4-resend-timer", true); if (r < 0) goto error; } else if (r == -ENOMSG) @@ -1639,8 +1577,7 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, i r = client_handle_ack(client, message, len); if (r >= 0) { client->start_delay = 0; - client->timeout_resend = - sd_event_source_unref(client->timeout_resend); + (void) event_source_disable(client->timeout_resend); client->receive_message = sd_event_source_unref(client->receive_message); client->fd = asynchronous_close(client->fd); @@ -1680,9 +1617,6 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, i } else if (r == -EADDRNOTAVAIL) { /* got a NAK, let's restart the client */ - client->timeout_resend = - sd_event_source_unref(client->timeout_resend); - client_notify(client, SD_DHCP_CLIENT_EVENT_EXPIRED); r = client_initialize(client); @@ -1958,9 +1892,12 @@ static sd_dhcp_client *dhcp_client_free(sd_dhcp_client *client) { log_dhcp_client(client, "FREE"); - client_initialize(client); + client->timeout_resend = sd_event_source_unref(client->timeout_resend); + client->timeout_t1 = sd_event_source_unref(client->timeout_t1); + client->timeout_t2 = sd_event_source_unref(client->timeout_t2); + client->timeout_expire = sd_event_source_unref(client->timeout_expire); - client->receive_message = sd_event_source_unref(client->receive_message); + client_initialize(client); sd_dhcp_client_detach_event(client); @@ -1980,19 +1917,20 @@ int sd_dhcp_client_new(sd_dhcp_client **ret, int anonymize) { assert_return(ret, -EINVAL); - client = new0(sd_dhcp_client, 1); + client = new(sd_dhcp_client, 1); if (!client) return -ENOMEM; - client->n_ref = 1; - client->state = DHCP_STATE_INIT; - client->ifindex = -1; - client->fd = -1; - client->attempt = 1; - client->mtu = DHCP_DEFAULT_MIN_SIZE; - client->port = DHCP_PORT_CLIENT; - - client->anonymize = !!anonymize; + *client = (sd_dhcp_client) { + .n_ref = 1, + .state = DHCP_STATE_INIT, + .ifindex = -1, + .fd = -1, + .attempt = 1, + .mtu = DHCP_DEFAULT_MIN_SIZE, + .port = DHCP_PORT_CLIENT, + .anonymize = !!anonymize, + }; /* NOTE: this could be moved to a function. */ if (anonymize) { client->req_opts_size = ELEMENTSOF(default_req_opts_anonymize); diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-lease.c b/src/systemd/src/libsystemd-network/sd-dhcp-lease.c index 863818d6d..a90c01d7d 100644 --- a/src/systemd/src/libsystemd-network/sd-dhcp-lease.c +++ b/src/systemd/src/libsystemd-network/sd-dhcp-lease.c @@ -1016,7 +1016,7 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) { if (r < 0) return r; - r = parse_env_file(NULL, lease_file, NEWLINE, + r = parse_env_file(NULL, lease_file, "ADDRESS", &address, "ROUTER", &router, "NETMASK", &netmask, @@ -1067,8 +1067,7 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) { "OPTION_251", &options[27], "OPTION_252", &options[28], "OPTION_253", &options[29], - "OPTION_254", &options[30], - NULL); + "OPTION_254", &options[30]); if (r < 0) return r; diff --git a/src/systemd/src/libsystemd-network/sd-dhcp6-client.c b/src/systemd/src/libsystemd-network/sd-dhcp6-client.c index 2ddfead4b..c81c0f095 100644 --- a/src/systemd/src/libsystemd-network/sd-dhcp6-client.c +++ b/src/systemd/src/libsystemd-network/sd-dhcp6-client.c @@ -16,6 +16,7 @@ #include "dhcp6-lease-internal.h" #include "dhcp6-protocol.h" #include "dns-domain.h" +#include "event-util.h" #include "fd-util.h" #include "hostname-util.h" #include "in-addr-util.h" @@ -408,12 +409,11 @@ static int client_reset(sd_dhcp6_client *client) { client->retransmit_time = 0; client->retransmit_count = 0; - client->timeout_resend = sd_event_source_unref(client->timeout_resend); - client->timeout_resend_expire = - sd_event_source_unref(client->timeout_resend_expire); - client->timeout_t1 = sd_event_source_unref(client->timeout_t1); - client->timeout_t2 = sd_event_source_unref(client->timeout_t2); + (void) event_source_disable(client->timeout_resend); + (void) event_source_disable(client->timeout_resend_expire); + (void) event_source_disable(client->timeout_t1); + (void) event_source_disable(client->timeout_t2); client->state = DHCP6_STATE_STOPPED; @@ -600,8 +600,7 @@ static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata) assert(client); assert(client->lease); - client->timeout_t2 = - sd_event_source_unref(client->timeout_t2); + (void) event_source_disable(client->timeout_t2); log_dhcp6_client(client, "Timeout T2"); @@ -617,8 +616,7 @@ static int client_timeout_t1(sd_event_source *s, uint64_t usec, void *userdata) assert(client); assert(client->lease); - client->timeout_t1 = - sd_event_source_unref(client->timeout_t1); + (void) event_source_disable(client->timeout_t1); log_dhcp6_client(client, "Timeout T1"); @@ -666,7 +664,7 @@ static int client_timeout_resend(sd_event_source *s, uint64_t usec, void *userda assert(client); assert(client->event); - client->timeout_resend = sd_event_source_unref(client->timeout_resend); + (void) event_source_disable(client->timeout_resend); switch (client->state) { case DHCP6_STATE_INFORMATION_REQUEST: @@ -708,7 +706,7 @@ static int client_timeout_resend(sd_event_source *s, uint64_t usec, void *userda init_retransmit_time = DHCP6_REB_TIMEOUT; max_retransmit_time = DHCP6_REB_MAX_RT; - if (!client->timeout_resend_expire) { + if (event_source_is_enabled(client->timeout_resend_expire) <= 0) { r = dhcp6_lease_ia_rebind_expire(&client->lease->ia, &expire); if (r < 0) { @@ -757,43 +755,24 @@ static int client_timeout_resend(sd_event_source *s, uint64_t usec, void *userda log_dhcp6_client(client, "Next retransmission in %s", format_timespan(time_string, FORMAT_TIMESPAN_MAX, client->retransmit_time, USEC_PER_SEC)); - r = sd_event_add_time(client->event, &client->timeout_resend, - clock_boottime_or_monotonic(), - time_now + client->retransmit_time, - 10 * USEC_PER_MSEC, client_timeout_resend, - client); - if (r < 0) - goto error; - - r = sd_event_source_set_priority(client->timeout_resend, - client->event_priority); - if (r < 0) - goto error; - - r = sd_event_source_set_description(client->timeout_resend, "dhcp6-resend-timer"); + r = event_reset_time(client->event, &client->timeout_resend, + clock_boottime_or_monotonic(), + time_now + client->retransmit_time, 10 * USEC_PER_MSEC, + client_timeout_resend, client, + client->event_priority, "dhcp6-resend-timer", true); if (r < 0) goto error; - if (max_retransmit_duration && !client->timeout_resend_expire) { + if (max_retransmit_duration && event_source_is_enabled(client->timeout_resend_expire) <= 0) { log_dhcp6_client(client, "Max retransmission duration %"PRIu64" secs", max_retransmit_duration / USEC_PER_SEC); - r = sd_event_add_time(client->event, - &client->timeout_resend_expire, - clock_boottime_or_monotonic(), - time_now + max_retransmit_duration, - USEC_PER_SEC, - client_timeout_resend_expire, client); - if (r < 0) - goto error; - - r = sd_event_source_set_priority(client->timeout_resend_expire, - client->event_priority); - if (r < 0) - goto error; - - r = sd_event_source_set_description(client->timeout_resend_expire, "dhcp6-resend-expire-timer"); + r = event_reset_time(client->event, &client->timeout_resend_expire, + clock_boottime_or_monotonic(), + time_now + max_retransmit_duration, USEC_PER_SEC, + client_timeout_resend_expire, client, + client->event_priority, "dhcp6-resend-expire-timer", true); if (r < 0) goto error; } @@ -807,14 +786,14 @@ error: static int client_ensure_iaid(sd_dhcp6_client *client) { int r; - be32_t iaid; + uint32_t iaid; assert(client); if (client->ia_na.ia_na.id) return 0; - r = dhcp_identifier_set_iaid(client->ifindex, client->mac_addr, client->mac_addr_len, &iaid); + r = dhcp_identifier_set_iaid(client->ifindex, client->mac_addr, client->mac_addr_len, true, &iaid); if (r < 0) return r; @@ -1263,9 +1242,8 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state) { assert_return(client->ifindex > 0, -EINVAL); assert_return(client->state != state, -EINVAL); - client->timeout_resend_expire = - sd_event_source_unref(client->timeout_resend_expire); - client->timeout_resend = sd_event_source_unref(client->timeout_resend); + (void) event_source_disable(client->timeout_resend_expire); + (void) event_source_disable(client->timeout_resend); client->retransmit_time = 0; client->retransmit_count = 0; @@ -1332,20 +1310,11 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state) { log_dhcp6_client(client, "T1 expires in %s", format_timespan(time_string, FORMAT_TIMESPAN_MAX, timeout, USEC_PER_SEC)); - r = sd_event_add_time(client->event, - &client->timeout_t1, - clock_boottime_or_monotonic(), time_now + timeout, - 10 * USEC_PER_SEC, client_timeout_t1, - client); - if (r < 0) - goto error; - - r = sd_event_source_set_priority(client->timeout_t1, - client->event_priority); - if (r < 0) - goto error; - - r = sd_event_source_set_description(client->timeout_t1, "dhcp6-t1-timeout"); + r = event_reset_time(client->event, &client->timeout_t1, + clock_boottime_or_monotonic(), + time_now + timeout, 10 * USEC_PER_SEC, + client_timeout_t1, client, + client->event_priority, "dhcp6-t1-timeout", true); if (r < 0) goto error; @@ -1354,20 +1323,11 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state) { log_dhcp6_client(client, "T2 expires in %s", format_timespan(time_string, FORMAT_TIMESPAN_MAX, timeout, USEC_PER_SEC)); - r = sd_event_add_time(client->event, - &client->timeout_t2, - clock_boottime_or_monotonic(), time_now + timeout, - 10 * USEC_PER_SEC, client_timeout_t2, - client); - if (r < 0) - goto error; - - r = sd_event_source_set_priority(client->timeout_t2, - client->event_priority); - if (r < 0) - goto error; - - r = sd_event_source_set_description(client->timeout_t2, "dhcp6-t2-timeout"); + r = event_reset_time(client->event, &client->timeout_t2, + clock_boottime_or_monotonic(), + time_now + timeout, 10 * USEC_PER_SEC, + client_timeout_t2, client, + client->event_priority, "dhcp6-t2-timeout", true); if (r < 0) goto error; @@ -1379,18 +1339,11 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state) { client->transaction_id = random_u32() & htobe32(0x00ffffff); client->transaction_start = time_now; - r = sd_event_add_time(client->event, &client->timeout_resend, - clock_boottime_or_monotonic(), 0, 0, client_timeout_resend, - client); - if (r < 0) - goto error; - - r = sd_event_source_set_priority(client->timeout_resend, - client->event_priority); - if (r < 0) - goto error; - - r = sd_event_source_set_description(client->timeout_resend, "dhcp6-resend-timeout"); + r = event_reset_time(client->event, &client->timeout_resend, + clock_boottime_or_monotonic(), + 0, 0, + client_timeout_resend, client, + client->event_priority, "dhcp6-resend-timeout", true); if (r < 0) goto error; @@ -1503,6 +1456,11 @@ sd_event *sd_dhcp6_client_get_event(sd_dhcp6_client *client) { static sd_dhcp6_client *dhcp6_client_free(sd_dhcp6_client *client) { assert(client); + client->timeout_resend = sd_event_source_unref(client->timeout_resend); + client->timeout_resend_expire = sd_event_source_unref(client->timeout_resend_expire); + client->timeout_t1 = sd_event_source_unref(client->timeout_t1); + client->timeout_t2 = sd_event_source_unref(client->timeout_t2); + client_reset(client); client->fd = safe_close(client->fd); @@ -1518,28 +1476,32 @@ DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp6_client, sd_dhcp6_client, dhcp6_client_fre int sd_dhcp6_client_new(sd_dhcp6_client **ret) { _cleanup_(sd_dhcp6_client_unrefp) sd_dhcp6_client *client = NULL; + _cleanup_free_ be16_t *req_opts = NULL; size_t t; assert_return(ret, -EINVAL); - client = new0(sd_dhcp6_client, 1); - if (!client) + req_opts = new(be16_t, ELEMENTSOF(default_req_opts)); + if (!req_opts) return -ENOMEM; - client->n_ref = 1; - client->ia_na.type = SD_DHCP6_OPTION_IA_NA; - client->ia_pd.type = SD_DHCP6_OPTION_IA_PD; - client->ifindex = -1; - client->request = DHCP6_REQUEST_IA_NA; - client->fd = -1; + for (t = 0; t < ELEMENTSOF(default_req_opts); t++) + req_opts[t] = htobe16(default_req_opts[t]); - client->req_opts_len = ELEMENTSOF(default_req_opts); - client->req_opts = new0(be16_t, client->req_opts_len); - if (!client->req_opts) + client = new(sd_dhcp6_client, 1); + if (!client) return -ENOMEM; - for (t = 0; t < client->req_opts_len; t++) - client->req_opts[t] = htobe16(default_req_opts[t]); + *client = (sd_dhcp6_client) { + .n_ref = 1, + .ia_na.type = SD_DHCP6_OPTION_IA_NA, + .ia_pd.type = SD_DHCP6_OPTION_IA_PD, + .ifindex = -1, + .request = DHCP6_REQUEST_IA_NA, + .fd = -1, + .req_opts_len = ELEMENTSOF(default_req_opts), + .req_opts = TAKE_PTR(req_opts), + }; *ret = TAKE_PTR(client); diff --git a/src/systemd/src/libsystemd-network/sd-ipv4acd.c b/src/systemd/src/libsystemd-network/sd-ipv4acd.c index 6c12b5144..59359aec7 100644 --- a/src/systemd/src/libsystemd-network/sd-ipv4acd.c +++ b/src/systemd/src/libsystemd-network/sd-ipv4acd.c @@ -14,6 +14,7 @@ #include "alloc-util.h" #include "arp-util.h" #include "ether-addr-util.h" +#include "event-util.h" #include "fd-util.h" #include "in-addr-util.h" #include "list.h" @@ -89,7 +90,7 @@ static void ipv4acd_set_state(sd_ipv4acd *acd, IPv4ACDState st, bool reset_count static void ipv4acd_reset(sd_ipv4acd *acd) { assert(acd); - acd->timer_event_source = sd_event_source_unref(acd->timer_event_source); + (void) event_source_disable(acd->timer_event_source); acd->receive_message_event_source = sd_event_source_unref(acd->receive_message_event_source); acd->fd = safe_close(acd->fd); @@ -100,6 +101,8 @@ static void ipv4acd_reset(sd_ipv4acd *acd) { static sd_ipv4acd *ipv4acd_free(sd_ipv4acd *acd) { assert(acd); + acd->timer_event_source = sd_event_source_unref(acd->timer_event_source); + ipv4acd_reset(acd); sd_ipv4acd_detach_event(acd); @@ -113,14 +116,16 @@ int sd_ipv4acd_new(sd_ipv4acd **ret) { assert_return(ret, -EINVAL); - acd = new0(sd_ipv4acd, 1); + acd = new(sd_ipv4acd, 1); if (!acd) return -ENOMEM; - acd->n_ref = 1; - acd->state = IPV4ACD_STATE_INIT; - acd->ifindex = -1; - acd->fd = -1; + *acd = (sd_ipv4acd) { + .n_ref = 1, + .state = IPV4ACD_STATE_INIT, + .ifindex = -1, + .fd = -1, + }; *ret = TAKE_PTR(acd); @@ -151,9 +156,7 @@ int sd_ipv4acd_stop(sd_ipv4acd *acd) { static int ipv4acd_on_timeout(sd_event_source *s, uint64_t usec, void *userdata); static int ipv4acd_set_next_wakeup(sd_ipv4acd *acd, usec_t usec, usec_t random_usec) { - _cleanup_(sd_event_source_unrefp) sd_event_source *timer = NULL; usec_t next_timeout, time_now; - int r; assert(acd); @@ -164,20 +167,11 @@ static int ipv4acd_set_next_wakeup(sd_ipv4acd *acd, usec_t usec, usec_t random_u assert_se(sd_event_now(acd->event, clock_boottime_or_monotonic(), &time_now) >= 0); - r = sd_event_add_time(acd->event, &timer, clock_boottime_or_monotonic(), time_now + next_timeout, 0, ipv4acd_on_timeout, acd); - if (r < 0) - return r; - - r = sd_event_source_set_priority(timer, acd->event_priority); - if (r < 0) - return r; - - (void) sd_event_source_set_description(timer, "ipv4acd-timer"); - - sd_event_source_unref(acd->timer_event_source); - acd->timer_event_source = TAKE_PTR(timer); - - return 0; + return event_reset_time(acd->event, &acd->timer_event_source, + clock_boottime_or_monotonic(), + time_now + next_timeout, 0, + ipv4acd_on_timeout, acd, + acd->event_priority, "ipv4acd-timer", true); } static bool ipv4acd_arp_conflict(sd_ipv4acd *acd, struct ether_arp *arp) { diff --git a/src/systemd/src/libsystemd-network/sd-lldp.c b/src/systemd/src/libsystemd-network/sd-lldp.c index f72ef204b..4e3ee53cd 100644 --- a/src/systemd/src/libsystemd-network/sd-lldp.c +++ b/src/systemd/src/libsystemd-network/sd-lldp.c @@ -6,15 +6,26 @@ #include "sd-lldp.h" #include "alloc-util.h" +#include "ether-addr-util.h" +#include "event-util.h" #include "fd-util.h" #include "lldp-internal.h" #include "lldp-neighbor.h" #include "lldp-network.h" #include "socket-util.h" -#include "ether-addr-util.h" +#include "string-table.h" #define LLDP_DEFAULT_NEIGHBORS_MAX 128U +static const char * const lldp_event_table[_SD_LLDP_EVENT_MAX] = { + [SD_LLDP_EVENT_ADDED] = "added", + [SD_LLDP_EVENT_REMOVED] = "removed", + [SD_LLDP_EVENT_UPDATED] = "updated", + [SD_LLDP_EVENT_REFRESHED] = "refreshed", +}; + +DEFINE_STRING_TABLE_LOOKUP(lldp_event, sd_lldp_event); + static void lldp_flush_neighbors(sd_lldp *lldp) { sd_lldp_neighbor *n; @@ -26,12 +37,14 @@ static void lldp_flush_neighbors(sd_lldp *lldp) { static void lldp_callback(sd_lldp *lldp, sd_lldp_event event, sd_lldp_neighbor *n) { assert(lldp); + assert(event >= 0 && event < _SD_LLDP_EVENT_MAX); - log_lldp("Invoking callback for '%c'.", event); - - if (!lldp->callback) + if (!lldp->callback) { + log_lldp("Received '%s' event.", lldp_event_to_string(event)); return; + } + log_lldp("Invoking callback for '%s' event.", lldp_event_to_string(event)); lldp->callback(lldp, event, n, lldp->userdata); } @@ -223,7 +236,7 @@ static int lldp_receive_datagram(sd_event_source *s, int fd, uint32_t revents, v static void lldp_reset(sd_lldp *lldp) { assert(lldp); - lldp->timer_event_source = sd_event_source_unref(lldp->timer_event_source); + (void) event_source_disable(lldp->timer_event_source); lldp->io_event_source = sd_event_source_unref(lldp->io_event_source); lldp->fd = safe_close(lldp->fd); } @@ -332,6 +345,8 @@ _public_ int sd_lldp_set_ifindex(sd_lldp *lldp, int ifindex) { static sd_lldp* lldp_free(sd_lldp *lldp) { assert(lldp); + lldp->timer_event_source = sd_event_source_unref(lldp->timer_event_source); + lldp_reset(lldp); sd_lldp_detach_event(lldp); lldp_flush_neighbors(lldp); @@ -349,14 +364,16 @@ _public_ int sd_lldp_new(sd_lldp **ret) { assert_return(ret, -EINVAL); - lldp = new0(sd_lldp, 1); + lldp = new(sd_lldp, 1); if (!lldp) return -ENOMEM; - lldp->n_ref = 1; - lldp->fd = -1; - lldp->neighbors_max = LLDP_DEFAULT_NEIGHBORS_MAX; - lldp->capability_mask = (uint16_t) -1; + *lldp = (sd_lldp) { + .n_ref = 1, + .fd = -1, + .neighbors_max = LLDP_DEFAULT_NEIGHBORS_MAX, + .capability_mask = (uint16_t) -1, + }; lldp->neighbor_by_id = hashmap_new(&lldp_neighbor_id_hash_ops); if (!lldp->neighbor_by_id) @@ -392,7 +409,6 @@ static int on_timer_event(sd_event_source *s, uint64_t usec, void *userdata) { static int lldp_start_timer(sd_lldp *lldp, sd_lldp_neighbor *neighbor) { sd_lldp_neighbor *n; - int r; assert(lldp); @@ -400,35 +416,17 @@ static int lldp_start_timer(sd_lldp *lldp, sd_lldp_neighbor *neighbor) { lldp_neighbor_start_ttl(neighbor); n = prioq_peek(lldp->neighbor_by_expiry); - if (!n) { - - if (lldp->timer_event_source) - return sd_event_source_set_enabled(lldp->timer_event_source, SD_EVENT_OFF); - - return 0; - } - - if (lldp->timer_event_source) { - r = sd_event_source_set_time(lldp->timer_event_source, n->until); - if (r < 0) - return r; - - return sd_event_source_set_enabled(lldp->timer_event_source, SD_EVENT_ONESHOT); - } + if (!n) + return event_source_disable(lldp->timer_event_source); if (!lldp->event) return 0; - r = sd_event_add_time(lldp->event, &lldp->timer_event_source, clock_boottime_or_monotonic(), n->until, 0, on_timer_event, lldp); - if (r < 0) - return r; - - r = sd_event_source_set_priority(lldp->timer_event_source, lldp->event_priority); - if (r < 0) - return r; - - (void) sd_event_source_set_description(lldp->timer_event_source, "lldp-timer"); - return 0; + return event_reset_time(lldp->event, &lldp->timer_event_source, + clock_boottime_or_monotonic(), + n->until, 0, + on_timer_event, lldp, + lldp->event_priority, "lldp-timer", true); } _public_ int sd_lldp_get_neighbors(sd_lldp *lldp, sd_lldp_neighbor ***ret) { diff --git a/src/systemd/src/libsystemd/sd-event/event-util.c b/src/systemd/src/libsystemd/sd-event/event-util.c new file mode 100644 index 000000000..43e73d55e --- /dev/null +++ b/src/systemd/src/libsystemd/sd-event/event-util.c @@ -0,0 +1,99 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include <errno.h> + +#include "event-source.h" +#include "event-util.h" +#include "log.h" +#include "string-util.h" + +int event_reset_time( + sd_event *e, + sd_event_source **s, + clockid_t clock, + uint64_t usec, + uint64_t accuracy, + sd_event_time_handler_t callback, + void *userdata, + int64_t priority, + const char *description, + bool force_reset) { + + bool created = false; + int enabled, r; + clockid_t c; + + assert(e); + assert(s); + + if (*s) { + if (!force_reset) { + r = sd_event_source_get_enabled(*s, &enabled); + if (r < 0) + return log_debug_errno(r, "sd-event: Failed to query whether event source \"%s\" is enabled or not: %m", + strna((*s)->description ?: description)); + + if (enabled != SD_EVENT_OFF) + return 0; + } + + r = sd_event_source_get_time_clock(*s, &c); + if (r < 0) + return log_debug_errno(r, "sd-event: Failed to get clock id of event source \"%s\": %m", strna((*s)->description ?: description)); + + if (c != clock) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "sd-event: Current clock id %i of event source \"%s\" is different from specified one %i.", + (int)c, + strna((*s)->description ? : description), + (int)clock); + + r = sd_event_source_set_time(*s, usec); + if (r < 0) + return log_debug_errno(r, "sd-event: Failed to set time for event source \"%s\": %m", strna((*s)->description ?: description)); + + r = sd_event_source_set_time_accuracy(*s, accuracy); + if (r < 0) + return log_debug_errno(r, "sd-event: Failed to set accuracy for event source \"%s\": %m", strna((*s)->description ?: description)); + + /* callback function is not updated, as we do not have sd_event_source_set_time_callback(). */ + + (void) sd_event_source_set_userdata(*s, userdata); + + r = sd_event_source_set_enabled(*s, SD_EVENT_ONESHOT); + if (r < 0) + return log_debug_errno(r, "sd-event: Failed to enable event source \"%s\": %m", strna((*s)->description ?: description)); + } else { + r = sd_event_add_time(e, s, clock, usec, accuracy, callback, userdata); + if (r < 0) + return log_debug_errno(r, "sd-event: Failed to create timer event \"%s\": %m", strna(description)); + + created = true; + } + + r = sd_event_source_set_priority(*s, priority); + if (r < 0) + return log_debug_errno(r, "sd-event: Failed to set priority for event source \"%s\": %m", strna((*s)->description ?: description)); + + if (description) { + r = sd_event_source_set_description(*s, description); + if (r < 0) + return log_debug_errno(r, "sd-event: Failed to set description for event source \"%s\": %m", description); + } + + return created; +} + +int event_source_disable(sd_event_source *s) { + if (!s) + return 0; + + return sd_event_source_set_enabled(s, SD_EVENT_OFF); +} + +int event_source_is_enabled(sd_event_source *s) { + if (!s) + return false; + + return sd_event_source_get_enabled(s, NULL); +} diff --git a/src/systemd/src/libsystemd/sd-event/event-util.h b/src/systemd/src/libsystemd/sd-event/event-util.h new file mode 100644 index 000000000..00180955f --- /dev/null +++ b/src/systemd/src/libsystemd/sd-event/event-util.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include <stdbool.h> + +#include "sd-event.h" + +int event_reset_time(sd_event *e, sd_event_source **s, + clockid_t clock, uint64_t usec, uint64_t accuracy, + sd_event_time_handler_t callback, void *userdata, + int64_t priority, const char *description, bool force_reset); +int event_source_disable(sd_event_source *s); +int event_source_is_enabled(sd_event_source *s); diff --git a/src/systemd/src/libsystemd/sd-event/sd-event.c b/src/systemd/src/libsystemd/sd-event/sd-event.c index f44e6b4cc..f0c58a589 100644 --- a/src/systemd/src/libsystemd/sd-event/sd-event.c +++ b/src/systemd/src/libsystemd/sd-event/sd-event.c @@ -9,6 +9,7 @@ #include "sd-id128.h" #include "alloc-util.h" +#include "event-source.h" #include "fd-util.h" #include "fs-util.h" #include "hashmap.h" @@ -26,24 +27,6 @@ #define DEFAULT_ACCURACY_USEC (250 * USEC_PER_MSEC) -typedef enum EventSourceType { - SOURCE_IO, - SOURCE_TIME_REALTIME, - SOURCE_TIME_BOOTTIME, - SOURCE_TIME_MONOTONIC, - SOURCE_TIME_REALTIME_ALARM, - SOURCE_TIME_BOOTTIME_ALARM, - SOURCE_SIGNAL, - SOURCE_CHILD, - SOURCE_DEFER, - SOURCE_POST, - SOURCE_EXIT, - SOURCE_WATCHDOG, - SOURCE_INOTIFY, - _SOURCE_EVENT_SOURCE_TYPE_MAX, - _SOURCE_EVENT_SOURCE_TYPE_INVALID = -1 -} EventSourceType; - static const char* const event_source_type_table[_SOURCE_EVENT_SOURCE_TYPE_MAX] = { [SOURCE_IO] = "io", [SOURCE_TIME_REALTIME] = "realtime", @@ -62,183 +45,8 @@ static const char* const event_source_type_table[_SOURCE_EVENT_SOURCE_TYPE_MAX] DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(event_source_type, int); -/* All objects we use in epoll events start with this value, so that - * we know how to dispatch it */ -typedef enum WakeupType { - WAKEUP_NONE, - WAKEUP_EVENT_SOURCE, - WAKEUP_CLOCK_DATA, - WAKEUP_SIGNAL_DATA, - WAKEUP_INOTIFY_DATA, - _WAKEUP_TYPE_MAX, - _WAKEUP_TYPE_INVALID = -1, -} WakeupType; - #define EVENT_SOURCE_IS_TIME(t) IN_SET((t), SOURCE_TIME_REALTIME, SOURCE_TIME_BOOTTIME, SOURCE_TIME_MONOTONIC, SOURCE_TIME_REALTIME_ALARM, SOURCE_TIME_BOOTTIME_ALARM) -struct inode_data; - -struct sd_event_source { - WakeupType wakeup; - - unsigned n_ref; - - sd_event *event; - void *userdata; - sd_event_handler_t prepare; - - char *description; - - EventSourceType type:5; - signed int enabled:3; - bool pending:1; - bool dispatching:1; - bool floating:1; - - int64_t priority; - unsigned pending_index; - unsigned prepare_index; - uint64_t pending_iteration; - uint64_t prepare_iteration; - - sd_event_destroy_t destroy_callback; - - LIST_FIELDS(sd_event_source, sources); - - union { - struct { - sd_event_io_handler_t callback; - int fd; - uint32_t events; - uint32_t revents; - bool registered:1; - bool owned:1; - } io; - struct { - sd_event_time_handler_t callback; - usec_t next, accuracy; - unsigned earliest_index; - unsigned latest_index; - } time; - struct { - sd_event_signal_handler_t callback; - struct signalfd_siginfo siginfo; - int sig; - } signal; - struct { - sd_event_child_handler_t callback; - siginfo_t siginfo; - pid_t pid; - int options; - } child; - struct { - sd_event_handler_t callback; - } defer; - struct { - sd_event_handler_t callback; - } post; - struct { - sd_event_handler_t callback; - unsigned prioq_index; - } exit; - struct { - sd_event_inotify_handler_t callback; - uint32_t mask; - struct inode_data *inode_data; - LIST_FIELDS(sd_event_source, by_inode_data); - } inotify; - }; -}; - -struct clock_data { - WakeupType wakeup; - int fd; - - /* For all clocks we maintain two priority queues each, one - * ordered for the earliest times the events may be - * dispatched, and one ordered by the latest times they must - * have been dispatched. The range between the top entries in - * the two prioqs is the time window we can freely schedule - * wakeups in */ - - Prioq *earliest; - Prioq *latest; - usec_t next; - - bool needs_rearm:1; -}; - -struct signal_data { - WakeupType wakeup; - - /* For each priority we maintain one signal fd, so that we - * only have to dequeue a single event per priority at a - * time. */ - - int fd; - int64_t priority; - sigset_t sigset; - sd_event_source *current; -}; - -/* A structure listing all event sources currently watching a specific inode */ -struct inode_data { - /* The identifier for the inode, the combination of the .st_dev + .st_ino fields of the file */ - ino_t ino; - dev_t dev; - - /* An fd of the inode to watch. The fd is kept open until the next iteration of the loop, so that we can - * rearrange the priority still until then, as we need the original inode to change the priority as we need to - * add a watch descriptor to the right inotify for the priority which we can only do if we have a handle to the - * original inode. We keep a list of all inode_data objects with an open fd in the to_close list (see below) of - * the sd-event object, so that it is efficient to close everything, before entering the next event loop - * iteration. */ - int fd; - - /* The inotify "watch descriptor" */ - int wd; - - /* The combination of the mask of all inotify watches on this inode we manage. This is also the mask that has - * most recently been set on the watch descriptor. */ - uint32_t combined_mask; - - /* All event sources subscribed to this inode */ - LIST_HEAD(sd_event_source, event_sources); - - /* The inotify object we watch this inode with */ - struct inotify_data *inotify_data; - - /* A linked list of all inode data objects with fds to close (see above) */ - LIST_FIELDS(struct inode_data, to_close); -}; - -/* A structure encapsulating an inotify fd */ -struct inotify_data { - WakeupType wakeup; - - /* For each priority we maintain one inotify fd, so that we only have to dequeue a single event per priority at - * a time */ - - int fd; - int64_t priority; - - Hashmap *inodes; /* The inode_data structures keyed by dev+ino */ - Hashmap *wd; /* The inode_data structures keyed by the watch descriptor for each */ - - /* The buffer we read inotify events into */ - union inotify_event_buffer buffer; - size_t buffer_filled; /* fill level of the buffer */ - - /* How many event sources are currently marked pending for this inotify. We won't read new events off the - * inotify fd as long as there are still pending events on the inotify (because we have no strategy of queuing - * the events locally if they can't be coalesced). */ - unsigned n_pending; - - /* A linked list of all inotify objects with data already read, that still need processing. We keep this list - * to make it efficient to figure out what inotify objects to process data on next. */ - LIST_FIELDS(struct inotify_data, buffered); -}; - struct sd_event { unsigned n_ref; @@ -1887,9 +1695,11 @@ _public_ int sd_event_source_set_description(sd_event_source *s, const char *des _public_ int sd_event_source_get_description(sd_event_source *s, const char **description) { assert_return(s, -EINVAL); assert_return(description, -EINVAL); - assert_return(s->description, -ENXIO); assert_return(!event_pid_changed(s->event), -ECHILD); + if (!s->description) + return -ENXIO; + *description = s->description; return 0; } @@ -2141,11 +1951,11 @@ fail: _public_ int sd_event_source_get_enabled(sd_event_source *s, int *m) { assert_return(s, -EINVAL); - assert_return(m, -EINVAL); assert_return(!event_pid_changed(s->event), -ECHILD); - *m = s->enabled; - return 0; + if (m) + *m = s->enabled; + return s->enabled != SD_EVENT_OFF; } _public_ int sd_event_source_set_enabled(sd_event_source *s, int m) { @@ -3702,3 +3512,31 @@ _public_ int sd_event_source_get_destroy_callback(sd_event_source *s, sd_event_d return !!s->destroy_callback; } + +_public_ int sd_event_source_get_floating(sd_event_source *s) { + assert_return(s, -EINVAL); + + return s->floating; +} + +_public_ int sd_event_source_set_floating(sd_event_source *s, int b) { + assert_return(s, -EINVAL); + + if (s->floating == !!b) + return 0; + + if (!s->event) /* Already disconnected */ + return -ESTALE; + + s->floating = b; + + if (b) { + sd_event_source_ref(s); + sd_event_unref(s->event); + } else { + sd_event_ref(s->event); + sd_event_source_unref(s); + } + + return 1; +} diff --git a/src/systemd/src/libsystemd/sd-id128/sd-id128.c b/src/systemd/src/libsystemd/sd-id128/sd-id128.c index b7cca832d..3593a71c0 100644 --- a/src/systemd/src/libsystemd/sd-id128/sd-id128.c +++ b/src/systemd/src/libsystemd/sd-id128/sd-id128.c @@ -272,7 +272,9 @@ _public_ int sd_id128_randomize(sd_id128_t *ret) { assert_return(ret, -EINVAL); - r = acquire_random_bytes(&t, sizeof t, true); + /* We allow usage if x86-64 RDRAND here. It might not be trusted enough for keeping secrets, but it should be + * fine for UUIDS. */ + r = genuine_random_bytes(&t, sizeof t, RANDOM_ALLOW_RDRAND); if (r < 0) return r; diff --git a/src/systemd/src/systemd/_sd-common.h b/src/systemd/src/systemd/_sd-common.h index 4742b2e74..b026b5c55 100644 --- a/src/systemd/src/systemd/_sd-common.h +++ b/src/systemd/src/systemd/_sd-common.h @@ -25,22 +25,22 @@ #ifndef _sd_printf_ # if __GNUC__ >= 4 -# define _sd_printf_(a,b) __attribute__ ((format (printf, a, b))) +# define _sd_printf_(a,b) __attribute__ ((__format__(printf, a, b))) # else # define _sd_printf_(a,b) # endif #endif #ifndef _sd_sentinel_ -# define _sd_sentinel_ __attribute__((sentinel)) +# define _sd_sentinel_ __attribute__((__sentinel__)) #endif #ifndef _sd_packed_ -# define _sd_packed_ __attribute__((packed)) +# define _sd_packed_ __attribute__((__packed__)) #endif #ifndef _sd_pure_ -# define _sd_pure_ __attribute__((pure)) +# define _sd_pure_ __attribute__((__pure__)) #endif #ifndef _SD_STRINGIFY diff --git a/src/systemd/src/systemd/sd-event.h b/src/systemd/src/systemd/sd-event.h index c38eb84be..b15cade20 100644 --- a/src/systemd/src/systemd/sd-event.h +++ b/src/systemd/src/systemd/sd-event.h @@ -143,6 +143,8 @@ int sd_event_source_get_child_pid(sd_event_source *s, pid_t *pid); int sd_event_source_get_inotify_mask(sd_event_source *s, uint32_t *ret); int sd_event_source_set_destroy_callback(sd_event_source *s, sd_event_destroy_t callback); int sd_event_source_get_destroy_callback(sd_event_source *s, sd_event_destroy_t *ret); +int sd_event_source_get_floating(sd_event_source *s); +int sd_event_source_set_floating(sd_event_source *s, int b); /* Define helpers so that __attribute__((cleanup(sd_event_unrefp))) and similar may be used. */ _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_event, sd_event_unref); diff --git a/src/systemd/src/systemd/sd-lldp.h b/src/systemd/src/systemd/sd-lldp.h index d650794cc..a3e5cd6be 100644 --- a/src/systemd/src/systemd/sd-lldp.h +++ b/src/systemd/src/systemd/sd-lldp.h @@ -109,10 +109,12 @@ typedef struct sd_lldp sd_lldp; typedef struct sd_lldp_neighbor sd_lldp_neighbor; typedef enum sd_lldp_event { - SD_LLDP_EVENT_ADDED = 'a', - SD_LLDP_EVENT_REMOVED = 'r', - SD_LLDP_EVENT_UPDATED = 'u', - SD_LLDP_EVENT_REFRESHED = 'f', + SD_LLDP_EVENT_ADDED, + SD_LLDP_EVENT_REMOVED, + SD_LLDP_EVENT_UPDATED, + SD_LLDP_EVENT_REFRESHED, + _SD_LLDP_EVENT_MAX, + _SD_LLDP_EVENT_INVALID = -1, } sd_lldp_event; typedef void (*sd_lldp_callback_t)(sd_lldp *lldp, sd_lldp_event event, sd_lldp_neighbor *n, void *userdata); diff --git a/src/systemd/src/systemd/sd-ndisc.h b/src/systemd/src/systemd/sd-ndisc.h index 6b6249ca0..d1bee343a 100644 --- a/src/systemd/src/systemd/sd-ndisc.h +++ b/src/systemd/src/systemd/sd-ndisc.h @@ -55,8 +55,10 @@ typedef struct sd_ndisc sd_ndisc; typedef struct sd_ndisc_router sd_ndisc_router; typedef enum sd_ndisc_event { - SD_NDISC_EVENT_TIMEOUT = 't', - SD_NDISC_EVENT_ROUTER = 'r', + SD_NDISC_EVENT_TIMEOUT, + SD_NDISC_EVENT_ROUTER, + _SD_NDISC_EVENT_MAX, + _SD_NDISC_EVENT_INVALID = -1, } sd_ndisc_event; typedef void (*sd_ndisc_callback_t)(sd_ndisc *nd, sd_ndisc_event event, sd_ndisc_router *rt, void *userdata); |