From f61a12ee200de63360b23d3f6c3dad2243e4fb69 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 14 May 2019 14:19:41 +0200 Subject: [PATCH] systemd: update code from upstream (2019-05-14) This is a direct dump from systemd git. ====== SYSTEMD_DIR=../systemd COMMIT=b6ec9afd44934a599a761e8c741077a7512e0c82 ( cd "$SYSTEMD_DIR" git checkout "$COMMIT" git reset --hard git clean -fdx ) git ls-files -z :/src/systemd/src/ \ :/shared/systemd/src/ \ :/shared/nm-utils/unaligned.h | \ xargs -0 rm -f nm_copy_sd_shared() { mkdir -p "./shared/systemd/$(dirname "$1")" cp "$SYSTEMD_DIR/$1" "./shared/systemd/$1" } nm_copy_sd_core() { mkdir -p "./src/systemd/$(dirname "$1")" cp "$SYSTEMD_DIR/$1" "./src/systemd/$1" } nm_copy_sd_nmutils() { mkdir -p "./shared/nm-utils/" cp "$SYSTEMD_DIR/$1" "./shared/nm-utils/${1##*/}" } nm_copy_sd_core "src/libsystemd-network/arp-util.c" nm_copy_sd_core "src/libsystemd-network/arp-util.h" nm_copy_sd_core "src/libsystemd-network/dhcp-identifier.c" nm_copy_sd_core "src/libsystemd-network/dhcp-identifier.h" nm_copy_sd_core "src/libsystemd-network/dhcp-internal.h" nm_copy_sd_core "src/libsystemd-network/dhcp-lease-internal.h" nm_copy_sd_core "src/libsystemd-network/dhcp-network.c" nm_copy_sd_core "src/libsystemd-network/dhcp-option.c" nm_copy_sd_core "src/libsystemd-network/dhcp-packet.c" nm_copy_sd_core "src/libsystemd-network/dhcp-protocol.h" nm_copy_sd_core "src/libsystemd-network/dhcp6-internal.h" nm_copy_sd_core "src/libsystemd-network/dhcp6-lease-internal.h" nm_copy_sd_core "src/libsystemd-network/dhcp6-network.c" nm_copy_sd_core "src/libsystemd-network/dhcp6-option.c" nm_copy_sd_core "src/libsystemd-network/dhcp6-protocol.h" nm_copy_sd_core "src/libsystemd-network/lldp-internal.h" nm_copy_sd_core "src/libsystemd-network/lldp-neighbor.c" nm_copy_sd_core "src/libsystemd-network/lldp-neighbor.h" nm_copy_sd_core "src/libsystemd-network/lldp-network.c" nm_copy_sd_core "src/libsystemd-network/lldp-network.h" nm_copy_sd_core "src/libsystemd-network/network-internal.c" nm_copy_sd_core "src/libsystemd-network/network-internal.h" nm_copy_sd_core "src/libsystemd-network/sd-dhcp-client.c" nm_copy_sd_core "src/libsystemd-network/sd-dhcp-lease.c" nm_copy_sd_core "src/libsystemd-network/sd-dhcp6-client.c" nm_copy_sd_core "src/libsystemd-network/sd-dhcp6-lease.c" nm_copy_sd_core "src/libsystemd-network/sd-ipv4acd.c" nm_copy_sd_core "src/libsystemd-network/sd-ipv4ll.c" nm_copy_sd_core "src/libsystemd-network/sd-lldp.c" nm_copy_sd_core "src/libsystemd/sd-event/event-source.h" nm_copy_sd_core "src/libsystemd/sd-event/event-util.c" nm_copy_sd_core "src/libsystemd/sd-event/event-util.h" nm_copy_sd_core "src/libsystemd/sd-event/sd-event.c" nm_copy_sd_core "src/libsystemd/sd-id128/id128-util.c" nm_copy_sd_core "src/libsystemd/sd-id128/id128-util.h" nm_copy_sd_core "src/libsystemd/sd-id128/sd-id128.c" nm_copy_sd_core "src/shared/dns-domain.c" nm_copy_sd_core "src/shared/dns-domain.h" nm_copy_sd_core "src/systemd/_sd-common.h" nm_copy_sd_core "src/systemd/sd-dhcp-client.h" nm_copy_sd_core "src/systemd/sd-dhcp-lease.h" nm_copy_sd_core "src/systemd/sd-dhcp6-client.h" nm_copy_sd_core "src/systemd/sd-dhcp6-lease.h" nm_copy_sd_core "src/systemd/sd-event.h" nm_copy_sd_core "src/systemd/sd-id128.h" nm_copy_sd_core "src/systemd/sd-ipv4acd.h" nm_copy_sd_core "src/systemd/sd-ipv4ll.h" nm_copy_sd_core "src/systemd/sd-lldp.h" nm_copy_sd_core "src/systemd/sd-ndisc.h" nm_copy_sd_nmutils "src/basic/unaligned.h" nm_copy_sd_shared "src/basic/alloc-util.c" nm_copy_sd_shared "src/basic/alloc-util.h" nm_copy_sd_shared "src/basic/async.h" nm_copy_sd_shared "src/basic/env-file.c" nm_copy_sd_shared "src/basic/env-file.h" nm_copy_sd_shared "src/basic/env-util.c" nm_copy_sd_shared "src/basic/env-util.h" nm_copy_sd_shared "src/basic/errno-util.h" nm_copy_sd_shared "src/basic/escape.c" nm_copy_sd_shared "src/basic/escape.h" nm_copy_sd_shared "src/basic/ether-addr-util.c" nm_copy_sd_shared "src/basic/ether-addr-util.h" nm_copy_sd_shared "src/basic/extract-word.c" nm_copy_sd_shared "src/basic/extract-word.h" nm_copy_sd_shared "src/basic/fd-util.c" nm_copy_sd_shared "src/basic/fd-util.h" nm_copy_sd_shared "src/basic/fileio.c" nm_copy_sd_shared "src/basic/fileio.h" nm_copy_sd_shared "src/basic/fs-util.c" nm_copy_sd_shared "src/basic/fs-util.h" nm_copy_sd_shared "src/basic/hash-funcs.c" nm_copy_sd_shared "src/basic/hash-funcs.h" nm_copy_sd_shared "src/basic/hashmap.c" nm_copy_sd_shared "src/basic/hashmap.h" nm_copy_sd_shared "src/basic/hexdecoct.c" nm_copy_sd_shared "src/basic/hexdecoct.h" nm_copy_sd_shared "src/basic/hostname-util.c" nm_copy_sd_shared "src/basic/hostname-util.h" nm_copy_sd_shared "src/basic/in-addr-util.c" nm_copy_sd_shared "src/basic/in-addr-util.h" nm_copy_sd_shared "src/basic/io-util.c" nm_copy_sd_shared "src/basic/io-util.h" nm_copy_sd_shared "src/basic/list.h" nm_copy_sd_shared "src/basic/log.h" nm_copy_sd_shared "src/basic/macro.h" nm_copy_sd_shared "src/basic/memory-util.c" nm_copy_sd_shared "src/basic/memory-util.h" nm_copy_sd_shared "src/basic/mempool.c" nm_copy_sd_shared "src/basic/mempool.h" nm_copy_sd_shared "src/basic/missing_fcntl.h" nm_copy_sd_shared "src/basic/missing_socket.h" nm_copy_sd_shared "src/basic/missing_stat.h" nm_copy_sd_shared "src/basic/missing_type.h" nm_copy_sd_shared "src/basic/parse-util.c" nm_copy_sd_shared "src/basic/parse-util.h" nm_copy_sd_shared "src/basic/path-util.c" nm_copy_sd_shared "src/basic/path-util.h" nm_copy_sd_shared "src/basic/prioq.c" nm_copy_sd_shared "src/basic/prioq.h" nm_copy_sd_shared "src/basic/process-util.c" nm_copy_sd_shared "src/basic/process-util.h" nm_copy_sd_shared "src/basic/random-util.c" nm_copy_sd_shared "src/basic/random-util.h" nm_copy_sd_shared "src/basic/set.h" nm_copy_sd_shared "src/basic/signal-util.h" nm_copy_sd_shared "src/basic/siphash24.h" nm_copy_sd_shared "src/basic/socket-util.c" nm_copy_sd_shared "src/basic/socket-util.h" nm_copy_sd_shared "src/basic/sort-util.h" nm_copy_sd_shared "src/basic/sparse-endian.h" nm_copy_sd_shared "src/basic/stat-util.c" nm_copy_sd_shared "src/basic/stat-util.h" nm_copy_sd_shared "src/basic/stdio-util.h" nm_copy_sd_shared "src/basic/string-table.c" nm_copy_sd_shared "src/basic/string-table.h" nm_copy_sd_shared "src/basic/string-util.c" nm_copy_sd_shared "src/basic/string-util.h" nm_copy_sd_shared "src/basic/strv.c" nm_copy_sd_shared "src/basic/strv.h" nm_copy_sd_shared "src/basic/time-util.c" nm_copy_sd_shared "src/basic/time-util.h" nm_copy_sd_shared "src/basic/tmpfile-util.c" nm_copy_sd_shared "src/basic/tmpfile-util.h" nm_copy_sd_shared "src/basic/umask-util.h" nm_copy_sd_shared "src/basic/utf8.c" nm_copy_sd_shared "src/basic/utf8.h" nm_copy_sd_shared "src/basic/util.c" nm_copy_sd_shared "src/basic/util.h" --- shared/systemd/src/basic/alloc-util.c | 25 ++++- shared/systemd/src/basic/env-file.c | 3 - shared/systemd/src/basic/fd-util.c | 2 +- shared/systemd/src/basic/fileio.c | 98 ++++++++++++----- shared/systemd/src/basic/fileio.h | 6 + shared/systemd/src/basic/hexdecoct.c | 25 ++++- shared/systemd/src/basic/hexdecoct.h | 5 +- shared/systemd/src/basic/macro.h | 9 ++ shared/systemd/src/basic/process-util.c | 57 ++++------ shared/systemd/src/basic/random-util.c | 84 +++++++++----- shared/systemd/src/basic/random-util.h | 4 +- shared/systemd/src/basic/socket-util.c | 27 ++++- shared/systemd/src/basic/string-util.c | 16 +-- shared/systemd/src/basic/string-util.h | 6 + shared/systemd/src/basic/tmpfile-util.c | 13 ++- shared/systemd/src/basic/umask-util.h | 20 ++-- src/systemd/src/libsystemd-network/arp-util.h | 2 +- .../src/libsystemd-network/network-internal.c | 2 +- .../src/libsystemd-network/sd-dhcp-client.c | 103 ++++++++++++++---- .../src/libsystemd-network/sd-dhcp-lease.c | 2 - .../src/libsystemd/sd-event/sd-event.c | 8 +- src/systemd/src/shared/dns-domain.c | 2 +- src/systemd/src/systemd/sd-dhcp-client.h | 7 +- src/systemd/src/systemd/sd-event.h | 2 + 24 files changed, 363 insertions(+), 165 deletions(-) diff --git a/shared/systemd/src/basic/alloc-util.c b/shared/systemd/src/basic/alloc-util.c index 1e4ee722f2..a16db6824f 100644 --- a/shared/systemd/src/basic/alloc-util.c +++ b/shared/systemd/src/basic/alloc-util.c @@ -64,8 +64,31 @@ void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size) { if (!q) return NULL; + if (size > 0) { + size_t bn; + + /* Adjust for the 64 byte minimum */ + newalloc = a / size; + + bn = malloc_usable_size(q) / size; + if (bn > newalloc) { + void *qq; + + /* The actual size allocated is larger than what we asked for. Let's call realloc() again to + * take possession of the extra space. This should be cheap, since libc doesn't have to move + * the memory for this. */ + + qq = realloc(q, bn * size); + if (_likely_(qq)) { + *p = qq; + *allocated = bn; + return qq; + } + } + } + *p = q; - *allocated = _unlikely_(size == 0) ? newalloc : malloc_usable_size(q) / size; + *allocated = newalloc; return q; } diff --git a/shared/systemd/src/basic/env-file.c b/shared/systemd/src/basic/env-file.c index a1f1308a54..83767b0a24 100644 --- a/shared/systemd/src/basic/env-file.c +++ b/shared/systemd/src/basic/env-file.c @@ -1,7 +1,5 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -#include - #include "alloc-util.h" #include "env-file.h" #include "env-util.h" @@ -545,7 +543,6 @@ int write_env_file(const char *fname, char **l) { if (r < 0) return r; - (void) __fsetlocking(f, FSETLOCKING_BYCALLER); (void) fchmod_umask(fileno(f), 0644); STRV_FOREACH(i, l) diff --git a/shared/systemd/src/basic/fd-util.c b/shared/systemd/src/basic/fd-util.c index b3b840145f..e571f6616e 100644 --- a/shared/systemd/src/basic/fd-util.c +++ b/shared/systemd/src/basic/fd-util.c @@ -387,7 +387,7 @@ int fd_get_path(int fd, char **ret) { r = readlink_malloc(procfs_path, ret); if (r == -ENOENT) { /* ENOENT can mean two things: that the fd does not exist or that /proc is not mounted. Let's make - * things debuggable and distuingish the two. */ + * things debuggable and distinguish the two. */ if (access("/proc/self/fd/", F_OK) < 0) /* /proc is not available or not set up properly, we're most likely in some chroot diff --git a/shared/systemd/src/basic/fileio.c b/shared/systemd/src/basic/fileio.c index 9ab2f501c7..16034fb9e8 100644 --- a/shared/systemd/src/basic/fileio.c +++ b/shared/systemd/src/basic/fileio.c @@ -29,6 +29,52 @@ #define READ_FULL_BYTES_MAX (4U*1024U*1024U) +int fopen_unlocked(const char *path, const char *options, FILE **ret) { + assert(ret); + + FILE *f = fopen(path, options); + if (!f) + return -errno; + + (void) __fsetlocking(f, FSETLOCKING_BYCALLER); + + *ret = f; + return 0; +} + +int fdopen_unlocked(int fd, const char *options, FILE **ret) { + assert(ret); + + FILE *f = fdopen(fd, options); + if (!f) + return -errno; + + (void) __fsetlocking(f, FSETLOCKING_BYCALLER); + + *ret = f; + return 0; +} + +FILE* open_memstream_unlocked(char **ptr, size_t *sizeloc) { + FILE *f = open_memstream(ptr, sizeloc); + if (!f) + return NULL; + + (void) __fsetlocking(f, FSETLOCKING_BYCALLER); + + return f; +} + +FILE* fmemopen_unlocked(void *buf, size_t size, const char *mode) { + FILE *f = fmemopen(buf, size, mode); + if (!f) + return NULL; + + (void) __fsetlocking(f, FSETLOCKING_BYCALLER); + + return f; +} + int write_string_stream_ts( FILE *f, const char *line, @@ -95,7 +141,6 @@ static int write_string_file_atomic( if (r < 0) return r; - (void) __fsetlocking(f, FSETLOCKING_BYCALLER); (void) fchmod_umask(fileno(f), 0644); r = write_string_stream_ts(f, line, flags, ts); @@ -141,11 +186,9 @@ int write_string_file_ts( assert(!ts); if (flags & WRITE_STRING_FILE_CREATE) { - f = fopen(fn, "we"); - if (!f) { - r = -errno; + r = fopen_unlocked(fn, "we", &f); + if (r < 0) goto fail; - } } else { int fd; @@ -157,16 +200,13 @@ int write_string_file_ts( goto fail; } - f = fdopen(fd, "w"); - if (!f) { - r = -errno; + r = fdopen_unlocked(fd, "w", &f); + if (r < 0) { safe_close(fd); goto fail; } } - (void) __fsetlocking(f, FSETLOCKING_BYCALLER); - if (flags & WRITE_STRING_FILE_DISABLE_BUFFER) setvbuf(f, NULL, _IONBF, 0); @@ -213,15 +253,14 @@ int write_string_filef( int read_one_line_file(const char *fn, char **line) { _cleanup_fclose_ FILE *f = NULL; + int r; assert(fn); assert(line); - f = fopen(fn, "re"); - if (!f) - return -errno; - - (void) __fsetlocking(f, FSETLOCKING_BYCALLER); + r = fopen_unlocked(fn, "re", &f); + if (r < 0) + return r; return read_line(f, LONG_LINE_MAX, line); } @@ -230,6 +269,7 @@ int verify_file(const char *fn, const char *blob, bool accept_extra_nl) { _cleanup_fclose_ FILE *f = NULL; _cleanup_free_ char *buf = NULL; size_t l, k; + int r; assert(fn); assert(blob); @@ -243,11 +283,9 @@ int verify_file(const char *fn, const char *blob, bool accept_extra_nl) { if (!buf) return -ENOMEM; - f = fopen(fn, "re"); - if (!f) - return -errno; - - (void) __fsetlocking(f, FSETLOCKING_BYCALLER); + r = fopen_unlocked(fn, "re", &f); + if (r < 0) + return r; /* We try to read one byte more than we need, so that we know whether we hit eof */ errno = 0; @@ -279,7 +317,8 @@ int read_full_stream_full( assert(f); assert(ret_contents); - assert(!(flags & READ_FULL_FILE_UNBASE64) || ret_size); + assert(!FLAGS_SET(flags, READ_FULL_FILE_UNBASE64 | READ_FULL_FILE_UNHEX)); + assert(!(flags & (READ_FULL_FILE_UNBASE64 | READ_FULL_FILE_UNHEX)) || ret_size); n_next = LINE_MAX; /* Start size */ @@ -320,6 +359,7 @@ int read_full_stream_full( } memcpy_safe(t, buf, n); explicit_bzero_safe(buf, n); + buf = mfree(buf); } else { t = realloc(buf, n_next + 1); if (!t) @@ -356,9 +396,12 @@ int read_full_stream_full( n_next = MIN(n * 2, READ_FULL_BYTES_MAX); } - if (flags & READ_FULL_FILE_UNBASE64) { + if (flags & (READ_FULL_FILE_UNBASE64 | READ_FULL_FILE_UNHEX)) { buf[l++] = 0; - r = unbase64mem_full(buf, l, flags & READ_FULL_FILE_SECURE, (void **) ret_contents, ret_size); + if (flags & READ_FULL_FILE_UNBASE64) + r = unbase64mem_full(buf, l, flags & READ_FULL_FILE_SECURE, (void **) ret_contents, ret_size); + else + r = unhexmem_full(buf, l, flags & READ_FULL_FILE_SECURE, (void **) ret_contents, ret_size); goto finalize; } @@ -390,15 +433,14 @@ finalize: int read_full_file_full(const char *filename, ReadFullFileFlags flags, char **contents, size_t *size) { _cleanup_fclose_ FILE *f = NULL; + int r; assert(filename); assert(contents); - f = fopen(filename, "re"); - if (!f) - return -errno; - - (void) __fsetlocking(f, FSETLOCKING_BYCALLER); + r = fopen_unlocked(filename, "re", &f); + if (r < 0) + return r; return read_full_stream_full(f, filename, flags, contents, size); } diff --git a/shared/systemd/src/basic/fileio.h b/shared/systemd/src/basic/fileio.h index 760e738688..eb551c7ac1 100644 --- a/shared/systemd/src/basic/fileio.h +++ b/shared/systemd/src/basic/fileio.h @@ -31,8 +31,14 @@ typedef enum { typedef enum { READ_FULL_FILE_SECURE = 1 << 0, READ_FULL_FILE_UNBASE64 = 1 << 1, + READ_FULL_FILE_UNHEX = 1 << 2, } ReadFullFileFlags; +int fopen_unlocked(const char *path, const char *options, FILE **ret); +int fdopen_unlocked(int fd, const char *options, FILE **ret); +FILE* open_memstream_unlocked(char **ptr, size_t *sizeloc); +FILE* fmemopen_unlocked(void *buf, size_t size, const char *mode); + int write_string_stream_ts(FILE *f, const char *line, WriteStringFileFlags flags, struct timespec *ts); static inline int write_string_stream(FILE *f, const char *line, WriteStringFileFlags flags) { return write_string_stream_ts(f, line, flags, NULL); diff --git a/shared/systemd/src/basic/hexdecoct.c b/shared/systemd/src/basic/hexdecoct.c index 132439fd1c..5e425b0231 100644 --- a/shared/systemd/src/basic/hexdecoct.c +++ b/shared/systemd/src/basic/hexdecoct.c @@ -108,10 +108,12 @@ static int unhex_next(const char **p, size_t *l) { return r; } -int unhexmem(const char *p, size_t l, void **ret, size_t *ret_len) { +int unhexmem_full(const char *p, size_t l, bool secure, void **ret, size_t *ret_len) { _cleanup_free_ uint8_t *buf = NULL; + size_t buf_size; const char *x; uint8_t *z; + int r; assert(ret); assert(ret_len); @@ -121,7 +123,8 @@ int unhexmem(const char *p, size_t l, void **ret, size_t *ret_len) { l = strlen(p); /* Note that the calculation of memory size is an upper boundary, as we ignore whitespace while decoding */ - buf = malloc((l + 1) / 2 + 1); + buf_size = (l + 1) / 2 + 1; + buf = malloc(buf_size); if (!buf) return -ENOMEM; @@ -131,12 +134,16 @@ int unhexmem(const char *p, size_t l, void **ret, size_t *ret_len) { a = unhex_next(&x, &l); if (a == -EPIPE) /* End of string */ break; - if (a < 0) - return a; + if (a < 0) { + r = a; + goto on_failure; + } b = unhex_next(&x, &l); - if (b < 0) - return b; + if (b < 0) { + r = b; + goto on_failure; + } *(z++) = (uint8_t) a << 4 | (uint8_t) b; } @@ -147,6 +154,12 @@ int unhexmem(const char *p, size_t l, void **ret, size_t *ret_len) { *ret = TAKE_PTR(buf); return 0; + +on_failure: + if (secure) + explicit_bzero_safe(buf, buf_size); + + return r; } /* https://tools.ietf.org/html/rfc4648#section-6 diff --git a/shared/systemd/src/basic/hexdecoct.h b/shared/systemd/src/basic/hexdecoct.h index fa6013ee75..dfdff1e9bb 100644 --- a/shared/systemd/src/basic/hexdecoct.h +++ b/shared/systemd/src/basic/hexdecoct.h @@ -18,7 +18,10 @@ char hexchar(int x) _const_; int unhexchar(char c) _const_; char *hexmem(const void *p, size_t l); -int unhexmem(const char *p, size_t l, void **mem, size_t *len); +int unhexmem_full(const char *p, size_t l, bool secure, void **mem, size_t *len); +static inline int unhexmem(const char *p, size_t l, void **mem, size_t *len) { + return unhexmem_full(p, l, false, mem, len); +} char base32hexchar(int x) _const_; int unbase32hexchar(char c) _const_; diff --git a/shared/systemd/src/basic/macro.h b/shared/systemd/src/basic/macro.h index 1971e912db..ae8907db04 100644 --- a/shared/systemd/src/basic/macro.h +++ b/shared/systemd/src/basic/macro.h @@ -105,6 +105,15 @@ _Pragma("GCC diagnostic push"); \ _Pragma("GCC diagnostic ignored \"-Wincompatible-pointer-types\"") +#if HAVE_WSTRINGOP_TRUNCATION +# define DISABLE_WARNING_STRINGOP_TRUNCATION \ + _Pragma("GCC diagnostic push"); \ + _Pragma("GCC diagnostic ignored \"-Wstringop-truncation\"") +#else +# define DISABLE_WARNING_STRINGOP_TRUNCATION \ + _Pragma("GCC diagnostic push") +#endif + #define REENABLE_WARNING \ _Pragma("GCC diagnostic pop") diff --git a/shared/systemd/src/basic/process-util.c b/shared/systemd/src/basic/process-util.c index f773eeaffd..3dc3534e1a 100644 --- a/shared/systemd/src/basic/process-util.c +++ b/shared/systemd/src/basic/process-util.c @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include @@ -106,7 +105,7 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char * char *k; _cleanup_free_ char *ans = NULL; const char *p; - int c; + int c, r; assert(line); assert(pid >= 0); @@ -121,15 +120,11 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char * * comm_fallback is false). Returns 0 and sets *line otherwise. */ p = procfs_file_alloca(pid, "cmdline"); - - f = fopen(p, "re"); - if (!f) { - if (errno == ENOENT) - return -ESRCH; - return -errno; - } - - (void) __fsetlocking(f, FSETLOCKING_BYCALLER); + r = fopen_unlocked(p, "re", &f); + if (r == -ENOENT) + return -ESRCH; + if (r < 0) + return r; if (max_length == 0) { /* This is supposed to be a safety guard against runaway command lines. */ @@ -513,14 +508,11 @@ static int get_process_id(pid_t pid, const char *field, uid_t *uid) { return -EINVAL; p = procfs_file_alloca(pid, "status"); - f = fopen(p, "re"); - if (!f) { - if (errno == ENOENT) - return -ESRCH; - return -errno; - } - - (void) __fsetlocking(f, FSETLOCKING_BYCALLER); + r = fopen_unlocked(p, "re", &f); + if (r == -ENOENT) + return -ESRCH; + if (r < 0) + return r; for (;;) { _cleanup_free_ char *line = NULL; @@ -602,14 +594,11 @@ int get_process_environ(pid_t pid, char **env) { p = procfs_file_alloca(pid, "environ"); - f = fopen(p, "re"); - if (!f) { - if (errno == ENOENT) - return -ESRCH; - return -errno; - } - - (void) __fsetlocking(f, FSETLOCKING_BYCALLER); + r = fopen_unlocked(p, "re", &f); + if (r == -ENOENT) + return -ESRCH; + if (r < 0) + return r; for (;;) { char c; @@ -895,15 +884,11 @@ int getenv_for_pid(pid_t pid, const char *field, char **ret) { path = procfs_file_alloca(pid, "environ"); - f = fopen(path, "re"); - if (!f) { - if (errno == ENOENT) - return -ESRCH; - - return -errno; - } - - (void) __fsetlocking(f, FSETLOCKING_BYCALLER); + r = fopen_unlocked(path, "re", &f); + if (r == -ENOENT) + return -ESRCH; + if (r < 0) + return r; l = strlen(field); for (;;) { diff --git a/shared/systemd/src/basic/random-util.c b/shared/systemd/src/basic/random-util.c index ca25fd2420..0561f0cb22 100644 --- a/shared/systemd/src/basic/random-util.c +++ b/shared/systemd/src/basic/random-util.c @@ -28,13 +28,15 @@ #include "io-util.h" #include "missing.h" #include "random-util.h" +#include "siphash24.h" #include "time-util.h" int rdrand(unsigned long *ret) { #if defined(__i386__) || defined(__x86_64__) static int have_rdrand = -1; - unsigned char err; + unsigned long v; + uint8_t success; if (have_rdrand < 0) { uint32_t eax, ebx, ecx, edx; @@ -45,7 +47,12 @@ int rdrand(unsigned long *ret) { return -EOPNOTSUPP; } - have_rdrand = !!(ecx & (1U << 30)); +/* Compat with old gcc where bit_RDRND didn't exist yet */ +#ifndef bit_RDRND +#define bit_RDRND (1U << 30) +#endif + + have_rdrand = !!(ecx & bit_RDRND); } if (have_rdrand == 0) @@ -53,12 +60,24 @@ int rdrand(unsigned long *ret) { asm volatile("rdrand %0;" "setc %1" - : "=r" (*ret), - "=qm" (err)); - msan_unpoison(&err, sizeof(err)); - if (!err) + : "=r" (v), + "=qm" (success)); + msan_unpoison(&success, sizeof(success)); + if (!success) return -EAGAIN; + /* Apparently on some AMD CPUs RDRAND will sometimes (after a suspend/resume cycle?) report success + * via the carry flag but nonetheless return the same fixed value -1 in all cases. This appears to be + * a bad bug in the CPU or firmware. Let's deal with that and work-around this by explicitly checking + * for this special value (and also 0, just to be sure) and filtering it out. This is a work-around + * only however and something AMD really should fix properly. The Linux kernel should probably work + * around this issue by turning off RDRAND altogether on those CPUs. See: + * https://github.com/systemd/systemd/issues/11810 */ + if (v == 0 || v == ULONG_MAX) + return log_debug_errno(SYNTHETIC_ERRNO(EUCLEAN), + "RDRAND returned suspicious value %lx, assuming bad hardware RNG, not using value.", v); + + *ret = v; return 0; #else return -EOPNOTSUPP; @@ -71,21 +90,22 @@ int genuine_random_bytes(void *p, size_t n, RandomFlags flags) { bool got_some = false; int r; - /* 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. */ + /* 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_MAY_FAIL 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. */ + /* 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 to, since this way we won't upset + * the kernel's random subsystem by accessing it before the pool is initialized (after all it + * will kmsg log about every attempt to do so)..*/ for (;;) { unsigned long u; size_t m; @@ -153,12 +173,13 @@ int genuine_random_bytes(void *p, size_t n, RandomFlags flags) { break; } else if (errno == EAGAIN) { - /* The kernel has no entropy whatsoever. Let's remember to use the syscall the next - * time again though. + /* 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. */ + * If RANDOM_MAY_FAIL 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)) { @@ -167,7 +188,7 @@ int genuine_random_bytes(void *p, size_t n, RandomFlags flags) { return 0; } - if (FLAGS_SET(flags, RANDOM_DONT_DRAIN)) + if (FLAGS_SET(flags, RANDOM_MAY_FAIL)) return -ENODATA; /* Use /dev/urandom instead */ @@ -196,14 +217,19 @@ void initialize_srand(void) { return; #if HAVE_SYS_AUXV_H - /* The kernel provides us with 16 bytes of entropy in auxv, so let's - * try to make use of that to seed the pseudo-random generator. It's - * better than nothing... */ + /* The kernel provides us with 16 bytes of entropy in auxv, so let's try to make use of that to seed + * the pseudo-random generator. It's better than nothing... But let's first hash it to make it harder + * to recover the original value by watching any pseudo-random bits we generate. After all the + * AT_RANDOM data might be used by other stuff too (in particular: ASLR), and we probably shouldn't + * leak the seed for that. */ - auxv = (const void*) getauxval(AT_RANDOM); + auxv = ULONG_TO_PTR(getauxval(AT_RANDOM)); if (auxv) { - assert_cc(sizeof(x) <= 16); - memcpy(&x, auxv, sizeof(x)); + static const uint8_t auxval_hash_key[16] = { + 0x92, 0x6e, 0xfe, 0x1b, 0xcf, 0x00, 0x52, 0x9c, 0xcc, 0x42, 0xcf, 0xdc, 0x94, 0x1f, 0x81, 0x0f + }; + + x = (unsigned) siphash24(auxv, 16, auxval_hash_key); } else #endif x = 0; @@ -250,7 +276,7 @@ void pseudo_random_bytes(void *p, size_t n) { void random_bytes(void *p, size_t n) { - if (genuine_random_bytes(p, n, RANDOM_EXTEND_WITH_PSEUDO|RANDOM_DONT_DRAIN|RANDOM_ALLOW_RDRAND) >= 0) + if (genuine_random_bytes(p, n, RANDOM_EXTEND_WITH_PSEUDO|RANDOM_MAY_FAIL|RANDOM_ALLOW_RDRAND) >= 0) return; /* If for some reason some user made /dev/urandom unavailable to us, or the kernel has no entropy, use a PRNG instead. */ diff --git a/shared/systemd/src/basic/random-util.h b/shared/systemd/src/basic/random-util.h index 3e8c288d3d..148b6c7813 100644 --- a/shared/systemd/src/basic/random-util.h +++ b/shared/systemd/src/basic/random-util.h @@ -8,11 +8,11 @@ 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_MAY_FAIL = 1 << 2, /* If we can't get any randomness at all, return early with -ENODATA */ 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 */ +int genuine_random_bytes(void *p, size_t n, RandomFlags flags); /* returns "genuine" randomness, optionally filled up with 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. */ diff --git a/shared/systemd/src/basic/socket-util.c b/shared/systemd/src/basic/socket-util.c index 904bafb76f..32a0d9c5d0 100644 --- a/shared/systemd/src/basic/socket-util.c +++ b/shared/systemd/src/basic/socket-util.c @@ -1219,17 +1219,34 @@ fallback: return (ssize_t) k; } +/* Put a limit on how many times will attempt to call accept4(). We loop + * only on "transient" errors, but let's make sure we don't loop forever. */ +#define MAX_FLUSH_ITERATIONS 1024 + int flush_accept(int fd) { struct pollfd pollfd = { .fd = fd, .events = POLLIN, }; - int r; + int r, b; + socklen_t l = sizeof(b); - /* Similar to flush_fd() but flushes all incoming connection by accepting them and immediately closing them. */ + /* Similar to flush_fd() but flushes all incoming connections by accepting and immediately closing + * them. */ - for (;;) { + if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &b, &l) < 0) + return -errno; + + assert(l == sizeof(b)); + if (!b) /* Let's check if this socket accepts connections before calling accept(). accept4() can + * return EOPNOTSUPP if the fd is not a listening socket, which we should treat as a fatal + * error, or in case the incoming TCP connection triggered a network issue, which we want to + * treat as a transient error. Thus, let's rule out the first reason for EOPNOTSUPP early, so + * we can loop safely on transient errors below. */ + return -ENOTTY; + + for (unsigned iteration = 0;; iteration++) { int cfd; r = poll(&pollfd, 1, 0); @@ -1242,6 +1259,10 @@ int flush_accept(int fd) { if (r == 0) return 0; + if (iteration >= MAX_FLUSH_ITERATIONS) + return log_debug_errno(SYNTHETIC_ERRNO(EBUSY), + "Failed to flush connections within " STRINGIFY(MAX_FLUSH_ITERATIONS) " iterations."); + cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC); if (cfd < 0) { if (errno == EAGAIN) diff --git a/shared/systemd/src/basic/string-util.c b/shared/systemd/src/basic/string-util.c index 5001a2be3a..779048904a 100644 --- a/shared/systemd/src/basic/string-util.c +++ b/shared/systemd/src/basic/string-util.c @@ -4,7 +4,6 @@ #include #include #include -#include #include #include @@ -761,23 +760,20 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) { * 2. Strips ANSI color sequences (a subset of CSI), i.e. ESC '[' … 'm' sequences * 3. Strips ANSI operating system sequences (CSO), i.e. ESC ']' … BEL sequences * - * Everything else will be left as it is. In particular other ANSI sequences are left as they are, as are any - * other special characters. Truncated ANSI sequences are left-as is too. This call is supposed to suppress the - * most basic formatting noise, but nothing else. + * Everything else will be left as it is. In particular other ANSI sequences are left as they are, as + * are any other special characters. Truncated ANSI sequences are left-as is too. This call is + * supposed to suppress the most basic formatting noise, but nothing else. * * Why care for CSO sequences? Well, to undo what terminal_urlify() and friends generate. */ isz = _isz ? *_isz : strlen(*ibuf); - f = open_memstream(&obuf, &osz); + /* Note we turn off internal locking on f for performance reasons. It's safe to do so since we + * created f here and it doesn't leave our scope. */ + f = open_memstream_unlocked(&obuf, &osz); if (!f) return NULL; - /* Note we turn off internal locking on f for performance reasons. It's safe to do so since we created f here - * and it doesn't leave our scope. */ - - (void) __fsetlocking(f, FSETLOCKING_BYCALLER); - for (i = *ibuf; i < *ibuf + isz + 1; i++) { switch (state) { diff --git a/shared/systemd/src/basic/string-util.h b/shared/systemd/src/basic/string-util.h index b23f4c8341..a630856236 100644 --- a/shared/systemd/src/basic/string-util.h +++ b/shared/systemd/src/basic/string-util.h @@ -212,6 +212,12 @@ static inline size_t strlen_ptr(const char *s) { return strlen(s); } +DISABLE_WARNING_STRINGOP_TRUNCATION; +static inline void strncpy_exact(char *buf, const char *src, size_t buf_len) { + strncpy(buf, src, buf_len); +} +REENABLE_WARNING; + /* Like startswith(), but operates on arbitrary memory blocks */ static inline void *memory_startswith(const void *p, size_t sz, const char *token) { size_t n; diff --git a/shared/systemd/src/basic/tmpfile-util.c b/shared/systemd/src/basic/tmpfile-util.c index bc92d6a6de..e77af7659f 100644 --- a/shared/systemd/src/basic/tmpfile-util.c +++ b/shared/systemd/src/basic/tmpfile-util.c @@ -1,9 +1,11 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ +#include #include #include "alloc-util.h" #include "fd-util.h" +#include "fileio.h" #include "fs-util.h" #include "hexdecoct.h" #include "macro.h" @@ -37,12 +39,15 @@ int fopen_temporary(const char *path, FILE **_f, char **_temp_path) { return -errno; } - f = fdopen(fd, "w"); - if (!f) { - unlink_noerrno(t); + /* This assumes that returned FILE object is short-lived and used within the same single-threaded + * context and never shared externally, hence locking is not necessary. */ + + r = fdopen_unlocked(fd, "w", &f); + if (r < 0) { + unlink(t); free(t); safe_close(fd); - return -errno; + return r; } *_f = f; diff --git a/shared/systemd/src/basic/umask-util.h b/shared/systemd/src/basic/umask-util.h index e964292eaf..cad745170e 100644 --- a/shared/systemd/src/basic/umask-util.h +++ b/shared/systemd/src/basic/umask-util.h @@ -8,21 +8,19 @@ #include "macro.h" static inline void umaskp(mode_t *u) { - umask(*u); + umask(*u & 0777); } #define _cleanup_umask_ _cleanup_(umaskp) -struct _umask_struct_ { - mode_t mask; - bool quit; -}; +/* We make use of the fact here that the umask() concept is using only the lower 9 bits of mode_t, although + * mode_t has space for the file type in the bits further up. We simply OR in the file type mask S_IFMT to + * distinguish the first and the second iteration of the RUN_WITH_UMASK() loop, so that we can run the first + * one, and exit on the second. */ -static inline void _reset_umask_(struct _umask_struct_ *s) { - umask(s->mask); -}; +assert_cc((S_IFMT & 0777) == 0); #define RUN_WITH_UMASK(mask) \ - for (_cleanup_(_reset_umask_) struct _umask_struct_ _saved_umask_ = { umask(mask), false }; \ - !_saved_umask_.quit ; \ - _saved_umask_.quit = true) + for (_cleanup_umask_ mode_t _saved_umask_ = umask(mask) | S_IFMT; \ + FLAGS_SET(_saved_umask_, S_IFMT); \ + _saved_umask_ &= 0777) diff --git a/src/systemd/src/libsystemd-network/arp-util.h b/src/systemd/src/libsystemd-network/arp-util.h index 10c684864b..9a4427e831 100644 --- a/src/systemd/src/libsystemd-network/arp-util.h +++ b/src/systemd/src/libsystemd-network/arp-util.h @@ -5,7 +5,7 @@ Copyright © 2014 Axis Communications AB. All rights reserved. ***/ -#include +#include #include "socket-util.h" #include "sparse-endian.h" diff --git a/src/systemd/src/libsystemd-network/network-internal.c b/src/systemd/src/libsystemd-network/network-internal.c index 2154cf7eac..a112b9f70f 100644 --- a/src/systemd/src/libsystemd-network/network-internal.c +++ b/src/systemd/src/libsystemd-network/network-internal.c @@ -612,7 +612,7 @@ int serialize_dhcp_option(FILE *f, const char *key, const void *data, size_t siz assert(data); hex_buf = hexmem(data, size); - if (hex_buf == NULL) + if (!hex_buf) return -ENOMEM; fprintf(f, "%s=%s\n", key, hex_buf); diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-client.c b/src/systemd/src/libsystemd-network/sd-dhcp-client.c index 97e1dd3702..6e077c0860 100644 --- a/src/systemd/src/libsystemd-network/sd-dhcp-client.c +++ b/src/systemd/src/libsystemd-network/sd-dhcp-client.c @@ -88,7 +88,8 @@ struct sd_dhcp_client { uint32_t mtu; uint32_t xid; usec_t start_time; - unsigned attempt; + uint64_t attempt; + uint64_t max_attempts; usec_t request_sent; sd_event_source *timeout_t1; sd_event_source *timeout_t2; @@ -520,10 +521,18 @@ int sd_dhcp_client_set_mtu(sd_dhcp_client *client, uint32_t mtu) { return 0; } +int sd_dhcp_client_set_max_attempts(sd_dhcp_client *client, uint64_t max_attempts) { + assert_return(client, -EINVAL); + + client->max_attempts = max_attempts; + + return 0; +} + int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret) { assert_return(client, -EINVAL); - if (!IN_SET(client->state, DHCP_STATE_BOUND, DHCP_STATE_RENEWING, DHCP_STATE_REBINDING)) + if (!IN_SET(client->state, DHCP_STATE_SELECTING, DHCP_STATE_BOUND, DHCP_STATE_RENEWING, DHCP_STATE_REBINDING)) return -EADDRNOTAVAIL; if (ret) @@ -532,11 +541,13 @@ int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret) { return 0; } -static void client_notify(sd_dhcp_client *client, int event) { +static int client_notify(sd_dhcp_client *client, int event) { assert(client); if (client->callback) - client->callback(client, event, client->userdata); + return client->callback(client, event, client->userdata); + + return 0; } static int client_initialize(sd_dhcp_client *client) { @@ -551,7 +562,7 @@ static int client_initialize(sd_dhcp_client *client) { (void) event_source_disable(client->timeout_t2); (void) event_source_disable(client->timeout_expire); - client->attempt = 1; + client->attempt = 0; client->state = DHCP_STATE_INIT; client->xid = 0; @@ -595,7 +606,7 @@ static int client_message_init( assert(ret); assert(_optlen); assert(_optoffset); - assert(IN_SET(type, DHCP_DISCOVER, DHCP_REQUEST)); + assert(IN_SET(type, DHCP_DISCOVER, DHCP_REQUEST, DHCP_RELEASE)); optlen = DHCP_MIN_OPTIONS_SIZE; size = sizeof(DHCPPacket) + optlen; @@ -686,7 +697,7 @@ static int client_message_init( MAY contain the Parameter Request List option. */ /* NOTE: in case that there would be an option to do not send * any PRL at all, the size should be checked before sending */ - if (client->req_opts_size > 0) { + if (client->req_opts_size > 0 && type != DHCP_RELEASE) { r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0, SD_DHCP_OPTION_PARAMETER_REQUEST_LIST, client->req_opts_size, client->req_opts); @@ -718,7 +729,7 @@ static int client_message_init( */ /* RFC7844 section 3: SHOULD NOT contain any other option. */ - if (!client->anonymize) { + if (!client->anonymize && type != DHCP_RELEASE) { max_size = htobe16(size); r = dhcp_option_append(&packet->dhcp, client->mtu, &optoffset, 0, SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE, @@ -850,6 +861,41 @@ static int client_send_discover(sd_dhcp_client *client) { return 0; } +static int client_send_release(sd_dhcp_client *client) { + _cleanup_free_ DHCPPacket *release = NULL; + size_t optoffset, optlen; + int r; + + assert(client); + assert(!IN_SET(client->state, DHCP_STATE_STOPPED)); + + r = client_message_init(client, &release, DHCP_RELEASE, + &optlen, &optoffset); + if (r < 0) + return r; + + /* Fill up release IP and MAC */ + release->dhcp.ciaddr = client->lease->address; + memcpy(&release->dhcp.chaddr, &client->mac_addr, client->mac_addr_len); + + r = dhcp_option_append(&release->dhcp, optlen, &optoffset, 0, + SD_DHCP_OPTION_END, 0, NULL); + if (r < 0) + return r; + + r = dhcp_network_send_udp_socket(client->fd, + client->lease->server_address, + DHCP_PORT_SERVER, + &release->dhcp, + sizeof(DHCPMessage) + optoffset); + if (r < 0) + return r; + + log_dhcp_client(client, "RELEASE"); + + return 0; +} + static int client_send_request(sd_dhcp_client *client) { _cleanup_free_ DHCPPacket *request = NULL; size_t optoffset, optlen; @@ -1050,10 +1096,12 @@ static int client_timeout_resend( case DHCP_STATE_REQUESTING: case DHCP_STATE_BOUND: - if (client->attempt < 64) - client->attempt *= 2; + if (client->attempt < client->max_attempts) + client->attempt++; + else + goto error; - next_timeout = time_now + (client->attempt - 1) * USEC_PER_SEC; + next_timeout = time_now + ((UINT64_C(1) << MIN(client->attempt, (uint64_t) 6)) - 1) * USEC_PER_SEC; break; @@ -1077,17 +1125,15 @@ static int client_timeout_resend( r = client_send_discover(client); if (r >= 0) { client->state = DHCP_STATE_SELECTING; - client->attempt = 1; - } else { - if (client->attempt >= 64) - goto error; - } + client->attempt = 0; + } else if (client->attempt >= client->max_attempts) + goto error; break; case DHCP_STATE_SELECTING: r = client_send_discover(client); - if (r < 0 && client->attempt >= 64) + if (r < 0 && client->attempt >= client->max_attempts) goto error; break; @@ -1097,7 +1143,7 @@ static int client_timeout_resend( case DHCP_STATE_RENEWING: case DHCP_STATE_REBINDING: r = client_send_request(client); - if (r < 0 && client->attempt >= 64) + if (r < 0 && client->attempt >= client->max_attempts) goto error; if (client->state == DHCP_STATE_INIT_REBOOT) @@ -1249,7 +1295,7 @@ static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata) client->fd = asynchronous_close(client->fd); client->state = DHCP_STATE_REBINDING; - client->attempt = 1; + client->attempt = 0; r = dhcp_network_bind_raw_socket(client->ifindex, &client->link, client->xid, client->mac_addr, @@ -1269,7 +1315,7 @@ static int client_timeout_t1(sd_event_source *s, uint64_t usec, void *userdata) DHCP_CLIENT_DONT_DESTROY(client); client->state = DHCP_STATE_RENEWING; - client->attempt = 1; + client->attempt = 0; return client_initialize_time_events(client); } @@ -1319,6 +1365,9 @@ static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer, size_ sd_dhcp_lease_unref(client->lease); client->lease = TAKE_PTR(lease); + if (client_notify(client, SD_DHCP_CLIENT_EVENT_SELECTING) < 0) + return -ENOMSG; + log_dhcp_client(client, "OFFER"); return 0; @@ -1553,7 +1602,7 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, i if (r >= 0) { client->state = DHCP_STATE_REQUESTING; - client->attempt = 1; + client->attempt = 0; r = event_reset_time(client->event, &client->timeout_resend, clock_boottime_or_monotonic(), @@ -1588,7 +1637,7 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, i notify_event = r; client->state = DHCP_STATE_BOUND; - client->attempt = 1; + client->attempt = 0; client->last_addr = client->lease->address; @@ -1844,6 +1893,14 @@ int sd_dhcp_client_start(sd_dhcp_client *client) { return r; } +int sd_dhcp_client_send_release(sd_dhcp_client *client) { + assert_return(client, -EINVAL); + + client_send_release(client); + + return 0; +} + int sd_dhcp_client_stop(sd_dhcp_client *client) { DHCP_CLIENT_DONT_DESTROY(client); @@ -1927,10 +1984,10 @@ int sd_dhcp_client_new(sd_dhcp_client **ret, int anonymize) { .state = DHCP_STATE_INIT, .ifindex = -1, .fd = -1, - .attempt = 1, .mtu = DHCP_DEFAULT_MIN_SIZE, .port = DHCP_PORT_CLIENT, .anonymize = !!anonymize, + .max_attempts = (uint64_t) -1, }; /* NOTE: this could be moved to a function. */ if (anonymize) { diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-lease.c b/src/systemd/src/libsystemd-network/sd-dhcp-lease.c index a16314a9d3..c089b4278b 100644 --- a/src/systemd/src/libsystemd-network/sd-dhcp-lease.c +++ b/src/systemd/src/libsystemd-network/sd-dhcp-lease.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include @@ -832,7 +831,6 @@ int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) { if (r < 0) goto fail; - (void) __fsetlocking(f, FSETLOCKING_BYCALLER); (void) fchmod(fileno(f), 0644); fprintf(f, diff --git a/src/systemd/src/libsystemd/sd-event/sd-event.c b/src/systemd/src/libsystemd/sd-event/sd-event.c index 1987f279eb..09285c19d8 100644 --- a/src/systemd/src/libsystemd/sd-event/sd-event.c +++ b/src/systemd/src/libsystemd/sd-event/sd-event.c @@ -339,6 +339,12 @@ fail: DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_event, sd_event, event_free); +_public_ sd_event_source* sd_event_source_disable_unref(sd_event_source *s) { + if (s) + (void) sd_event_source_set_enabled(s, SD_EVENT_OFF); + return sd_event_source_unref(s); +} + static bool event_pid_changed(sd_event *e) { assert(e); @@ -3022,7 +3028,7 @@ static void event_close_inode_data_fds(sd_event *e) { /* Close the fds pointing to the inodes to watch now. We need to close them as they might otherwise pin * filesystems. But we can't close them right-away as we need them as long as the user still wants to make - * adjustments to the even source, such as changing the priority (which requires us to remove and readd a watch + * adjustments to the even source, such as changing the priority (which requires us to remove and re-add a watch * for the inode). Hence, let's close them when entering the first iteration after they were added, as a * compromise. */ diff --git a/src/systemd/src/shared/dns-domain.c b/src/systemd/src/shared/dns-domain.c index 4b31cb36ed..f62ad0a0f5 100644 --- a/src/systemd/src/shared/dns-domain.c +++ b/src/systemd/src/shared/dns-domain.c @@ -37,7 +37,7 @@ int dns_label_unescape(const char **name, char *dest, size_t sz, DNSLabelFlags f d = dest; for (;;) { - if (*n == 0 || *n == '.') { + if (IN_SET(*n, 0, '.')) { if (FLAGS_SET(flags, DNS_LABEL_LDH) && last_char == '-') /* Trailing dash */ return -EINVAL; diff --git a/src/systemd/src/systemd/sd-dhcp-client.h b/src/systemd/src/systemd/sd-dhcp-client.h index bd0d429df6..ab62368e9c 100644 --- a/src/systemd/src/systemd/sd-dhcp-client.h +++ b/src/systemd/src/systemd/sd-dhcp-client.h @@ -38,6 +38,7 @@ enum { SD_DHCP_CLIENT_EVENT_IP_CHANGE = 2, SD_DHCP_CLIENT_EVENT_EXPIRED = 3, SD_DHCP_CLIENT_EVENT_RENEW = 4, + SD_DHCP_CLIENT_EVENT_SELECTING = 5, }; enum { @@ -98,7 +99,7 @@ enum { typedef struct sd_dhcp_client sd_dhcp_client; -typedef void (*sd_dhcp_client_callback_t)(sd_dhcp_client *client, int event, void *userdata); +typedef int (*sd_dhcp_client_callback_t)(sd_dhcp_client *client, int event, void *userdata); int sd_dhcp_client_set_callback( sd_dhcp_client *client, sd_dhcp_client_callback_t cb, @@ -154,6 +155,9 @@ int sd_dhcp_client_get_client_id( int sd_dhcp_client_set_mtu( sd_dhcp_client *client, uint32_t mtu); +int sd_dhcp_client_set_max_attempts( + sd_dhcp_client *client, + uint64_t attempt); int sd_dhcp_client_set_client_port( sd_dhcp_client *client, uint16_t port); @@ -172,6 +176,7 @@ int sd_dhcp_client_get_lease( int sd_dhcp_client_stop(sd_dhcp_client *client); int sd_dhcp_client_start(sd_dhcp_client *client); +int sd_dhcp_client_send_release(sd_dhcp_client *client); sd_dhcp_client *sd_dhcp_client_ref(sd_dhcp_client *client); sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client); diff --git a/src/systemd/src/systemd/sd-event.h b/src/systemd/src/systemd/sd-event.h index 7bb8609376..b14c92697b 100644 --- a/src/systemd/src/systemd/sd-event.h +++ b/src/systemd/src/systemd/sd-event.h @@ -113,6 +113,7 @@ int sd_event_get_iteration(sd_event *e, uint64_t *ret); sd_event_source* sd_event_source_ref(sd_event_source *s); sd_event_source* sd_event_source_unref(sd_event_source *s); +sd_event_source* sd_event_source_disable_unref(sd_event_source *s); sd_event *sd_event_source_get_event(sd_event_source *s); void* sd_event_source_get_userdata(sd_event_source *s); @@ -149,6 +150,7 @@ 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); _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_event_source, sd_event_source_unref); +_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_event_source, sd_event_source_disable_unref); _SD_END_DECLARATIONS;