diff options
Diffstat (limited to 'src/systemd')
116 files changed, 1271 insertions, 3651 deletions
diff --git a/src/systemd/meson.build b/src/systemd/meson.build deleted file mode 100644 index fe3d88d3..00000000 --- a/src/systemd/meson.build +++ /dev/null @@ -1,70 +0,0 @@ -sources = files( - 'sd-adapt/nm-sd-adapt.c', - 'src/basic/alloc-util.c', - 'src/basic/escape.c', - 'src/basic/ether-addr-util.c', - 'src/basic/extract-word.c', - 'src/basic/fd-util.c', - 'src/basic/fileio.c', - 'src/basic/fs-util.c', - 'src/basic/hash-funcs.c', - 'src/basic/hashmap.c', - 'src/basic/hexdecoct.c', - 'src/basic/hostname-util.c', - 'src/basic/in-addr-util.c', - 'src/basic/io-util.c', - 'src/basic/mempool.c', - 'src/basic/parse-util.c', - 'src/basic/path-util.c', - 'src/basic/prioq.c', - 'src/basic/process-util.c', - 'src/basic/random-util.c', - 'src/basic/socket-util.c', - 'src/basic/string-table.c', - 'src/basic/string-util.c', - 'src/basic/strv.c', - 'src/basic/time-util.c', - 'src/basic/utf8.c', - 'src/basic/util.c', - 'src/libsystemd-network/arp-util.c', - 'src/libsystemd-network/dhcp-identifier.c', - 'src/libsystemd-network/dhcp-network.c', - 'src/libsystemd-network/dhcp-option.c', - 'src/libsystemd-network/dhcp-packet.c', - 'src/libsystemd-network/dhcp6-network.c', - 'src/libsystemd-network/dhcp6-option.c', - 'src/libsystemd-network/lldp-neighbor.c', - 'src/libsystemd-network/lldp-network.c', - 'src/libsystemd-network/network-internal.c', - 'src/libsystemd-network/sd-dhcp-client.c', - 'src/libsystemd-network/sd-dhcp-lease.c', - 'src/libsystemd-network/sd-dhcp6-client.c', - 'src/libsystemd-network/sd-dhcp6-lease.c', - 'src/libsystemd-network/sd-ipv4acd.c', - 'src/libsystemd-network/sd-ipv4ll.c', - 'src/libsystemd-network/sd-lldp.c', - 'src/libsystemd/sd-event/sd-event.c', - 'src/libsystemd/sd-id128/id128-util.c', - 'src/libsystemd/sd-id128/sd-id128.c', - 'src/shared/dns-domain.c', - 'nm-sd.c' -) - -incs = [ - src_inc, - include_directories( - 'sd-adapt', - 'src/basic', - 'src/libsystemd-network', - 'src/shared', - 'src/systemd' - ) -] - -libsystemd_nm = static_library( - 'systemd-nm', - sources: sources, - include_directories: incs, - dependencies: nm_core_dep, - c_args: '-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_SYSTEMD' -) diff --git a/src/systemd/sd-adapt/device-nodes.h b/src/systemd/sd-adapt/device-nodes.h deleted file mode 100644 index 637892c2..00000000 --- a/src/systemd/sd-adapt/device-nodes.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -/* dummy header */ diff --git a/src/systemd/sd-adapt/errno-list.h b/src/systemd/sd-adapt/errno-list.h deleted file mode 100644 index 637892c2..00000000 --- a/src/systemd/sd-adapt/errno-list.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -/* dummy header */ diff --git a/src/systemd/sd-adapt/locale-util.h b/src/systemd/sd-adapt/locale-util.h deleted file mode 100644 index 637892c2..00000000 --- a/src/systemd/sd-adapt/locale-util.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -/* dummy header */ diff --git a/src/systemd/sd-adapt/memfd-util.h b/src/systemd/sd-adapt/memfd-util.h deleted file mode 100644 index 637892c2..00000000 --- a/src/systemd/sd-adapt/memfd-util.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -/* dummy header */ diff --git a/src/systemd/sd-adapt/nm-sd-adapt.h b/src/systemd/sd-adapt/nm-sd-adapt.h index 3a4125a0..0d291e26 100644 --- a/src/systemd/sd-adapt/nm-sd-adapt.h +++ b/src/systemd/sd-adapt/nm-sd-adapt.h @@ -26,16 +26,12 @@ #include <sys/resource.h> #include <time.h> +#define noreturn G_GNUC_NORETURN + #ifndef CLOCK_BOOTTIME #define CLOCK_BOOTTIME 7 #endif -#if defined(HAVE_DECL_REALLOCARRAY) && HAVE_DECL_REALLOCARRAY == 1 -#define HAVE_REALLOCARRAY 1 -#else -#define HAVE_REALLOCARRAY 0 -#endif - #if defined(HAVE_DECL_EXPLICIT_BZERO) && HAVE_DECL_EXPLICIT_BZERO == 1 #define HAVE_EXPLICIT_BZERO 1 #else @@ -109,7 +105,7 @@ G_STMT_START { \ * itself. *****************************************************************************/ -#if (NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_SYSTEMD +#if (NETWORKMANAGER_COMPILATION) == NM_NETWORKMANAGER_COMPILATION_SYSTEMD #include <netinet/in.h> #include <string.h> @@ -142,15 +138,6 @@ G_STMT_START { \ # endif #endif -static inline pid_t -raw_getpid (void) { -#if defined(__alpha__) - return (pid_t) syscall (__NR_getxpid); -#else - return (pid_t) syscall (__NR_getpid); -#endif -} - /*****************************************************************************/ /* work around missing uchar.h */ @@ -159,6 +146,8 @@ typedef guint32 char32_t; /*****************************************************************************/ +#define PID_TO_PTR(p) ((void*) ((uintptr_t) p)) + static inline int sd_notify (int unset_environment, const char *state) { @@ -197,7 +186,7 @@ static inline pid_t gettid(void) { return (pid_t) syscall(SYS_gettid); } -#endif /* (NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_SYSTEMD */ +#endif /* (NETWORKMANAGER_COMPILATION) == NM_NETWORKMANAGER_COMPILATION_SYSTEMD */ #endif /* NM_SD_ADAPT_H */ diff --git a/src/systemd/sd-adapt/procfs-util.h b/src/systemd/sd-adapt/procfs-util.h deleted file mode 100644 index 637892c2..00000000 --- a/src/systemd/sd-adapt/procfs-util.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -/* dummy header */ diff --git a/src/systemd/sd-adapt/terminal-util.h b/src/systemd/sd-adapt/terminal-util.h deleted file mode 100644 index 637892c2..00000000 --- a/src/systemd/sd-adapt/terminal-util.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -/* dummy header */ diff --git a/src/systemd/src/basic/alloc-util.c b/src/systemd/src/basic/alloc-util.c index 1a058d2f..97588312 100644 --- a/src/systemd/src/basic/alloc-util.c +++ b/src/systemd/src/basic/alloc-util.c @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. @@ -40,7 +39,7 @@ void* memdup(const void *p, size_t l) { return ret; } -void* memdup_suffix0(const void *p, size_t l) { +void* memdup_suffix0(const void*p, size_t l) { void *ret; assert(l == 0 || p); diff --git a/src/systemd/src/basic/alloc-util.h b/src/systemd/src/basic/alloc-util.h index b1e0edbb..0a89691b 100644 --- a/src/systemd/src/basic/alloc-util.h +++ b/src/systemd/src/basic/alloc-util.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once /*** @@ -55,7 +54,7 @@ static inline void *mfree(void *memory) { }) void* memdup(const void *p, size_t l) _alloc_(2); -void* memdup_suffix0(const void *p, size_t l) _alloc_(2); +void* memdup_suffix0(const void*p, size_t l) _alloc_(2); static inline void freep(void *p) { free(*(void**) p); @@ -74,14 +73,12 @@ _malloc_ _alloc_(1, 2) static inline void *malloc_multiply(size_t size, size_t return malloc(size * need); } -#if !HAVE_REALLOCARRAY -_alloc_(2, 3) static inline void *reallocarray(void *p, size_t need, size_t size) { +_alloc_(2, 3) static inline void *realloc_multiply(void *p, size_t size, size_t need) { if (size_multiply_overflow(size, need)) return NULL; return realloc(p, size * need); } -#endif _alloc_(2, 3) static inline void *memdup_multiply(const void *p, size_t size, size_t need) { if (size_multiply_overflow(size, need)) @@ -130,12 +127,3 @@ void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size); _new_ = alloca_align(_size_, (align)); \ (void*)memset(_new_, 0, _size_); \ }) - -/* Takes inspiration from Rusts's Option::take() method: reads and returns a pointer, but at the same time resets it to - * NULL. See: https://doc.rust-lang.org/std/option/enum.Option.html#method.take */ -#define TAKE_PTR(ptr) \ - ({ \ - typeof(ptr) _ptr_ = (ptr); \ - (ptr) = NULL; \ - _ptr_; \ - }) diff --git a/src/systemd/src/basic/async.h b/src/systemd/src/basic/async.h index 01c975bb..9bd13ff6 100644 --- a/src/systemd/src/basic/async.h +++ b/src/systemd/src/basic/async.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once /*** @@ -22,5 +21,5 @@ int asynchronous_job(void* (*func)(void *p), void *arg); -int asynchronous_sync(pid_t *ret_pid); +int asynchronous_sync(void); int asynchronous_close(int fd); diff --git a/src/systemd/src/basic/escape.c b/src/systemd/src/basic/escape.c index fac618dd..27a20702 100644 --- a/src/systemd/src/basic/escape.c +++ b/src/systemd/src/basic/escape.c @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. diff --git a/src/systemd/src/basic/escape.h b/src/systemd/src/basic/escape.h index cd5c49fa..e62347af 100644 --- a/src/systemd/src/basic/escape.h +++ b/src/systemd/src/basic/escape.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once /*** diff --git a/src/systemd/src/basic/ether-addr-util.c b/src/systemd/src/basic/ether-addr-util.c index 93922a28..a793219c 100644 --- a/src/systemd/src/basic/ether-addr-util.c +++ b/src/systemd/src/basic/ether-addr-util.c @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. @@ -20,7 +19,6 @@ #include "nm-sd-adapt.h" -#include <errno.h> #include <net/ethernet.h> #include <stdio.h> #include <sys/types.h> @@ -74,7 +72,7 @@ int ether_addr_from_string(const char *s, struct ether_addr *ret, size_t *offset if (s[pos] == '\0') \ break; \ hexoff = strchr(hex, s[pos]); \ - if (!hexoff) \ + if (hexoff == NULL) \ break; \ assert(hexoff >= hex); \ x = hexoff - hex; \ @@ -102,7 +100,7 @@ int ether_addr_from_string(const char *s, struct ether_addr *ret, size_t *offset sep = s[strspn(s, hex)]; if (sep == '\n') return -EINVAL; - if (!strchr(":.-", sep)) + if (strchr(":.-", sep) == NULL) return -EINVAL; if (sep == '.') { diff --git a/src/systemd/src/basic/ether-addr-util.h b/src/systemd/src/basic/ether-addr-util.h index 08d05a13..74e125a9 100644 --- a/src/systemd/src/basic/ether-addr-util.h +++ b/src/systemd/src/basic/ether-addr-util.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once /*** diff --git a/src/systemd/src/basic/extract-word.c b/src/systemd/src/basic/extract-word.c index e52c376b..69d8c48d 100644 --- a/src/systemd/src/basic/extract-word.c +++ b/src/systemd/src/basic/extract-word.c @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. @@ -196,7 +195,8 @@ finish: finish_force_next: s[sz] = 0; - *ret = TAKE_PTR(s); + *ret = s; + s = NULL; return 1; } diff --git a/src/systemd/src/basic/extract-word.h b/src/systemd/src/basic/extract-word.h index 300c51bb..04746c6d 100644 --- a/src/systemd/src/basic/extract-word.h +++ b/src/systemd/src/basic/extract-word.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once /*** diff --git a/src/systemd/src/basic/fd-util.c b/src/systemd/src/basic/fd-util.c index ff480f51..1c327d83 100644 --- a/src/systemd/src/basic/fd-util.c +++ b/src/systemd/src/basic/fd-util.c @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. @@ -29,10 +28,8 @@ #include "dirent-util.h" #include "fd-util.h" -#include "fileio.h" #include "fs-util.h" #include "macro.h" -#include "memfd-util.h" #include "missing.h" #include "parse-util.h" #include "path-util.h" @@ -194,6 +191,12 @@ int fd_cloexec(int fd, bool cloexec) { } #if 0 /* NM_IGNORED */ +void stdio_unset_cloexec(void) { + fd_cloexec(STDIN_FILENO, false); + fd_cloexec(STDOUT_FILENO, false); + fd_cloexec(STDERR_FILENO, false); +} + _pure_ static bool fd_in_set(int fd, const int fdset[], unsigned n_fdset) { unsigned i; @@ -224,21 +227,20 @@ int close_all_fds(const int except[], unsigned n_except) { assert_se(getrlimit(RLIMIT_NOFILE, &rl) >= 0); for (fd = 3; fd < (int) rl.rlim_max; fd ++) { - int q; if (fd_in_set(fd, except, n_except)) continue; - q = close_nointr(fd); - if (q < 0 && q != -EBADF && r >= 0) - r = q; + if (close_nointr(fd) < 0) + if (errno != EBADF && r == 0) + r = -errno; } return r; } FOREACH_DIRENT(de, d, return -errno) { - int fd = -1, q; + int fd = -1; if (safe_atoi(de->d_name, &fd) < 0) /* Let's better ignore this, just in case */ @@ -253,9 +255,11 @@ int close_all_fds(const int except[], unsigned n_except) { if (fd_in_set(fd, except, n_except)) continue; - q = close_nointr(fd); - if (q < 0 && q != -EBADF && r >= 0) /* Valgrind has its own FD and doesn't want to have it closed */ - r = q; + if (close_nointr(fd) < 0) { + /* Valgrind has its own FD and doesn't want to have it closed */ + if (errno != EBADF && r == 0) + r = -errno; + } } return r; @@ -365,384 +369,15 @@ bool fdname_is_valid(const char *s) { } int fd_get_path(int fd, char **ret) { - _cleanup_close_ int dir = -1; - char fdname[DECIMAL_STR_MAX(int)]; + char procfs_path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int)]; int r; - dir = open("/proc/self/fd/", O_CLOEXEC | O_DIRECTORY | O_PATH); - if (dir < 0) - /* /proc is not available or not set up properly, we're most likely - * in some chroot environment. */ - return errno == ENOENT ? -EOPNOTSUPP : -errno; + xsprintf(procfs_path, "/proc/self/fd/%i", fd); - xsprintf(fdname, "%i", fd); + r = readlink_malloc(procfs_path, ret); - r = readlinkat_malloc(dir, fdname, ret); - if (r == -ENOENT) - /* If the file doesn't exist the fd is invalid */ + if (r == -ENOENT) /* If the file doesn't exist the fd is invalid */ return -EBADF; return r; } - -#if 0 /* NM_IGNORED */ -int move_fd(int from, int to, int cloexec) { - int r; - - /* Move fd 'from' to 'to', make sure FD_CLOEXEC remains equal if requested, and release the old fd. If - * 'cloexec' is passed as -1, the original FD_CLOEXEC is inherited for the new fd. If it is 0, it is turned - * off, if it is > 0 it is turned on. */ - - if (from < 0) - return -EBADF; - if (to < 0) - return -EBADF; - - if (from == to) { - - if (cloexec >= 0) { - r = fd_cloexec(to, cloexec); - if (r < 0) - return r; - } - - return to; - } - - if (cloexec < 0) { - int fl; - - fl = fcntl(from, F_GETFD, 0); - if (fl < 0) - return -errno; - - cloexec = !!(fl & FD_CLOEXEC); - } - - r = dup3(from, to, cloexec ? O_CLOEXEC : 0); - if (r < 0) - return -errno; - - assert(r == to); - - safe_close(from); - - return to; -} - -int acquire_data_fd(const void *data, size_t size, unsigned flags) { - - _cleanup_close_pair_ int pipefds[2] = { -1, -1 }; - char pattern[] = "/dev/shm/data-fd-XXXXXX"; - _cleanup_close_ int fd = -1; - int isz = 0, r; - ssize_t n; - off_t f; - - assert(data || size == 0); - - /* Acquire a read-only file descriptor that when read from returns the specified data. This is much more - * complex than I wish it was. But here's why: - * - * a) First we try to use memfds. They are the best option, as we can seal them nicely to make them - * read-only. Unfortunately they require kernel 3.17, and – at the time of writing – we still support 3.14. - * - * b) Then, we try classic pipes. They are the second best options, as we can close the writing side, retaining - * a nicely read-only fd in the reading side. However, they are by default quite small, and unprivileged - * clients can only bump their size to a system-wide limit, which might be quite low. - * - * c) Then, we try an O_TMPFILE file in /dev/shm (that dir is the only suitable one known to exist from - * earliest boot on). To make it read-only we open the fd a second time with O_RDONLY via - * /proc/self/<fd>. Unfortunately O_TMPFILE is not available on older kernels on tmpfs. - * - * d) Finally, we try creating a regular file in /dev/shm, which we then delete. - * - * It sucks a bit that depending on the situation we return very different objects here, but that's Linux I - * figure. */ - - if (size == 0 && ((flags & ACQUIRE_NO_DEV_NULL) == 0)) { - /* As a special case, return /dev/null if we have been called for an empty data block */ - r = open("/dev/null", O_RDONLY|O_CLOEXEC|O_NOCTTY); - if (r < 0) - return -errno; - - return r; - } - - if ((flags & ACQUIRE_NO_MEMFD) == 0) { - fd = memfd_new("data-fd"); - if (fd < 0) - goto try_pipe; - - n = write(fd, data, size); - if (n < 0) - return -errno; - if ((size_t) n != size) - return -EIO; - - f = lseek(fd, 0, SEEK_SET); - if (f != 0) - return -errno; - - r = memfd_set_sealed(fd); - if (r < 0) - return r; - - return TAKE_FD(fd); - } - -try_pipe: - if ((flags & ACQUIRE_NO_PIPE) == 0) { - if (pipe2(pipefds, O_CLOEXEC|O_NONBLOCK) < 0) - return -errno; - - isz = fcntl(pipefds[1], F_GETPIPE_SZ, 0); - if (isz < 0) - return -errno; - - if ((size_t) isz < size) { - isz = (int) size; - if (isz < 0 || (size_t) isz != size) - return -E2BIG; - - /* Try to bump the pipe size */ - (void) fcntl(pipefds[1], F_SETPIPE_SZ, isz); - - /* See if that worked */ - isz = fcntl(pipefds[1], F_GETPIPE_SZ, 0); - if (isz < 0) - return -errno; - - if ((size_t) isz < size) - goto try_dev_shm; - } - - n = write(pipefds[1], data, size); - if (n < 0) - return -errno; - if ((size_t) n != size) - return -EIO; - - (void) fd_nonblock(pipefds[0], false); - - return TAKE_FD(pipefds[0]); - } - -try_dev_shm: - if ((flags & ACQUIRE_NO_TMPFILE) == 0) { - fd = open("/dev/shm", O_RDWR|O_TMPFILE|O_CLOEXEC, 0500); - if (fd < 0) - goto try_dev_shm_without_o_tmpfile; - - n = write(fd, data, size); - if (n < 0) - return -errno; - if ((size_t) n != size) - return -EIO; - - /* Let's reopen the thing, in order to get an O_RDONLY fd for the original O_RDWR one */ - return fd_reopen(fd, O_RDONLY|O_CLOEXEC); - } - -try_dev_shm_without_o_tmpfile: - if ((flags & ACQUIRE_NO_REGULAR) == 0) { - fd = mkostemp_safe(pattern); - if (fd < 0) - return fd; - - n = write(fd, data, size); - if (n < 0) { - r = -errno; - goto unlink_and_return; - } - if ((size_t) n != size) { - r = -EIO; - goto unlink_and_return; - } - - /* Let's reopen the thing, in order to get an O_RDONLY fd for the original O_RDWR one */ - r = open(pattern, O_RDONLY|O_CLOEXEC); - if (r < 0) - r = -errno; - - unlink_and_return: - (void) unlink(pattern); - return r; - } - - return -EOPNOTSUPP; -} -#endif /* NM_IGNORED */ - -int fd_move_above_stdio(int fd) { - int flags, copy; - PROTECT_ERRNO; - - /* Moves the specified file descriptor if possible out of the range [0…2], i.e. the range of - * stdin/stdout/stderr. If it can't be moved outside of this range the original file descriptor is - * returned. This call is supposed to be used for long-lasting file descriptors we allocate in our code that - * might get loaded into foreign code, and where we want ensure our fds are unlikely used accidentally as - * stdin/stdout/stderr of unrelated code. - * - * Note that this doesn't fix any real bugs, it just makes it less likely that our code will be affected by - * buggy code from others that mindlessly invokes 'fprintf(stderr, …' or similar in places where stderr has - * been closed before. - * - * This function is written in a "best-effort" and "least-impact" style. This means whenever we encounter an - * error we simply return the original file descriptor, and we do not touch errno. */ - - if (fd < 0 || fd > 2) - return fd; - - flags = fcntl(fd, F_GETFD, 0); - if (flags < 0) - return fd; - - if (flags & FD_CLOEXEC) - copy = fcntl(fd, F_DUPFD_CLOEXEC, 3); - else - copy = fcntl(fd, F_DUPFD, 3); - if (copy < 0) - return fd; - - assert(copy > 2); - - (void) close(fd); - return copy; -} - -#if 0 /* NM_IGNORED */ -int rearrange_stdio(int original_input_fd, int original_output_fd, int original_error_fd) { - - int fd[3] = { /* Put together an array of fds we work on */ - original_input_fd, - original_output_fd, - original_error_fd - }; - - int r, i, - null_fd = -1, /* if we open /dev/null, we store the fd to it here */ - copy_fd[3] = { -1, -1, -1 }; /* This contains all fds we duplicate here temporarily, and hence need to close at the end */ - bool null_readable, null_writable; - - /* Sets up stdin, stdout, stderr with the three file descriptors passed in. If any of the descriptors is - * specified as -1 it will be connected with /dev/null instead. If any of the file descriptors is passed as - * itself (e.g. stdin as STDIN_FILENO) it is left unmodified, but the O_CLOEXEC bit is turned off should it be - * on. - * - * Note that if any of the passed file descriptors are > 2 they will be closed — both on success and on - * failure! Thus, callers should assume that when this function returns the input fds are invalidated. - * - * Note that when this function fails stdin/stdout/stderr might remain half set up! - * - * O_CLOEXEC is turned off for all three file descriptors (which is how it should be for - * stdin/stdout/stderr). */ - - null_readable = original_input_fd < 0; - null_writable = original_output_fd < 0 || original_error_fd < 0; - - /* First step, open /dev/null once, if we need it */ - if (null_readable || null_writable) { - - /* Let's open this with O_CLOEXEC first, and convert it to non-O_CLOEXEC when we move the fd to the final position. */ - null_fd = open("/dev/null", (null_readable && null_writable ? O_RDWR : - null_readable ? O_RDONLY : O_WRONLY) | O_CLOEXEC); - if (null_fd < 0) { - r = -errno; - goto finish; - } - - /* If this fd is in the 0…2 range, let's move it out of it */ - if (null_fd < 3) { - int copy; - - copy = fcntl(null_fd, F_DUPFD_CLOEXEC, 3); /* Duplicate this with O_CLOEXEC set */ - if (copy < 0) { - r = -errno; - goto finish; - } - - safe_close(null_fd); - null_fd = copy; - } - } - - /* Let's assemble fd[] with the fds to install in place of stdin/stdout/stderr */ - for (i = 0; i < 3; i++) { - - if (fd[i] < 0) - fd[i] = null_fd; /* A negative parameter means: connect this one to /dev/null */ - else if (fd[i] != i && fd[i] < 3) { - /* This fd is in the 0…2 territory, but not at its intended place, move it out of there, so that we can work there. */ - copy_fd[i] = fcntl(fd[i], F_DUPFD_CLOEXEC, 3); /* Duplicate this with O_CLOEXEC set */ - if (copy_fd[i] < 0) { - r = -errno; - goto finish; - } - - fd[i] = copy_fd[i]; - } - } - - /* At this point we now have the fds to use in fd[], and they are all above the stdio range, so that we - * have freedom to move them around. If the fds already were at the right places then the specific fds are - * -1. Let's now move them to the right places. This is the point of no return. */ - for (i = 0; i < 3; i++) { - - if (fd[i] == i) { - - /* fd is already in place, but let's make sure O_CLOEXEC is off */ - r = fd_cloexec(i, false); - if (r < 0) - goto finish; - - } else { - assert(fd[i] > 2); - - if (dup2(fd[i], i) < 0) { /* Turns off O_CLOEXEC on the new fd. */ - r = -errno; - goto finish; - } - } - } - - r = 0; - -finish: - /* Close the original fds, but only if they were outside of the stdio range. Also, properly check for the same - * fd passed in multiple times. */ - safe_close_above_stdio(original_input_fd); - if (original_output_fd != original_input_fd) - safe_close_above_stdio(original_output_fd); - if (original_error_fd != original_input_fd && original_error_fd != original_output_fd) - safe_close_above_stdio(original_error_fd); - - /* Close the copies we moved > 2 */ - for (i = 0; i < 3; i++) - safe_close(copy_fd[i]); - - /* Close our null fd, if it's > 2 */ - safe_close_above_stdio(null_fd); - - return r; -} - -int fd_reopen(int fd, int flags) { - char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)]; - int new_fd; - - /* Reopens the specified fd with new flags. This is useful for convert an O_PATH fd into a regular one, or to - * turn O_RDWR fds into O_RDONLY fds. - * - * This doesn't work on sockets (since they cannot be open()ed, ever). - * - * This implicitly resets the file read index to 0. */ - - xsprintf(procfs_path, "/proc/self/fd/%i", fd); - new_fd = open(procfs_path, flags); - if (new_fd < 0) - return -errno; - - return new_fd; -} -#endif /* NM_IGNORED */ diff --git a/src/systemd/src/basic/fd-util.h b/src/systemd/src/basic/fd-util.h index 163b096b..34b98d4a 100644 --- a/src/systemd/src/basic/fd-util.h +++ b/src/systemd/src/basic/fd-util.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once /*** @@ -35,13 +34,6 @@ int close_nointr(int fd); int safe_close(int fd); void safe_close_pair(int p[]); -static inline int safe_close_above_stdio(int fd) { - if (fd < 3) /* Don't close stdin/stdout/stderr, but still invalidate the fd by returning -1 */ - return -1; - - return safe_close(fd); -} - void close_many(const int fds[], unsigned n_fd); int fclose_nointr(FILE *f); @@ -71,6 +63,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(DIR*, closedir); int fd_nonblock(int fd, bool nonblock); int fd_cloexec(int fd, bool cloexec); +void stdio_unset_cloexec(void); int close_all_fds(const int except[], unsigned n_except); @@ -82,36 +75,6 @@ bool fdname_is_valid(const char *s); int fd_get_path(int fd, char **ret); -int move_fd(int from, int to, int cloexec); - -enum { - ACQUIRE_NO_DEV_NULL = 1 << 0, - ACQUIRE_NO_MEMFD = 1 << 1, - ACQUIRE_NO_PIPE = 1 << 2, - ACQUIRE_NO_TMPFILE = 1 << 3, - ACQUIRE_NO_REGULAR = 1 << 4, -}; - -int acquire_data_fd(const void *data, size_t size, unsigned flags); - /* Hint: ENETUNREACH happens if we try to connect to "non-existing" special IP addresses, such as ::5 */ #define ERRNO_IS_DISCONNECT(r) \ IN_SET(r, ENOTCONN, ECONNRESET, ECONNREFUSED, ECONNABORTED, EPIPE, ENETUNREACH) - -int fd_move_above_stdio(int fd); - -int rearrange_stdio(int original_input_fd, int original_output_fd, int original_error_fd); - -static inline int make_null_stdio(void) { - return rearrange_stdio(-1, -1, -1); -} - -/* Like TAKE_PTR() but for file descriptors, resetting them to -1 */ -#define TAKE_FD(fd) \ - ({ \ - int _fd_ = (fd); \ - (fd) = -1; \ - _fd_; \ - }) - -int fd_reopen(int fd, int flags); diff --git a/src/systemd/src/basic/fileio.c b/src/systemd/src/basic/fileio.c index c7b4b241..51d1c052 100644 --- a/src/systemd/src/basic/fileio.c +++ b/src/systemd/src/basic/fileio.c @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. @@ -25,10 +24,8 @@ #include <limits.h> #include <stdarg.h> #include <stdint.h> -#include <stdio_ext.h> #include <stdlib.h> #include <string.h> -#include <sys/mman.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> @@ -65,30 +62,12 @@ int write_string_stream_ts( WriteStringFileFlags flags, struct timespec *ts) { - bool needs_nl; - assert(f); assert(line); - if (ferror(f)) - return -EIO; - - needs_nl = !(flags & WRITE_STRING_FILE_AVOID_NEWLINE) && !endswith(line, "\n"); - - if (needs_nl && (flags & WRITE_STRING_FILE_DISABLE_BUFFER)) { - /* If STDIO buffering was disabled, then let's append the newline character to the string itself, so - * that the write goes out in one go, instead of two */ - - line = strjoina(line, "\n"); - needs_nl = false; - } - - if (fputs(line, f) == EOF) - return -errno; - - if (needs_nl) - if (fputc('\n', f) == EOF) - return -errno; + fputs(line, f); + if (!(flags & WRITE_STRING_FILE_AVOID_NEWLINE) && !endswith(line, "\n")) + fputc('\n', f); if (ts) { struct timespec twice[2] = {*ts, *ts}; @@ -120,7 +99,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); @@ -163,7 +141,7 @@ int write_string_file_ts( return r; } else - assert(!ts); + assert(ts == NULL); if (flags & WRITE_STRING_FILE_CREATE) { f = fopen(fn, "we"); @@ -190,11 +168,6 @@ int write_string_file_ts( } } - (void) __fsetlocking(f, FSETLOCKING_BYCALLER); - - if (flags & WRITE_STRING_FILE_DISABLE_BUFFER) - setvbuf(f, NULL, _IONBF, 0); - r = write_string_stream_ts(f, line, flags, ts); if (r < 0) goto fail; @@ -228,11 +201,10 @@ int read_one_line_file(const char *fn, char **line) { if (!f) return -errno; - (void) __fsetlocking(f, FSETLOCKING_BYCALLER); - r = read_line(f, LONG_LINE_MAX, line); return r < 0 ? r : 0; } +#endif /* NM_IGNORED */ int verify_file(const char *fn, const char *blob, bool accept_extra_nl) { _cleanup_fclose_ FILE *f = NULL; @@ -255,8 +227,6 @@ int verify_file(const char *fn, const char *blob, bool accept_extra_nl) { if (!f) return -errno; - (void) __fsetlocking(f, FSETLOCKING_BYCALLER); - /* We try to read one byte more than we need, so that we know whether we hit eof */ errno = 0; k = fread(buf, 1, l + accept_extra_nl + 1, f); @@ -272,7 +242,6 @@ int verify_file(const char *fn, const char *blob, bool accept_extra_nl) { return 1; } -#endif /* NM_IGNORED */ int read_full_stream(FILE *f, char **contents, size_t *size) { size_t n, l; @@ -334,7 +303,8 @@ int read_full_stream(FILE *f, char **contents, size_t *size) { } buf[l] = 0; - *contents = TAKE_PTR(buf); + *contents = buf; + buf = NULL; /* do not free */ if (size) *size = l; @@ -352,8 +322,6 @@ int read_full_file(const char *fn, char **contents, size_t *size) { if (!f) return -errno; - (void) __fsetlocking(f, FSETLOCKING_BYCALLER); - return read_full_stream(f, contents, size); } @@ -366,11 +334,11 @@ static int parse_env_file_internal( void *userdata, int *n_pushed) { + _cleanup_free_ char *contents = NULL, *key = NULL; size_t key_alloc = 0, n_key = 0, value_alloc = 0, n_value = 0, last_value_whitespace = (size_t) -1, last_key_whitespace = (size_t) -1; - _cleanup_free_ char *contents = NULL, *key = NULL, *value = NULL; - unsigned line = 1; - char *p; + char *p, *value = NULL; int r; + unsigned line = 1; enum { PRE_KEY, @@ -407,8 +375,10 @@ static int parse_env_file_internal( state = KEY; last_key_whitespace = (size_t) -1; - if (!GREEDY_REALLOC(key, key_alloc, n_key+2)) - return -ENOMEM; + if (!GREEDY_REALLOC(key, key_alloc, n_key+2)) { + r = -ENOMEM; + goto fail; + } key[n_key++] = c; } @@ -428,8 +398,10 @@ static int parse_env_file_internal( else if (last_key_whitespace == (size_t) -1) last_key_whitespace = n_key; - if (!GREEDY_REALLOC(key, key_alloc, n_key+2)) - return -ENOMEM; + if (!GREEDY_REALLOC(key, key_alloc, n_key+2)) { + r = -ENOMEM; + goto fail; + } key[n_key++] = c; } @@ -451,7 +423,7 @@ static int parse_env_file_internal( r = push(fname, line, key, value, userdata, n_pushed); if (r < 0) - return r; + goto fail; n_key = 0; value = NULL; @@ -466,8 +438,10 @@ static int parse_env_file_internal( else if (!strchr(WHITESPACE, c)) { state = VALUE; - if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) - return -ENOMEM; + if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) { + r = -ENOMEM; + goto fail; + } value[n_value++] = c; } @@ -494,7 +468,7 @@ static int parse_env_file_internal( r = push(fname, line, key, value, userdata, n_pushed); if (r < 0) - return r; + goto fail; n_key = 0; value = NULL; @@ -509,8 +483,10 @@ static int parse_env_file_internal( else if (last_value_whitespace == (size_t) -1) last_value_whitespace = n_value; - if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) - return -ENOMEM; + if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) { + r = -ENOMEM; + goto fail; + } value[n_value++] = c; } @@ -522,8 +498,10 @@ static int parse_env_file_internal( if (!strchr(newline, c)) { /* Escaped newlines we eat up entirely */ - if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) - return -ENOMEM; + if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) { + r = -ENOMEM; + goto fail; + } value[n_value++] = c; } @@ -535,8 +513,10 @@ static int parse_env_file_internal( else if (c == '\\') state = SINGLE_QUOTE_VALUE_ESCAPE; else { - if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) - return -ENOMEM; + if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) { + r = -ENOMEM; + goto fail; + } value[n_value++] = c; } @@ -547,8 +527,10 @@ static int parse_env_file_internal( state = SINGLE_QUOTE_VALUE; if (!strchr(newline, c)) { - if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) - return -ENOMEM; + if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) { + r = -ENOMEM; + goto fail; + } value[n_value++] = c; } @@ -560,8 +542,10 @@ static int parse_env_file_internal( else if (c == '\\') state = DOUBLE_QUOTE_VALUE_ESCAPE; else { - if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) - return -ENOMEM; + if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) { + r = -ENOMEM; + goto fail; + } value[n_value++] = c; } @@ -572,8 +556,10 @@ static int parse_env_file_internal( state = DOUBLE_QUOTE_VALUE; if (!strchr(newline, c)) { - if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) - return -ENOMEM; + if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) { + r = -ENOMEM; + goto fail; + } value[n_value++] = c; } @@ -618,12 +604,14 @@ static int parse_env_file_internal( r = push(fname, line, key, value, userdata, n_pushed); if (r < 0) - return r; - - value = NULL; + goto fail; } return 0; + +fail: + free(value); + return r; } static int check_utf8ness_and_warn( @@ -891,8 +879,7 @@ 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); + fchmod_umask(fileno(f), 0644); STRV_FOREACH(i, l) write_env_var(f, *i); @@ -910,16 +897,14 @@ int write_env_file(const char *fname, char **l) { } int executable_is_script(const char *path, char **interpreter) { + int r; _cleanup_free_ char *line = NULL; - size_t len; + int len; char *ans; - int r; assert(path); r = read_one_line_file(path, &line); - if (r == -ENOBUFS) /* First line overly long? if so, then it's not a script */ - return 0; if (r < 0) return r; @@ -1162,7 +1147,6 @@ int fflush_and_check(FILE *f) { return 0; } -#if 0 /* NM_IGNORED */ int fflush_sync_and_check(FILE *f) { int r; @@ -1175,13 +1159,8 @@ int fflush_sync_and_check(FILE *f) { if (fsync(fileno(f)) < 0) return -errno; - r = fsync_directory_of_file(fileno(f)); - if (r < 0) - return r; - return 0; } -#endif /* NM_IGNORED */ /* This is much like mkostemp() but is subject to umask(). */ int mkostemp_safe(char *pattern) { @@ -1218,7 +1197,8 @@ int tempfn_xxxxxx(const char *p, const char *extra, char **ret) { if (!filename_is_valid(fn)) return -EINVAL; - extra = strempty(extra); + if (extra == NULL) + extra = ""; t = new(char, strlen(p) + 2 + strlen(extra) + 6 + 1); if (!t) @@ -1252,7 +1232,8 @@ int tempfn_random(const char *p, const char *extra, char **ret) { if (!filename_is_valid(fn)) return -EINVAL; - extra = strempty(extra); + if (!extra) + extra = ""; t = new(char, strlen(p) + 2 + strlen(extra) + 16 + 1); if (!t) @@ -1292,7 +1273,8 @@ int tempfn_random_child(const char *p, const char *extra, char **ret) { return r; } - extra = strempty(extra); + if (!extra) + extra = ""; t = new(char, strlen(p) + 3 + strlen(extra) + 16 + 1); if (!t) @@ -1444,7 +1426,8 @@ int open_tmpfile_linkable(const char *target, int flags, char **ret_path) { if (fd < 0) return -errno; - *ret_path = TAKE_PTR(tmp); + *ret_path = tmp; + tmp = NULL; return fd; } @@ -1484,7 +1467,7 @@ int link_tmpfile(int fd, const char *path, const char *target) { if (rename_noreplace(AT_FDCWD, path, AT_FDCWD, target) < 0) return -errno; } else { - char proc_fd_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(fd) + 1]; + char proc_fd_path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(fd) + 1]; xsprintf(proc_fd_path, "/proc/self/fd/%i", fd); @@ -1530,7 +1513,8 @@ int read_nul_string(FILE *f, char **ret) { return -ENOMEM; } - *ret = TAKE_PTR(x); + *ret = x; + x = NULL; return 0; } @@ -1554,7 +1538,9 @@ int mkdtemp_malloc(const char *template, char **ret) { return 0; } -DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, funlockfile); +static inline void funlockfilep(FILE **f) { + funlockfile(*f); +} int read_line(FILE *f, size_t limit, char **ret) { _cleanup_free_ char *buffer = NULL; @@ -1581,7 +1567,7 @@ int read_line(FILE *f, size_t limit, char **ret) { } { - _unused_ _cleanup_(funlockfilep) FILE *flocked = f; + _cleanup_(funlockfilep) FILE *flocked = f; flockfile(f); for (;;) { diff --git a/src/systemd/src/basic/fileio.h b/src/systemd/src/basic/fileio.h index da5d5c66..eba05be2 100644 --- a/src/systemd/src/basic/fileio.h +++ b/src/systemd/src/basic/fileio.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once /*** @@ -30,17 +29,11 @@ #include "time-util.h" typedef enum { - WRITE_STRING_FILE_CREATE = 1<<0, - WRITE_STRING_FILE_ATOMIC = 1<<1, - WRITE_STRING_FILE_AVOID_NEWLINE = 1<<2, + WRITE_STRING_FILE_CREATE = 1<<0, + WRITE_STRING_FILE_ATOMIC = 1<<1, + WRITE_STRING_FILE_AVOID_NEWLINE = 1<<2, WRITE_STRING_FILE_VERIFY_ON_FAILURE = 1<<3, - WRITE_STRING_FILE_SYNC = 1<<4, - WRITE_STRING_FILE_DISABLE_BUFFER = 1<<5, - - /* 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() - and friends. */ - + WRITE_STRING_FILE_SYNC = 1<<4, } WriteStringFileFlags; int write_string_stream_ts(FILE *f, const char *line, WriteStringFileFlags flags, struct timespec *ts); diff --git a/src/systemd/src/basic/fs-util.c b/src/systemd/src/basic/fs-util.c index ffd9996a..ff4ad5ab 100644 --- a/src/systemd/src/basic/fs-util.c +++ b/src/systemd/src/basic/fs-util.c @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. @@ -41,7 +40,6 @@ #include "mkdir.h" #include "parse-util.h" #include "path-util.h" -#include "process-util.h" #include "stat-util.h" #include "stdio-util.h" #include "string-util.h" @@ -109,6 +107,7 @@ int rmdir_parents(const char *path, const char *stop) { return 0; } + int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char *newpath) { struct stat buf; int ret; @@ -230,6 +229,49 @@ int readlink_and_make_absolute(const char *p, char **r) { return 0; } +int readlink_and_canonicalize(const char *p, const char *root, char **ret) { + char *t, *s; + int r; + + assert(p); + assert(ret); + + r = readlink_and_make_absolute(p, &t); + if (r < 0) + return r; + + r = chase_symlinks(t, root, 0, &s); + if (r < 0) + /* If we can't follow up, then let's return the original string, slightly cleaned up. */ + *ret = path_kill_slashes(t); + else { + *ret = s; + free(t); + } + + return 0; +} + +int readlink_and_make_absolute_root(const char *root, const char *path, char **ret) { + _cleanup_free_ char *target = NULL, *t = NULL; + const char *full; + int r; + + full = prefix_roota(root, path); + r = readlink_malloc(full, &target); + if (r < 0) + return r; + + t = file_in_same_dir(path, target); + if (!t) + return -ENOMEM; + + *ret = t; + t = NULL; + + return 0; +} + int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) { assert(path); @@ -280,60 +322,43 @@ int fd_warn_permissions(const char *path, int fd) { } int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gid, mode_t mode) { - char fdpath[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)]; - _cleanup_close_ int fd = -1; - int r, ret = 0; + _cleanup_close_ int fd; + int r; assert(path); - /* Note that touch_file() does not follow symlinks: if invoked on an existing symlink, then it is the symlink - * itself which is updated, not its target - * - * Returns the first error we encounter, but tries to apply as much as possible. */ - if (parents) - (void) mkdir_parents(path, 0755); - - /* Initially, we try to open the node with O_PATH, so that we get a reference to the node. This is useful in - * case the path refers to an existing device or socket node, as we can open it successfully in all cases, and - * won't trigger any driver magic or so. */ - fd = open(path, O_PATH|O_CLOEXEC|O_NOFOLLOW); - if (fd < 0) { - if (errno != ENOENT) - return -errno; + mkdir_parents(path, 0755); + + fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, + IN_SET(mode, 0, MODE_INVALID) ? 0644 : mode); + if (fd < 0) + return -errno; - /* if the node doesn't exist yet, we create it, but with O_EXCL, so that we only create a regular file - * here, and nothing else */ - fd = open(path, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, IN_SET(mode, 0, MODE_INVALID) ? 0644 : mode); - if (fd < 0) + if (mode != MODE_INVALID) { + r = fchmod(fd, mode); + if (r < 0) return -errno; } - /* Let's make a path from the fd, and operate on that. With this logic, we can adjust the access mode, - * ownership and time of the file node in all cases, even if the fd refers to an O_PATH object — which is - * something fchown(), fchmod(), futimensat() don't allow. */ - xsprintf(fdpath, "/proc/self/fd/%i", fd); - - if (mode != MODE_INVALID) - if (chmod(fdpath, mode) < 0) - ret = -errno; - - if (uid_is_valid(uid) || gid_is_valid(gid)) - if (chown(fdpath, uid, gid) < 0 && ret >= 0) - ret = -errno; + if (uid != UID_INVALID || gid != GID_INVALID) { + r = fchown(fd, uid, gid); + if (r < 0) + return -errno; + } if (stamp != USEC_INFINITY) { struct timespec ts[2]; timespec_store(&ts[0], stamp); ts[1] = ts[0]; - r = utimensat(AT_FDCWD, fdpath, ts, 0); + r = futimens(fd, ts); } else - r = utimensat(AT_FDCWD, fdpath, NULL, 0); - if (r < 0 && ret >= 0) + r = futimens(fd, NULL); + if (r < 0) return -errno; - return ret; + return 0; } int touch(const char *path) { @@ -465,8 +490,10 @@ int get_files_in_directory(const char *path, char ***list) { n++; } - if (list) - *list = TAKE_PTR(l); + if (list) { + *list = l; + l = NULL; /* avoid freeing */ + } return n; } @@ -489,7 +516,7 @@ static int getenv_tmp_dir(const char **ret_path) { r = -ENOTDIR; goto next; } - if (!path_is_normalized(e)) { + if (!path_is_safe(e)) { r = -EPERM; goto next; } @@ -559,19 +586,8 @@ int tmp_dir(const char **ret) { return tmp_dir_internal("/tmp", ret); } -int unlink_or_warn(const char *filename) { - if (unlink(filename) < 0 && errno != ENOENT) - /* If the file doesn't exist and the fs simply was read-only (in which - * case unlink() returns EROFS even if the file doesn't exist), don't - * complain */ - if (errno != EROFS || access(filename, F_OK) >= 0) - return log_error_errno(errno, "Failed to remove \"%s\": %m", filename); - - return 0; -} - int inotify_add_watch_fd(int fd, int what, uint32_t mask) { - char path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1]; + char path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1]; int r; /* This is like inotify_add_watch(), except that the file to watch is not referenced by a path, but by an fd */ @@ -584,39 +600,16 @@ int inotify_add_watch_fd(int fd, int what, uint32_t mask) { return r; } -static bool noop_root(const char *root) { - return isempty(root) || path_equal(root, "/"); -} - -static bool safe_transition(const struct stat *a, const struct stat *b) { - /* Returns true if the transition from a to b is safe, i.e. that we never transition from unprivileged to - * privileged files or directories. Why bother? So that unprivileged code can't symlink to privileged files - * making us believe we read something safe even though it isn't safe in the specific context we open it in. */ - - if (a->st_uid == 0) /* Transitioning from privileged to unprivileged is always fine */ - return true; - - return a->st_uid == b->st_uid; /* Otherwise we need to stay within the same UID */ -} - int chase_symlinks(const char *path, const char *original_root, unsigned flags, char **ret) { _cleanup_free_ char *buffer = NULL, *done = NULL, *root = NULL; _cleanup_close_ int fd = -1; unsigned max_follow = 32; /* how many symlinks to follow before giving up and returning ELOOP */ - struct stat previous_stat; bool exists = true; char *todo; int r; assert(path); - /* Either the file may be missing, or we return an fd to the final object, but both make no sense */ - if ((flags & (CHASE_NONEXISTENT|CHASE_OPEN)) == (CHASE_NONEXISTENT|CHASE_OPEN)) - return -EINVAL; - - if (isempty(path)) - return -EINVAL; - /* This is a lot like canonicalize_file_name(), but takes an additional "root" parameter, that allows following * symlinks relative to a root directory, instead of the root of the host. * @@ -635,35 +628,18 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags, * Suggested usage: whenever you want to canonicalize a path, use this function. Pass the absolute path you got * as-is: fully qualified and relative to your host's root. Optionally, specify the root parameter to tell this * function what to do when encountering a symlink with an absolute path as directory: prefix it by the - * specified path. */ - - /* A root directory of "/" or "" is identical to none */ - if (noop_root(original_root)) - original_root = NULL; - - if (!original_root && !ret && (flags & (CHASE_NONEXISTENT|CHASE_NO_AUTOFS|CHASE_SAFE|CHASE_OPEN)) == CHASE_OPEN) { - /* Shortcut the CHASE_OPEN case if the caller isn't interested in the actual path and has no root set - * and doesn't care about any of the other special features we provide either. */ - r = open(path, O_PATH|O_CLOEXEC); - if (r < 0) - return -errno; - - return r; - } + * specified path. + * + * Note: there's also chase_symlinks_prefix() (see below), which as first step prefixes the passed path by the + * passed root. */ if (original_root) { r = path_make_absolute_cwd(original_root, &root); if (r < 0) return r; - if (flags & CHASE_PREFIX_ROOT) { - - /* We don't support relative paths in combination with a root directory */ - if (!path_is_absolute(path)) - return -EINVAL; - + if (flags & CHASE_PREFIX_ROOT) path = prefix_roota(root, path); - } } r = path_make_absolute_cwd(path, &buffer); @@ -674,11 +650,6 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags, if (fd < 0) return -errno; - if (flags & CHASE_SAFE) { - if (fstat(fd, &previous_stat) < 0) - return -errno; - } - todo = buffer; for (;;) { _cleanup_free_ char *first = NULL; @@ -697,20 +668,9 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags, todo += m; - /* Empty? Then we reached the end. */ - if (isempty(first)) - break; - /* Just a single slash? Then we reached the end. */ - if (path_equal(first, "/")) { - /* Preserve the trailing slash */ - - if (flags & CHASE_TRAIL_SLASH) - if (!strextend(&done, "/", NULL)) - return -ENOMEM; - + if (isempty(first) || path_equal(first, "/")) break; - } /* Just a dot? Then let's eat this up. */ if (path_equal(first, "/.")) @@ -719,7 +679,7 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags, /* Two dots? Then chop off the last bit of what we already found out. */ if (path_equal(first, "/..")) { _cleanup_free_ char *parent = NULL; - _cleanup_close_ int fd_parent = -1; + int fd_parent = -1; /* If we already are at the top, then going up will not change anything. This is in-line with * how the kernel handles this. */ @@ -742,18 +702,8 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags, if (fd_parent < 0) return -errno; - if (flags & CHASE_SAFE) { - if (fstat(fd_parent, &st) < 0) - return -errno; - - if (!safe_transition(&previous_stat, &st)) - return -EPERM; - - previous_stat = st; - } - safe_close(fd); - fd = TAKE_FD(fd_parent); + fd = fd_parent; continue; } @@ -764,16 +714,12 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags, if (errno == ENOENT && (flags & CHASE_NONEXISTENT) && - (isempty(todo) || path_is_normalized(todo))) { + (isempty(todo) || path_is_safe(todo))) { /* If CHASE_NONEXISTENT is set, and the path does not exist, then that's OK, return * what we got so far. But don't allow this if the remaining path contains "../ or "./" * or something else weird. */ - /* If done is "/", as first also contains slash at the head, then remove this redundant slash. */ - if (streq_ptr(done, "/")) - *done = '\0'; - if (!strextend(&done, first, todo, NULL)) return -ENOMEM; @@ -786,14 +732,8 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags, if (fstat(child, &st) < 0) return -errno; - if ((flags & CHASE_SAFE) && - !safe_transition(&previous_stat, &st)) - return -EPERM; - - previous_stat = st; - if ((flags & CHASE_NO_AUTOFS) && - fd_is_fs_type(child, AUTOFS_SUPER_MAGIC) > 0) + fd_check_fstype(child, AUTOFS_SUPER_MAGIC) > 0) return -EREMOTE; if (S_ISLNK(st.st_mode)) { @@ -822,16 +762,6 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags, if (fd < 0) return -errno; - if (flags & CHASE_SAFE) { - if (fstat(fd, &st) < 0) - return -errno; - - if (!safe_transition(&previous_stat, &st)) - return -EPERM; - - previous_stat = st; - } - free(done); /* Note that we do not revalidate the root, we take it as is. */ @@ -843,11 +773,12 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags, return -ENOMEM; } - /* Prefix what's left to do with what we just read, and start the loop again, but - * remain in the current directory. */ - joined = strjoin(destination, todo); - } else - joined = strjoin("/", destination, todo); + } + + /* Prefix what's left to do with what we just read, and start the loop again, + * but remain in the current directory. */ + + joined = strjoin("/", destination, todo); if (!joined) return -ENOMEM; @@ -858,20 +789,18 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags, } /* If this is not a symlink, then let's just add the name we read to what we already verified. */ - if (!done) - done = TAKE_PTR(first); - else { - /* If done is "/", as first also contains slash at the head, then remove this redundant slash. */ - if (streq(done, "/")) - *done = '\0'; - + if (!done) { + done = first; + first = NULL; + } else { if (!strextend(&done, first, NULL)) return -ENOMEM; } /* And iterate again, but go one directory further down. */ safe_close(fd); - fd = TAKE_FD(child); + fd = child; + child = -1; } if (!done) { @@ -881,221 +810,11 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags, return -ENOMEM; } - if (ret) - *ret = TAKE_PTR(done); - - if (flags & CHASE_OPEN) { - /* Return the O_PATH fd we currently are looking to the caller. It can translate it to a proper fd by - * opening /proc/self/fd/xyz. */ - - assert(fd >= 0); - return TAKE_FD(fd); + if (ret) { + *ret = done; + done = NULL; } return exists; } - -int chase_symlinks_and_open( - const char *path, - const char *root, - unsigned chase_flags, - int open_flags, - char **ret_path) { - - _cleanup_close_ int path_fd = -1; - _cleanup_free_ char *p = NULL; - int r; - - if (chase_flags & CHASE_NONEXISTENT) - return -EINVAL; - - if (noop_root(root) && !ret_path && (chase_flags & (CHASE_NO_AUTOFS|CHASE_SAFE)) == 0) { - /* Shortcut this call if none of the special features of this call are requested */ - r = open(path, open_flags); - if (r < 0) - return -errno; - - return r; - } - - path_fd = chase_symlinks(path, root, chase_flags|CHASE_OPEN, ret_path ? &p : NULL); - if (path_fd < 0) - return path_fd; - - r = fd_reopen(path_fd, open_flags); - if (r < 0) - return r; - - if (ret_path) - *ret_path = TAKE_PTR(p); - - return r; -} - -int chase_symlinks_and_opendir( - const char *path, - const char *root, - unsigned chase_flags, - char **ret_path, - DIR **ret_dir) { - - char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)]; - _cleanup_close_ int path_fd = -1; - _cleanup_free_ char *p = NULL; - DIR *d; - - if (!ret_dir) - return -EINVAL; - if (chase_flags & CHASE_NONEXISTENT) - return -EINVAL; - - if (noop_root(root) && !ret_path && (chase_flags & (CHASE_NO_AUTOFS|CHASE_SAFE)) == 0) { - /* Shortcut this call if none of the special features of this call are requested */ - d = opendir(path); - if (!d) - return -errno; - - *ret_dir = d; - return 0; - } - - path_fd = chase_symlinks(path, root, chase_flags|CHASE_OPEN, ret_path ? &p : NULL); - if (path_fd < 0) - return path_fd; - - xsprintf(procfs_path, "/proc/self/fd/%i", path_fd); - d = opendir(procfs_path); - if (!d) - return -errno; - - if (ret_path) - *ret_path = TAKE_PTR(p); - - *ret_dir = d; - return 0; -} - -int access_fd(int fd, int mode) { - char p[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(fd) + 1]; - int r; - - /* Like access() but operates on an already open fd */ - - xsprintf(p, "/proc/self/fd/%i", fd); - r = access(p, mode); - if (r < 0) - return -errno; - - return r; -} - -int unlinkat_deallocate(int fd, const char *name, int flags) { - _cleanup_close_ int truncate_fd = -1; - struct stat st; - off_t l, bs; - - /* Operates like unlinkat() but also deallocates the file contents if it is a regular file and there's no other - * link to it. This is useful to ensure that other processes that might have the file open for reading won't be - * able to keep the data pinned on disk forever. This call is particular useful whenever we execute clean-up - * jobs ("vacuuming"), where we want to make sure the data is really gone and the disk space released and - * returned to the free pool. - * - * Deallocation is preferably done by FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE (👊) if supported, which means - * the file won't change size. That's a good thing since we shouldn't needlessly trigger SIGBUS in other - * programs that have mmap()ed the file. (The assumption here is that changing file contents to all zeroes - * underneath those programs is the better choice than simply triggering SIGBUS in them which truncation does.) - * However if hole punching is not implemented in the kernel or file system we'll fall back to normal file - * truncation (🔪), as our goal of deallocating the data space trumps our goal of being nice to readers (💐). - * - * Note that we attempt deallocation, but failure to succeed with that is not considered fatal, as long as the - * primary job – to delete the file – is accomplished. */ - - if ((flags & AT_REMOVEDIR) == 0) { - truncate_fd = openat(fd, name, O_WRONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW|O_NONBLOCK); - if (truncate_fd < 0) { - - /* If this failed because the file doesn't exist propagate the error right-away. Also, - * AT_REMOVEDIR wasn't set, and we tried to open the file for writing, which means EISDIR is - * returned when this is a directory but we are not supposed to delete those, hence propagate - * the error right-away too. */ - if (IN_SET(errno, ENOENT, EISDIR)) - return -errno; - - if (errno != ELOOP) /* don't complain if this is a symlink */ - log_debug_errno(errno, "Failed to open file '%s' for deallocation, ignoring: %m", name); - } - } - - if (unlinkat(fd, name, flags) < 0) - return -errno; - - if (truncate_fd < 0) /* Don't have a file handle, can't do more ☹️ */ - return 0; - - if (fstat(truncate_fd, &st) < 0) { - log_debug_errno(errno, "Failed to stat file '%s' for deallocation, ignoring.", name); - return 0; - } - - if (!S_ISREG(st.st_mode) || st.st_blocks == 0 || st.st_nlink > 0) - return 0; - - /* If this is a regular file, it actually took up space on disk and there are no other links it's time to - * punch-hole/truncate this to release the disk space. */ - - bs = MAX(st.st_blksize, 512); - l = DIV_ROUND_UP(st.st_size, bs) * bs; /* Round up to next block size */ - - if (fallocate(truncate_fd, FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE, 0, l) >= 0) - return 0; /* Successfully punched a hole! 😊 */ - - /* Fall back to truncation */ - if (ftruncate(truncate_fd, 0) < 0) { - log_debug_errno(errno, "Failed to truncate file to 0, ignoring: %m"); - return 0; - } - - return 0; -} - -int fsync_directory_of_file(int fd) { - _cleanup_free_ char *path = NULL, *dn = NULL; - _cleanup_close_ int dfd = -1; - int r; - - r = fd_verify_regular(fd); - if (r < 0) - return r; - - r = fd_get_path(fd, &path); - if (r < 0) { - log_debug("Failed to query /proc/self/fd/%d%s: %m", - fd, - r == -EOPNOTSUPP ? ", ignoring" : ""); - - if (r == -EOPNOTSUPP) - /* If /proc is not available, we're most likely running in some - * chroot environment, and syncing the directory is not very - * important in that case. Let's just silently do nothing. */ - return 0; - - return r; - } - - if (!path_is_absolute(path)) - return -EINVAL; - - dn = dirname_malloc(path); - if (!dn) - return -ENOMEM; - - dfd = open(dn, O_RDONLY|O_CLOEXEC|O_DIRECTORY); - if (dfd < 0) - return -errno; - - if (fsync(dfd) < 0) - return -errno; - - return 0; -} #endif /* NM_IGNORED */ diff --git a/src/systemd/src/basic/fs-util.h b/src/systemd/src/basic/fs-util.h index 2225b7e7..d3342d5c 100644 --- a/src/systemd/src/basic/fs-util.h +++ b/src/systemd/src/basic/fs-util.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once /*** @@ -20,7 +19,6 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <dirent.h> #include <fcntl.h> #include <limits.h> #include <stdbool.h> @@ -30,7 +28,6 @@ #include <unistd.h> #include "time-util.h" -#include "util.h" int unlink_noerrno(const char *path); @@ -42,6 +39,8 @@ int readlinkat_malloc(int fd, const char *p, char **ret); int readlink_malloc(const char *p, char **r); int readlink_value(const char *p, char **ret); int readlink_and_make_absolute(const char *p, char **r); +int readlink_and_canonicalize(const char *p, const char *root, char **r); +int readlink_and_make_absolute_root(const char *root, const char *path, char **ret); int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid); @@ -65,8 +64,6 @@ int get_files_in_directory(const char *path, char ***list); int tmp_dir(const char **ret); int var_tmp_dir(const char **ret); -int unlink_or_warn(const char *filename); - #define INOTIFY_EVENT_MAX (sizeof(struct inotify_event) + NAME_MAX + 1) #define FOREACH_INOTIFY_EVENT(e, buffer, sz) \ @@ -82,35 +79,22 @@ union inotify_event_buffer { int inotify_add_watch_fd(int fd, int what, uint32_t mask); enum { - CHASE_PREFIX_ROOT = 1U << 0, /* If set, the specified path will be prefixed by the specified root before beginning the iteration */ - CHASE_NONEXISTENT = 1U << 1, /* If set, it's OK if the path doesn't actually exist. */ - CHASE_NO_AUTOFS = 1U << 2, /* If set, return -EREMOTE if autofs mount point found */ - CHASE_SAFE = 1U << 3, /* If set, return EPERM if we ever traverse from unprivileged to privileged files or directories */ - CHASE_OPEN = 1U << 4, /* If set, return an O_PATH object to the final component */ - CHASE_TRAIL_SLASH = 1U << 5, /* If set, any trailing slash will be preserved */ + CHASE_PREFIX_ROOT = 1, /* If set, the specified path will be prefixed by the specified root before beginning the iteration */ + CHASE_NONEXISTENT = 2, /* If set, it's OK if the path doesn't actually exist. */ + CHASE_NO_AUTOFS = 4, /* If set, return -EREMOTE if autofs mount point found */ }; int chase_symlinks(const char *path_with_prefix, const char *root, unsigned flags, char **ret); -int chase_symlinks_and_open(const char *path, const char *root, unsigned chase_flags, int open_flags, char **ret_path); -int chase_symlinks_and_opendir(const char *path, const char *root, unsigned chase_flags, char **ret_path, DIR **ret_dir); - /* Useful for usage with _cleanup_(), removes a directory and frees the pointer */ static inline void rmdir_and_free(char *p) { - PROTECT_ERRNO; (void) rmdir(p); free(p); } DEFINE_TRIVIAL_CLEANUP_FUNC(char*, rmdir_and_free); static inline void unlink_and_free(char *p) { - (void) unlink_noerrno(p); + (void) unlink(p); free(p); } DEFINE_TRIVIAL_CLEANUP_FUNC(char*, unlink_and_free); - -int access_fd(int fd, int mode); - -int unlinkat_deallocate(int fd, const char *name, int flags); - -int fsync_directory_of_file(int fd); diff --git a/src/systemd/src/basic/hash-funcs.c b/src/systemd/src/basic/hash-funcs.c index 234565ed..4a29f43c 100644 --- a/src/systemd/src/basic/hash-funcs.c +++ b/src/systemd/src/basic/hash-funcs.c @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. @@ -21,16 +20,12 @@ #include "nm-sd-adapt.h" -#include <string.h> - #include "hash-funcs.h" -#include "path-util.h" void string_hash_func(const void *p, struct siphash *state) { siphash24_compress(p, strlen(p) + 1, state); } -#if 0 /* NM_IGNORED */ int string_compare_func(const void *a, const void *b) { return strcmp(a, b); } @@ -40,56 +35,6 @@ const struct hash_ops string_hash_ops = { .compare = string_compare_func }; - -void path_hash_func(const void *p, struct siphash *state) { - const char *q = p; - size_t n; - - assert(q); - assert(state); - - /* Calculates a hash for a path in a way this duplicate inner slashes don't make a differences, and also - * whether there's a trailing slash or not. This fits well with the semantics of path_compare(), which does - * similar checks and also doesn't care for trailing slashes. Note that relative and absolute paths (i.e. those - * which begin in a slash or not) will hash differently though. */ - - n = strspn(q, "/"); - if (n > 0) { /* Eat up initial slashes, and add one "/" to the hash for all of them */ - siphash24_compress(q, 1, state); - q += n; - } - - for (;;) { - /* Determine length of next component */ - n = strcspn(q, "/"); - if (n == 0) /* Reached the end? */ - break; - - /* Add this component to the hash and skip over it */ - siphash24_compress(q, n, state); - q += n; - - /* How many slashes follow this component? */ - n = strspn(q, "/"); - if (q[n] == 0) /* Is this a trailing slash? If so, we are at the end, and don't care about the slashes anymore */ - break; - - /* We are not add the end yet. Hash exactly one slash for all of the ones we just encountered. */ - siphash24_compress(q, 1, state); - q += n; - } -} - -int path_compare_func(const void *a, const void *b) { - return path_compare(a, b); -} - -const struct hash_ops path_hash_ops = { - .hash = path_hash_func, - .compare = path_compare_func -}; -#endif /* NM_IGNORED */ - void trivial_hash_func(const void *p, struct siphash *state) { siphash24_compress(&p, sizeof(p), state); } @@ -119,7 +64,6 @@ const struct hash_ops uint64_hash_ops = { .compare = uint64_compare_func }; -#if 0 /* NM_IGNORED */ #if SIZEOF_DEV_T != 8 void devt_hash_func(const void *p, struct siphash *state) { siphash24_compress(p, sizeof(dev_t), state); @@ -137,4 +81,3 @@ const struct hash_ops devt_hash_ops = { .compare = devt_compare_func }; #endif -#endif /* NM_IGNORED */ diff --git a/src/systemd/src/basic/hash-funcs.h b/src/systemd/src/basic/hash-funcs.h index 945b4c25..299189d1 100644 --- a/src/systemd/src/basic/hash-funcs.h +++ b/src/systemd/src/basic/hash-funcs.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once /*** @@ -36,28 +35,29 @@ void string_hash_func(const void *p, struct siphash *state); int string_compare_func(const void *a, const void *b) _pure_; extern const struct hash_ops string_hash_ops; -void path_hash_func(const void *p, struct siphash *state); -int path_compare_func(const void *a, const void *b) _pure_; -extern const struct hash_ops path_hash_ops; - -/* This will compare the passed pointers directly, and will not dereference them. This is hence not useful for strings - * or suchlike. */ +/* This will compare the passed pointers directly, and will not + * dereference them. This is hence not useful for strings or + * suchlike. */ void trivial_hash_func(const void *p, struct siphash *state); int trivial_compare_func(const void *a, const void *b) _const_; extern const struct hash_ops trivial_hash_ops; -/* 32bit values we can always just embed in the pointer itself, but in order to support 32bit archs we need store 64bit - * values indirectly, since they don't fit in a pointer. */ +/* 32bit values we can always just embed in the pointer itself, but + * in order to support 32bit archs we need store 64bit values + * indirectly, since they don't fit in a pointer. */ void uint64_hash_func(const void *p, struct siphash *state); int uint64_compare_func(const void *a, const void *b) _pure_; extern const struct hash_ops uint64_hash_ops; -/* On some archs dev_t is 32bit, and on others 64bit. And sometimes it's 64bit on 32bit archs, and sometimes 32bit on - * 64bit archs. Yuck! */ +/* On some archs dev_t is 32bit, and on others 64bit. And sometimes + * it's 64bit on 32bit archs, and sometimes 32bit on 64bit archs. Yuck! */ #if SIZEOF_DEV_T != 8 void devt_hash_func(const void *p, struct siphash *state) _pure_; int devt_compare_func(const void *a, const void *b) _pure_; -extern const struct hash_ops devt_hash_ops; +extern const struct hash_ops devt_hash_ops = { + .hash = devt_hash_func, + .compare = devt_compare_func +}; #else #define devt_hash_func uint64_hash_func #define devt_compare_func uint64_compare_func diff --git a/src/systemd/src/basic/hashmap.c b/src/systemd/src/basic/hashmap.c index a76ec8e8..c95d4991 100644 --- a/src/systemd/src/basic/hashmap.c +++ b/src/systemd/src/basic/hashmap.c @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. @@ -28,14 +27,12 @@ #include "alloc-util.h" #include "hashmap.h" -#include "fileio.h" #include "macro.h" #include "mempool.h" #include "process-util.h" #include "random-util.h" #include "set.h" #include "siphash24.h" -#include "string-util.h" #include "strv.h" #include "util.h" @@ -231,8 +228,6 @@ struct HashmapBase { unsigned n_direct_entries:3; /* Number of entries in direct storage. * Only valid if !has_indirect. */ bool from_pool:1; /* whether was allocated from mempool */ - bool dirty:1; /* whether dirtied since last iterated_cache_get() */ - bool cached:1; /* whether this hashmap is being cached */ HASHMAP_DEBUG_FIELDS /* optional hashmap_debug_info */ }; @@ -252,17 +247,6 @@ struct Set { struct HashmapBase b; }; -typedef struct CacheMem { - const void **ptr; - size_t n_populated, n_allocated; - bool active:1; -} CacheMem; - -struct IteratedCache { - HashmapBase *hashmap; - CacheMem keys, values; -}; - DEFINE_MEMPOOL(hashmap_pool, Hashmap, 8); DEFINE_MEMPOOL(ordered_hashmap_pool, OrderedHashmap, 8); /* No need for a separate Set pool */ @@ -296,28 +280,6 @@ static const struct hashmap_type_info hashmap_type_info[_HASHMAP_TYPE_MAX] = { }, }; -#ifdef VALGRIND -__attribute__((destructor)) static void cleanup_pools(void) { - _cleanup_free_ char *t = NULL; - int r; - - /* Be nice to valgrind */ - - /* The pool is only allocated by the main thread, but the memory can - * be passed to other threads. Let's clean up if we are the main thread - * and no other threads are live. */ - if (!is_main_thread()) - return; - - r = get_proc_field("/proc/self/status", "Threads", WHITESPACE, &t); - if (r < 0 || !streq(t, "1")) - return; - - mempool_drop(&hashmap_pool); - mempool_drop(&ordered_hashmap_pool); -} -#endif - static unsigned n_buckets(HashmapBase *h) { return h->has_indirect ? h->indirect.n_buckets : hashmap_type_info[h->type].n_direct_buckets; @@ -366,11 +328,6 @@ static unsigned base_bucket_hash(HashmapBase *h, const void *p) { } #define bucket_hash(h, p) base_bucket_hash(HASHMAP_BASE(h), p) -static inline void base_set_dirty(HashmapBase *h) { - h->dirty = true; -} -#define hashmap_set_dirty(h) base_set_dirty(HASHMAP_BASE(h)) - static void get_hash_key(uint8_t hash_key[HASH_KEY_SIZE], bool reuse_is_ok) { static uint8_t current[HASH_KEY_SIZE]; static bool current_initialized = false; @@ -588,7 +545,6 @@ static void base_remove_entry(HashmapBase *h, unsigned idx) { bucket_mark_free(h, prev); n_entries_dec(h); - base_set_dirty(h); } #define remove_entry(h, idx) base_remove_entry(HASHMAP_BASE(h), idx) @@ -758,25 +714,6 @@ bool set_iterate(Set *s, Iterator *i, void **value) { (idx != IDX_NIL); \ (idx) = hashmap_iterate_entry((h), &(i))) -IteratedCache *internal_hashmap_iterated_cache_new(HashmapBase *h) { - IteratedCache *cache; - - assert(h); - assert(!h->cached); - - if (h->cached) - return NULL; - - cache = new0(IteratedCache, 1); - if (!cache) - return NULL; - - cache->hashmap = h; - h->cached = true; - - return cache; -} - static void reset_direct_storage(HashmapBase *h) { const struct hashmap_type_info *hi = &hashmap_type_info[h->type]; void *p; @@ -937,8 +874,6 @@ void internal_hashmap_clear(HashmapBase *h) { OrderedHashmap *lh = (OrderedHashmap*) h; lh->iterate_list_head = lh->iterate_list_tail = IDX_NIL; } - - base_set_dirty(h); } void internal_hashmap_clear_free(HashmapBase *h) { @@ -1083,8 +1018,6 @@ static int hashmap_base_put_boldly(HashmapBase *h, unsigned idx, h->debug.max_entries = MAX(h->debug.max_entries, n_entries(h)); #endif - base_set_dirty(h); - return 1; } #define hashmap_put_boldly(h, idx, swap, may_resize) \ @@ -1321,8 +1254,6 @@ int hashmap_replace(Hashmap *h, const void *key, void *value) { #endif e->b.key = key; e->value = value; - hashmap_set_dirty(h); - return 0; } @@ -1345,8 +1276,6 @@ int hashmap_update(Hashmap *h, const void *key, void *value) { e = plain_bucket_at(h, idx); e->value = value; - hashmap_set_dirty(h); - return 0; } @@ -1899,95 +1828,3 @@ int set_put_strsplit(Set *s, const char *v, const char *separators, ExtractFlags return r; } } - -/* expand the cachemem if needed, return true if newly (re)activated. */ -static int cachemem_maintain(CacheMem *mem, unsigned size) { - assert(mem); - - if (!GREEDY_REALLOC(mem->ptr, mem->n_allocated, size)) { - if (size > 0) - return -ENOMEM; - } - - if (!mem->active) { - mem->active = true; - return true; - } - - return false; -} - -int iterated_cache_get(IteratedCache *cache, const void ***res_keys, const void ***res_values, unsigned *res_n_entries) { - bool sync_keys = false, sync_values = false; - unsigned size; - int r; - - assert(cache); - assert(cache->hashmap); - - size = n_entries(cache->hashmap); - - if (res_keys) { - r = cachemem_maintain(&cache->keys, size); - if (r < 0) - return r; - - sync_keys = r; - } else - cache->keys.active = false; - - if (res_values) { - r = cachemem_maintain(&cache->values, size); - if (r < 0) - return r; - - sync_values = r; - } else - cache->values.active = false; - - if (cache->hashmap->dirty) { - if (cache->keys.active) - sync_keys = true; - if (cache->values.active) - sync_values = true; - - cache->hashmap->dirty = false; - } - - if (sync_keys || sync_values) { - unsigned i, idx; - Iterator iter; - - i = 0; - HASHMAP_FOREACH_IDX(idx, cache->hashmap, iter) { - struct hashmap_base_entry *e; - - e = bucket_at(cache->hashmap, idx); - - if (sync_keys) - cache->keys.ptr[i] = e->key; - if (sync_values) - cache->values.ptr[i] = entry_value(cache->hashmap, e); - i++; - } - } - - if (res_keys) - *res_keys = cache->keys.ptr; - if (res_values) - *res_values = cache->values.ptr; - if (res_n_entries) - *res_n_entries = size; - - return 0; -} - -IteratedCache *iterated_cache_free(IteratedCache *cache) { - if (cache) { - free(cache->keys.ptr); - free(cache->values.ptr); - free(cache); - } - - return NULL; -} diff --git a/src/systemd/src/basic/hashmap.h b/src/systemd/src/basic/hashmap.h index b6749103..c1089652 100644 --- a/src/systemd/src/basic/hashmap.h +++ b/src/systemd/src/basic/hashmap.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once /*** @@ -53,8 +52,6 @@ typedef struct Hashmap Hashmap; /* Maps keys to values */ typedef struct OrderedHashmap OrderedHashmap; /* Like Hashmap, but also remembers entry insertion order */ typedef struct Set Set; /* Stores just keys */ -typedef struct IteratedCache IteratedCache; /* Caches the iterated order of one of the above */ - /* Ideally the Iterator would be an opaque struct, but it is instantiated * by hashmap users, so the definition has to be here. Do not use its fields * directly. */ @@ -128,9 +125,6 @@ static inline OrderedHashmap *ordered_hashmap_free_free_free(OrderedHashmap *h) return (void*)hashmap_free_free_free(PLAIN_HASHMAP(h)); } -IteratedCache *iterated_cache_free(IteratedCache *cache); -int iterated_cache_get(IteratedCache *cache, const void ***res_keys, const void ***res_values, unsigned *res_n_entries); - HashmapBase *internal_hashmap_copy(HashmapBase *h); static inline Hashmap *hashmap_copy(Hashmap *h) { return (Hashmap*) internal_hashmap_copy(HASHMAP_BASE(h)); @@ -144,14 +138,6 @@ int internal_ordered_hashmap_ensure_allocated(OrderedHashmap **h, const struct h #define hashmap_ensure_allocated(h, ops) internal_hashmap_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS) #define ordered_hashmap_ensure_allocated(h, ops) internal_ordered_hashmap_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS) -IteratedCache *internal_hashmap_iterated_cache_new(HashmapBase *h); -static inline IteratedCache *hashmap_iterated_cache_new(Hashmap *h) { - return (IteratedCache*) internal_hashmap_iterated_cache_new(HASHMAP_BASE(h)); -} -static inline IteratedCache *ordered_hashmap_iterated_cache_new(OrderedHashmap *h) { - return (IteratedCache*) internal_hashmap_iterated_cache_new(HASHMAP_BASE(h)); -} - int hashmap_put(Hashmap *h, const void *key, void *value); static inline int ordered_hashmap_put(OrderedHashmap *h, const void *key, void *value) { return hashmap_put(PLAIN_HASHMAP(h), key, value); @@ -342,29 +328,6 @@ static inline void *ordered_hashmap_first(OrderedHashmap *h) { return internal_hashmap_first(HASHMAP_BASE(h)); } -#define hashmap_clear_with_destructor(_s, _f) \ - ({ \ - void *_item; \ - while ((_item = hashmap_steal_first(_s))) \ - _f(_item); \ - }) -#define hashmap_free_with_destructor(_s, _f) \ - ({ \ - hashmap_clear_with_destructor(_s, _f); \ - hashmap_free(_s); \ - }) -#define ordered_hashmap_clear_with_destructor(_s, _f) \ - ({ \ - void *_item; \ - while ((_item = ordered_hashmap_steal_first(_s))) \ - _f(_item); \ - }) -#define ordered_hashmap_free_with_destructor(_s, _f) \ - ({ \ - ordered_hashmap_clear_with_destructor(_s, _f); \ - ordered_hashmap_free(_s); \ - }) - /* no hashmap_next */ void *ordered_hashmap_next(OrderedHashmap *h, const void *key); @@ -407,7 +370,3 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedHashmap*, ordered_hashmap_free_free_free); #define _cleanup_ordered_hashmap_free_ _cleanup_(ordered_hashmap_freep) #define _cleanup_ordered_hashmap_free_free_ _cleanup_(ordered_hashmap_free_freep) #define _cleanup_ordered_hashmap_free_free_free_ _cleanup_(ordered_hashmap_free_free_freep) - -DEFINE_TRIVIAL_CLEANUP_FUNC(IteratedCache*, iterated_cache_free); - -#define _cleanup_iterated_cache_free_ _cleanup_(iterated_cache_freep) diff --git a/src/systemd/src/basic/hexdecoct.c b/src/systemd/src/basic/hexdecoct.c index e8e82b5f..e0ae83c1 100644 --- a/src/systemd/src/basic/hexdecoct.c +++ b/src/systemd/src/basic/hexdecoct.c @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. @@ -99,10 +98,7 @@ int unhexmem(const char *p, size_t l, void **mem, size_t *len) { assert(mem); assert(len); - assert(p || l == 0); - - if (l == (size_t) -1) - l = strlen(p); + assert(p); if (l % 2 != 0) return -EINVAL; @@ -134,7 +130,6 @@ int unhexmem(const char *p, size_t l, void **mem, size_t *len) { return 0; } -#if 0 /* NM_IGNORED */ /* https://tools.ietf.org/html/rfc4648#section-6 * Notice that base32hex differs from base32 in the alphabet it uses. * The distinction is that the base32hex representation preserves the @@ -167,8 +162,6 @@ char *base32hexmem(const void *p, size_t l, bool padding) { const uint8_t *x; size_t len; - assert(p || l == 0); - if (padding) /* five input bytes makes eight output bytes, padding is added so we must round up */ len = 8 * (l + 4) / 5; @@ -278,12 +271,7 @@ int unbase32hexmem(const char *p, size_t l, bool padding, void **mem, size_t *_l size_t len; unsigned pad = 0; - assert(p || l == 0); - assert(mem); - assert(_len); - - if (l == (size_t) -1) - l = strlen(p); + assert(p); /* padding ensures any base32hex input has input divisible by 8 */ if (padding && l % 8 != 0) @@ -533,9 +521,6 @@ ssize_t base64mem(const void *p, size_t l, char **out) { char *r, *z; const uint8_t *x; - assert(p || l == 0); - assert(out); - /* three input bytes makes four output bytes, padding is added so we must round up */ z = r = malloc(4 * (l + 2) / 3 + 1); if (!r) @@ -571,11 +556,10 @@ ssize_t base64mem(const void *p, size_t l, char **out) { return z - r; } -static int base64_append_width( - char **prefix, int plen, - const char *sep, int indent, - const void *p, size_t l, - int width) { +static int base64_append_width(char **prefix, int plen, + const char *sep, int indent, + const void *p, size_t l, + int width) { _cleanup_free_ char *x = NULL; char *t, *s; @@ -586,7 +570,7 @@ static int base64_append_width( if (len <= 0) return len; - lines = DIV_ROUND_UP(len, width); + lines = (len + width - 1) / width; slen = strlen_ptr(sep); t = realloc(*prefix, plen + 1 + slen + (indent + width + 1) * lines); @@ -614,148 +598,118 @@ static int base64_append_width( return 0; } -int base64_append( - char **prefix, int plen, - const void *p, size_t l, - int indent, int width) { - +int base64_append(char **prefix, int plen, + const void *p, size_t l, + int indent, int width) { if (plen > width / 2 || plen + indent > width) /* leave indent on the left, keep last column free */ return base64_append_width(prefix, plen, "\n", indent, p, l, width - indent - 1); else /* leave plen on the left, keep last column free */ return base64_append_width(prefix, plen, NULL, plen, p, l, width - plen - 1); -} - -static int unbase64_next(const char **p, size_t *l) { - int ret; - - assert(p); - assert(l); - - /* Find the next non-whitespace character, and decode it. If we find padding, we return it as INT_MAX. We - * greedily skip all preceeding and all following whitespace. */ - - for (;;) { - if (*l == 0) - return -EPIPE; - - if (!strchr(WHITESPACE, **p)) - break; - - /* Skip leading whitespace */ - (*p)++, (*l)--; - } - - if (**p == '=') - ret = INT_MAX; /* return padding as INT_MAX */ - else { - ret = unbase64char(**p); - if (ret < 0) - return ret; - } +}; - for (;;) { - (*p)++, (*l)--; - if (*l == 0) - break; - if (!strchr(WHITESPACE, **p)) - break; - - /* Skip following whitespace */ - } - - return ret; -} - -int unbase64mem(const char *p, size_t l, void **ret, size_t *ret_size) { - _cleanup_free_ uint8_t *buf = NULL; - const char *x; +int unbase64mem(const char *p, size_t l, void **mem, size_t *_len) { + _cleanup_free_ uint8_t *r = NULL; + int a, b, c, d; uint8_t *z; + const char *x; size_t len; - assert(p || l == 0); - assert(ret); - assert(ret_size); + assert(p); - if (l == (size_t) -1) - l = strlen(p); + /* padding ensures any base63 input has input divisible by 4 */ + if (l % 4 != 0) + return -EINVAL; - /* A group of four input bytes needs three output bytes, in case of padding we need to add two or three extra - bytes. Note that this calculation is an upper boundary, as we ignore whitespace while decoding */ - len = (l / 4) * 3 + (l % 4 != 0 ? (l % 4) - 1 : 0); + /* strip the padding */ + if (l > 0 && p[l - 1] == '=') + l--; + if (l > 0 && p[l - 1] == '=') + l--; - buf = malloc(len + 1); - if (!buf) - return -ENOMEM; + /* a group of four input bytes needs three output bytes, in case of + padding we need to add two or three extra bytes */ + len = (l / 4) * 3 + (l % 4 ? (l % 4) - 1 : 0); - for (x = p, z = buf;;) { - int a, b, c, d; /* a == 00XXXXXX; b == 00YYYYYY; c == 00ZZZZZZ; d == 00WWWWWW */ + z = r = malloc(len + 1); + if (!r) + return -ENOMEM; - a = unbase64_next(&x, &l); - if (a == -EPIPE) /* End of string */ - break; + for (x = p; x < p + (l / 4) * 4; x += 4) { + /* a == 00XXXXXX; b == 00YYYYYY; c == 00ZZZZZZ; d == 00WWWWWW */ + a = unbase64char(x[0]); if (a < 0) - return a; - if (a == INT_MAX) /* Padding is not allowed at the beginning of a 4ch block */ return -EINVAL; - b = unbase64_next(&x, &l); + b = unbase64char(x[1]); if (b < 0) - return b; - if (b == INT_MAX) /* Padding is not allowed at the second character of a 4ch block either */ return -EINVAL; - c = unbase64_next(&x, &l); + c = unbase64char(x[2]); if (c < 0) - return c; + return -EINVAL; - d = unbase64_next(&x, &l); + d = unbase64char(x[3]); if (d < 0) - return d; + return -EINVAL; - if (c == INT_MAX) { /* Padding at the third character */ + *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */ + *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */ + *(z++) = (uint8_t) c << 6 | (uint8_t) d; /* ZZWWWWWW */ + } - if (d != INT_MAX) /* If the third character is padding, the fourth must be too */ - return -EINVAL; + switch (l % 4) { + case 3: + a = unbase64char(x[0]); + if (a < 0) + return -EINVAL; - /* b == 00YY0000 */ - if (b & 15) - return -EINVAL; + b = unbase64char(x[1]); + if (b < 0) + return -EINVAL; - if (l > 0) /* Trailing rubbish? */ - return -ENAMETOOLONG; + c = unbase64char(x[2]); + if (c < 0) + return -EINVAL; - *(z++) = (uint8_t) a << 2 | (uint8_t) (b >> 4); /* XXXXXXYY */ - break; - } + /* c == 00ZZZZ00 */ + if (c & 3) + return -EINVAL; - if (d == INT_MAX) { - /* c == 00ZZZZ00 */ - if (c & 3) - return -EINVAL; + *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */ + *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */ - if (l > 0) /* Trailing rubbish? */ - return -ENAMETOOLONG; + break; + case 2: + a = unbase64char(x[0]); + if (a < 0) + return -EINVAL; - *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */ - *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */ - break; - } + b = unbase64char(x[1]); + if (b < 0) + return -EINVAL; - *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */ - *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */ - *(z++) = (uint8_t) c << 6 | (uint8_t) d; /* ZZWWWWWW */ + /* b == 00YY0000 */ + if (b & 15) + return -EINVAL; + + *(z++) = (uint8_t) a << 2 | (uint8_t) (b >> 4); /* XXXXXXYY */ + + break; + case 0: + + break; + default: + return -EINVAL; } *z = 0; - if (ret_size) - *ret_size = (size_t) (z - buf); - - *ret = buf; - buf = NULL; + *mem = r; + r = NULL; + *_len = len; return 0; } @@ -764,10 +718,7 @@ void hexdump(FILE *f, const void *p, size_t s) { const uint8_t *b = p; unsigned n = 0; - assert(b || s == 0); - - if (!f) - f = stdout; + assert(s == 0 || b); while (s > 0) { size_t i; @@ -805,4 +756,3 @@ void hexdump(FILE *f, const void *p, size_t s) { s -= 16; } } -#endif /* NM_IGNORED */ diff --git a/src/systemd/src/basic/hexdecoct.h b/src/systemd/src/basic/hexdecoct.h index 08d0a522..1ba2f69e 100644 --- a/src/systemd/src/basic/hexdecoct.h +++ b/src/systemd/src/basic/hexdecoct.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once /*** diff --git a/src/systemd/src/basic/hostname-util.c b/src/systemd/src/basic/hostname-util.c index 66b80727..be6e9e58 100644 --- a/src/systemd/src/basic/hostname-util.c +++ b/src/systemd/src/basic/hostname-util.c @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. @@ -27,15 +26,12 @@ #include <sys/utsname.h> #include <unistd.h> -#include "alloc-util.h" -#include "def.h" #include "fd-util.h" #include "fileio.h" #include "hostname-util.h" #include "macro.h" #include "string-util.h" -#if 0 /* NM_IGNORED */ bool hostname_is_set(void) { struct utsname u; @@ -51,6 +47,7 @@ bool hostname_is_set(void) { return true; } +#if 0 /* NM_IGNORED */ char* gethostname_malloc(void) { struct utsname u; @@ -226,88 +223,36 @@ int sethostname_idempotent(const char *s) { return 1; } -int shorten_overlong(const char *s, char **ret) { - char *h, *p; - - /* Shorten an overlong name to HOST_NAME_MAX or to the first dot, - * whatever comes earlier. */ - - assert(s); - - h = strdup(s); - if (!h) - return -ENOMEM; - - if (hostname_is_valid(h, false)) { - *ret = h; - return 0; - } - - p = strchr(h, '.'); - if (p) - *p = 0; - - strshorten(h, HOST_NAME_MAX); - - if (!hostname_is_valid(h, false)) { - free(h); - return -EDOM; - } - - *ret = h; - return 1; -} - -int read_etc_hostname_stream(FILE *f, char **ret) { - int r; - - assert(f); - assert(ret); - - for (;;) { - _cleanup_free_ char *line = NULL; - char *p; - - r = read_line(f, LONG_LINE_MAX, &line); - if (r < 0) - return r; - if (r == 0) /* EOF without any hostname? the file is empty, let's treat that exactly like no file at all: ENOENT */ - return -ENOENT; - - p = strstrip(line); - - /* File may have empty lines or comments, ignore them */ - if (!IN_SET(*p, '\0', '#')) { - char *copy; - - hostname_cleanup(p); /* normalize the hostname */ - - if (!hostname_is_valid(p, true)) /* check that the hostname we return is valid */ - return -EBADMSG; - - copy = strdup(p); - if (!copy) - return -ENOMEM; - - *ret = copy; - return 0; - } - } -} - -int read_etc_hostname(const char *path, char **ret) { +int read_hostname_config(const char *path, char **hostname) { _cleanup_fclose_ FILE *f = NULL; + char l[LINE_MAX]; + char *name = NULL; - assert(ret); - - if (!path) - path = "/etc/hostname"; + assert(path); + assert(hostname); f = fopen(path, "re"); if (!f) return -errno; - return read_etc_hostname_stream(f, ret); + /* may have comments, ignore them */ + FOREACH_LINE(l, f, return -errno) { + truncate_nl(l); + if (!IN_SET(l[0], '\0', '#')) { + /* found line with value */ + name = hostname_cleanup(l); + name = strdup(name); + if (!name) + return -ENOMEM; + break; + } + } + if (!name) + /* no non-empty line found */ + return -ENOENT; + + *hostname = name; + return 0; } #endif /* NM_IGNORED */ diff --git a/src/systemd/src/basic/hostname-util.h b/src/systemd/src/basic/hostname-util.h index edae52e3..7af4e6c7 100644 --- a/src/systemd/src/basic/hostname-util.h +++ b/src/systemd/src/basic/hostname-util.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once /*** @@ -21,7 +20,6 @@ ***/ #include <stdbool.h> -#include <stdio.h> #include "macro.h" @@ -40,7 +38,4 @@ bool is_gateway_hostname(const char *hostname); int sethostname_idempotent(const char *s); -int shorten_overlong(const char *s, char **ret); - -int read_etc_hostname_stream(FILE *f, char **ret); -int read_etc_hostname(const char *path, char **ret); +int read_hostname_config(const char *path, char **hostname); diff --git a/src/systemd/src/basic/in-addr-util.c b/src/systemd/src/basic/in-addr-util.c index b2b68089..2a02d90b 100644 --- a/src/systemd/src/basic/in-addr-util.c +++ b/src/systemd/src/basic/in-addr-util.c @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. @@ -333,7 +332,6 @@ int in_addr_from_string_auto(const char *s, int *ret_family, union in_addr_union return -EINVAL; } -#if 0 /* NM_IGNORED */ int in_addr_ifindex_from_string_auto(const char *s, int *family, union in_addr_union *ret, int *ifindex) { const char *suffix; int r, ifi = 0; @@ -374,7 +372,6 @@ int in_addr_ifindex_from_string_auto(const char *s, int *family, union in_addr_u return r; } -#endif /* NM_IGNORED */ unsigned char in4_addr_netmask_to_prefixlen(const struct in_addr *addr) { assert(addr); diff --git a/src/systemd/src/basic/in-addr-util.h b/src/systemd/src/basic/in-addr-util.h index acaae6d2..59f8eb7e 100644 --- a/src/systemd/src/basic/in-addr-util.h +++ b/src/systemd/src/basic/in-addr-util.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once /*** diff --git a/src/systemd/src/basic/io-util.c b/src/systemd/src/basic/io-util.c index 0f10ad7f..61b667f0 100644 --- a/src/systemd/src/basic/io-util.c +++ b/src/systemd/src/basic/io-util.c @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. @@ -35,7 +34,6 @@ int flush_fd(int fd) { .fd = fd, .events = POLLIN, }; - int count = 0; /* Read from the specified file descriptor, until POLLIN is not set anymore, throwing away everything * read. Note that some file descriptors (notable IP sockets) will trigger POLLIN even when no data can be read @@ -55,7 +53,7 @@ int flush_fd(int fd) { return -errno; } else if (r == 0) - return count; + return 0; l = read(fd, buf, sizeof(buf)); if (l < 0) { @@ -64,13 +62,11 @@ int flush_fd(int fd) { continue; if (errno == EAGAIN) - return count; + return 0; return -errno; } else if (l == 0) - return count; - - count += (int) l; + return 0; } } @@ -139,7 +135,7 @@ int loop_write(int fd, const void *buf, size_t nbytes, bool do_poll) { assert(fd >= 0); assert(buf); - if (_unlikely_(nbytes > (size_t) SSIZE_MAX)) + if (nbytes > (size_t) SSIZE_MAX) return -EINVAL; do { @@ -205,6 +201,7 @@ int fd_wait_for_event(int fd, int event, usec_t t) { r = ppoll(&pollfd, 1, t == USEC_INFINITY ? NULL : timespec_store(&ts, t), NULL); if (r < 0) return -errno; + if (r == 0) return 0; diff --git a/src/systemd/src/basic/io-util.h b/src/systemd/src/basic/io-util.h index d81610ad..d9b69add 100644 --- a/src/systemd/src/basic/io-util.h +++ b/src/systemd/src/basic/io-util.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once /*** diff --git a/src/systemd/src/basic/list.h b/src/systemd/src/basic/list.h index 7006c3e2..c3771a17 100644 --- a/src/systemd/src/basic/list.h +++ b/src/systemd/src/basic/list.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once /*** @@ -183,6 +182,3 @@ for ((i) = (p)->name##_next ? (p)->name##_next : (head); \ (i) != (p); \ (i) = (i)->name##_next ? (i)->name##_next : (head)) - -#define LIST_IS_EMPTY(head) \ - (!(head)) diff --git a/src/systemd/src/basic/log.h b/src/systemd/src/basic/log.h index b0e963b0..67fda3f9 100644 --- a/src/systemd/src/basic/log.h +++ b/src/systemd/src/basic/log.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once /*** @@ -20,16 +19,18 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include <errno.h> #include <stdarg.h> #include <stdbool.h> #include <stdlib.h> +#include <sys/signalfd.h> +#include <sys/socket.h> #include <syslog.h> -#include "macro.h" +#include "sd-id128.h" -/* Some structures we reference but don't want to pull in headers for */ -struct iovec; -struct signalfd_siginfo; +#include "macro.h" +#include "process-util.h" typedef enum LogRealm { LOG_REALM_SYSTEMD, @@ -50,6 +51,7 @@ typedef enum LogTarget{ LOG_TARGET_SYSLOG, LOG_TARGET_SYSLOG_OR_KMSG, LOG_TARGET_AUTO, /* console if stderr is tty, JOURNAL_OR_KMSG otherwise */ + LOG_TARGET_SAFE, /* console if stderr is tty, KMSG otherwise */ LOG_TARGET_NULL, _LOG_TARGET_MAX, _LOG_TARGET_INVALID = -1 @@ -96,6 +98,11 @@ int log_open(void); void log_close(void); void log_forget_fds(void); +void log_close_syslog(void); +void log_close_journal(void); +void log_close_kmsg(void); +void log_close_console(void); + void log_parse_environment_realm(LogRealm realm); #define log_parse_environment() \ log_parse_environment_realm(LOG_REALM) @@ -149,6 +156,19 @@ int log_object_internal( const char *extra, const char *format, ...) _printf_(10,11); +int log_object_internalv( + int level, + int error, + const char *file, + int line, + const char *func, + const char *object_field, + const char *object, + const char *extra_field, + const char *extra, + const char *format, + va_list ap) _printf_(10,0); + int log_struct_internal( int level, int error, @@ -165,8 +185,8 @@ int log_oom_internal( int log_format_iovec( struct iovec *iovec, - size_t iovec_len, - size_t *n, + unsigned iovec_len, + unsigned *n, bool newline_separator, int error, const char *format, @@ -178,7 +198,7 @@ int log_struct_iovec_internal( const char *file, int line, const char *func, - const struct iovec *input_iovec, + const struct iovec input_iovec[], size_t n_input_iovec); /* This modifies the buffer passed! */ @@ -191,7 +211,7 @@ int log_dump_internal( char *buffer); /* Logging for various assertions */ -_noreturn_ void log_assert_failed_realm( +noreturn void log_assert_failed_realm( LogRealm realm, const char *text, const char *file, @@ -200,7 +220,7 @@ _noreturn_ void log_assert_failed_realm( #define log_assert_failed(text, ...) \ log_assert_failed_realm(LOG_REALM, (text), __VA_ARGS__) -_noreturn_ void log_assert_failed_unreachable_realm( +noreturn void log_assert_failed_unreachable_realm( LogRealm realm, const char *text, const char *file, @@ -225,9 +245,9 @@ void log_assert_failed_return_realm( /* Logging with level */ #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_internal_realm(LOG_REALM_PLUS_LEVEL(_realm, _level), _e, \ + int _level = (level), _e = (error); \ + (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); \ }) @@ -237,15 +257,13 @@ void log_assert_failed_return_realm( #define log_full(level, ...) log_full_errno((level), 0, __VA_ARGS__) -int log_emergency_level(void); - /* Normal logging */ #define log_debug(...) log_full(LOG_DEBUG, __VA_ARGS__) #define log_info(...) log_full(LOG_INFO, __VA_ARGS__) #define log_notice(...) log_full(LOG_NOTICE, __VA_ARGS__) #define log_warning(...) log_full(LOG_WARNING, __VA_ARGS__) #define log_error(...) log_full(LOG_ERR, __VA_ARGS__) -#define log_emergency(...) log_full(log_emergency_level(), __VA_ARGS__) +#define log_emergency(...) log_full(getpid_cached() == 1 ? LOG_EMERG : LOG_ERR, __VA_ARGS__) /* Logging triggered by an errno-like error */ #define log_debug_errno(error, ...) log_full_errno(LOG_DEBUG, error, __VA_ARGS__) @@ -253,7 +271,7 @@ int log_emergency_level(void); #define log_notice_errno(error, ...) log_full_errno(LOG_NOTICE, error, __VA_ARGS__) #define log_warning_errno(error, ...) log_full_errno(LOG_WARNING, error, __VA_ARGS__) #define log_error_errno(error, ...) log_full_errno(LOG_ERR, error, __VA_ARGS__) -#define log_emergency_errno(error, ...) log_full_errno(log_emergency_level(), error, __VA_ARGS__) +#define log_emergency_errno(error, ...) log_full_errno(getpid_cached() == 1 ? LOG_EMERG : LOG_ERR, error, __VA_ARGS__) #ifdef LOG_TRACE # define log_trace(...) log_debug(__VA_ARGS__) @@ -289,20 +307,10 @@ LogTarget log_target_from_string(const char *s) _pure_; void log_received_signal(int level, const struct signalfd_siginfo *si); -/* If turned on, any requests for a log target involving "syslog" will be implicitly upgraded to the equivalent journal target */ void log_set_upgrade_syslog_to_journal(bool b); - -/* If turned on, and log_open() is called, we'll not use STDERR_FILENO for logging ever, but rather open /dev/console */ void log_set_always_reopen_console(bool b); - -/* If turned on, we'll open the log stream implicitly if needed on each individual log call. This is normally not - * desired as we want to reuse our logging streams. It is useful however */ void log_set_open_when_needed(bool b); -/* If turned on, then we'll never use IPC-based logging, i.e. never log to syslog or the journal. We'll only log to - * stderr, the console or kmsg */ -void log_set_prohibit_ipc(bool b); - int log_syntax_internal( const char *unit, int level, @@ -314,16 +322,6 @@ int log_syntax_internal( const char *func, const char *format, ...) _printf_(9, 10); -int log_syntax_invalid_utf8_internal( - const char *unit, - int level, - const char *config_file, - unsigned config_line, - const char *file, - int line, - const char *func, - const char *rvalue); - #define log_syntax(unit, level, config_file, config_line, error, ...) \ ({ \ int _level = (level), _e = (error); \ @@ -335,9 +333,10 @@ int log_syntax_invalid_utf8_internal( #define log_syntax_invalid_utf8(unit, level, config_file, config_line, rvalue) \ ({ \ int _level = (level); \ - (log_get_max_level() >= LOG_PRI(_level)) \ - ? log_syntax_invalid_utf8_internal(unit, _level, config_file, config_line, __FILE__, __LINE__, __func__, rvalue) \ - : -EINVAL; \ + if (log_get_max_level() >= LOG_PRI(_level)) { \ + _cleanup_free_ char *_p = NULL; \ + _p = utf8_escape_invalid(rvalue); \ + log_syntax_internal(unit, _level, config_file, config_line, 0, __FILE__, __LINE__, __func__, \ + "String is not UTF-8 clean, ignoring assignment: %s", strna(_p)); \ + } \ }) - -#define DEBUG_LOGGING _unlikely_(log_get_max_level() >= LOG_DEBUG) diff --git a/src/systemd/src/basic/macro.h b/src/systemd/src/basic/macro.h index 025a5db7..afcde459 100644 --- a/src/systemd/src/basic/macro.h +++ b/src/systemd/src/basic/macro.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once /*** @@ -48,31 +47,6 @@ #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)) -#else -#define _fallthrough_ -#endif -/* Define C11 noreturn without <stdnoreturn.h> and even on older gcc - * compiler versions */ -#ifndef _noreturn_ -#if __STDC_VERSION__ >= 201112L -#define _noreturn_ _Noreturn -#else -#define _noreturn_ __attribute__((noreturn)) -#endif -#endif - -#if !defined(HAS_FEATURE_MEMORY_SANITIZER) -# if defined(__has_feature) -# if __has_feature(memory_sanitizer) -# define HAS_FEATURE_MEMORY_SANITIZER 1 -# endif -# endif -# if !defined(HAS_FEATURE_MEMORY_SANITIZER) -# define HAS_FEATURE_MEMORY_SANITIZER 0 -# endif -#endif #if (defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))) || defined (__clang__) /* Temporarily disable some warnings */ @@ -168,25 +142,11 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) { return 1UL << (sizeof(u) * 8 - __builtin_clzl(u - 1UL)); } -#ifndef __COVERITY__ -# define VOID_0 ((void)0) -#else -# define VOID_0 ((void*)0) -#endif - #define ELEMENTSOF(x) \ __extension__ (__builtin_choose_expr( \ !__builtin_types_compatible_p(typeof(x), typeof(&*(x))), \ sizeof(x)/sizeof((x)[0]), \ - VOID_0)) - -/* - * STRLEN - return the length of a string literal, minus the trailing NUL byte. - * Contrary to strlen(), this is a constant expression. - * @x: a string literal. - */ -#define STRLEN(x) (sizeof(""x"") - 1) - + (void)0)) /* * container_of - cast a member of a structure out to the containing structure * @ptr: the pointer to the member. @@ -216,7 +176,7 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) { __builtin_constant_p(_B) && \ __builtin_types_compatible_p(typeof(_A), typeof(_B)), \ ((_A) > (_B)) ? (_A) : (_B), \ - VOID_0)) + (void)0)) /* takes two types and returns the size of the larger one */ #define MAXSIZE(A, B) (sizeof(union _packed_ { typeof(A) a; typeof(B) b; })) @@ -443,10 +403,21 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) { #endif #endif +/* Define C11 noreturn without <stdnoreturn.h> and even on older gcc + * compiler versions */ +#ifndef noreturn +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L +#define noreturn _Noreturn +#else +#define noreturn __attribute__((noreturn)) +#endif +#endif + #define DEFINE_TRIVIAL_CLEANUP_FUNC(type, func) \ static inline void func##p(type *p) { \ if (*p) \ func(*p); \ - } + } \ + struct __useless_struct_to_allow_trailing_semicolon__ #include "log.h" diff --git a/src/systemd/src/basic/mempool.c b/src/systemd/src/basic/mempool.c index 43ae59c9..c1635964 100644 --- a/src/systemd/src/basic/mempool.c +++ b/src/systemd/src/basic/mempool.c @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. diff --git a/src/systemd/src/basic/mempool.h b/src/systemd/src/basic/mempool.h index c9235c83..0618b8dd 100644 --- a/src/systemd/src/basic/mempool.h +++ b/src/systemd/src/basic/mempool.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once /*** diff --git a/src/systemd/src/basic/parse-util.c b/src/systemd/src/basic/parse-util.c index 44fae932..6d978e93 100644 --- a/src/systemd/src/basic/parse-util.c +++ b/src/systemd/src/basic/parse-util.c @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. @@ -28,9 +27,7 @@ #include <string.h> #include "alloc-util.h" -#include "errno-list.h" #include "extract-word.h" -#include "locale-util.h" #include "macro.h" #include "parse-util.h" #include "process-util.h" @@ -71,6 +68,7 @@ int parse_pid(const char *s, pid_t* ret_pid) { *ret_pid = pid; return 0; } +#endif /* NM_IGNORED */ int parse_mode(const char *s, mode_t *ret) { char *x; @@ -87,7 +85,7 @@ int parse_mode(const char *s, mode_t *ret) { l = strtol(s, &x, 8); if (errno > 0) return -errno; - if (!x || x == s || *x != 0) + if (!x || x == s || *x) return -EINVAL; if (l < 0 || l > 07777) return -ERANGE; @@ -237,6 +235,7 @@ int parse_size(const char *t, uint64_t base, uint64_t *size) { return 0; } +#if 0 /* NM_IGNORED */ int parse_range(const char *t, unsigned *lower, unsigned *upper) { _cleanup_free_ char *word = NULL; unsigned l, u; @@ -273,64 +272,7 @@ int parse_range(const char *t, unsigned *lower, unsigned *upper) { *upper = u; return 0; } - -int parse_errno(const char *t) { - int r, e; - - assert(t); - - r = errno_from_name(t); - if (r > 0) - return r; - - r = safe_atoi(t, &e); - if (r < 0) - return r; - - /* 0 is also allowed here */ - if (!errno_is_valid(e) && e != 0) - return -ERANGE; - - return e; -} - -int parse_syscall_and_errno(const char *in, char **name, int *error) { - _cleanup_free_ char *n = NULL; - char *p; - int e = -1; - - assert(in); - assert(name); - assert(error); - - /* - * This parse "syscall:errno" like "uname:EILSEQ", "@sync:255". - * If errno is omitted, then error is set to -1. - * Empty syscall name is not allowed. - * Here, we do not check that the syscall name is valid or not. - */ - - p = strchr(in, ':'); - if (p) { - e = parse_errno(p + 1); - if (e < 0) - return e; - - n = strndup(in, p - in); - } else - n = strdup(in); - - if (!n) - return -ENOMEM; - - if (isempty(n)) - return -EINVAL; - - *error = e; - *name = TAKE_PTR(n); - - return 0; -} +#endif /* NM_IGNORED */ char *format_bytes(char *buf, size_t l, uint64_t t) { unsigned i; @@ -372,15 +314,13 @@ finish: return buf; } -#endif /* NM_IGNORED */ -int safe_atou_full(const char *s, unsigned base, unsigned *ret_u) { +int safe_atou(const char *s, unsigned *ret_u) { char *x = NULL; unsigned long l; assert(s); assert(ret_u); - assert(base <= 16); /* strtoul() is happy to parse negative values, and silently * converts them to unsigned values without generating an @@ -393,10 +333,10 @@ int safe_atou_full(const char *s, unsigned base, unsigned *ret_u) { s += strspn(s, WHITESPACE); errno = 0; - l = strtoul(s, &x, base); + l = strtoul(s, &x, 0); if (errno > 0) return -errno; - if (!x || x == s || *x != 0) + if (!x || x == s || *x) return -EINVAL; if (s[0] == '-') return -ERANGE; @@ -418,7 +358,7 @@ int safe_atoi(const char *s, int *ret_i) { l = strtol(s, &x, 0); if (errno > 0) return -errno; - if (!x || x == s || *x != 0) + if (!x || x == s || *x) return -EINVAL; if ((long) (int) l != l) return -ERANGE; @@ -440,7 +380,7 @@ int safe_atollu(const char *s, long long unsigned *ret_llu) { l = strtoull(s, &x, 0); if (errno > 0) return -errno; - if (!x || x == s || *x != 0) + if (!x || x == s || *x) return -EINVAL; if (*s == '-') return -ERANGE; @@ -460,7 +400,7 @@ int safe_atolli(const char *s, long long int *ret_lli) { l = strtoll(s, &x, 0); if (errno > 0) return -errno; - if (!x || x == s || *x != 0) + if (!x || x == s || *x) return -EINVAL; *ret_lli = l; @@ -480,7 +420,7 @@ int safe_atou8(const char *s, uint8_t *ret) { l = strtoul(s, &x, 0); if (errno > 0) return -errno; - if (!x || x == s || *x != 0) + if (!x || x == s || *x) return -EINVAL; if (s[0] == '-') return -ERANGE; @@ -491,21 +431,20 @@ int safe_atou8(const char *s, uint8_t *ret) { return 0; } -int safe_atou16_full(const char *s, unsigned base, uint16_t *ret) { +int safe_atou16(const char *s, uint16_t *ret) { char *x = NULL; unsigned long l; assert(s); assert(ret); - assert(base <= 16); s += strspn(s, WHITESPACE); errno = 0; - l = strtoul(s, &x, base); + l = strtoul(s, &x, 0); if (errno > 0) return -errno; - if (!x || x == s || *x != 0) + if (!x || x == s || *x) return -EINVAL; if (s[0] == '-') return -ERANGE; @@ -527,7 +466,7 @@ int safe_atoi16(const char *s, int16_t *ret) { l = strtol(s, &x, 0); if (errno > 0) return -errno; - if (!x || x == s || *x != 0) + if (!x || x == s || *x) return -EINVAL; if ((long) (int16_t) l != l) return -ERANGE; @@ -536,11 +475,10 @@ int safe_atoi16(const char *s, int16_t *ret) { return 0; } -#if 0 /* NM_IGNORED */ int safe_atod(const char *s, double *ret_d) { - _cleanup_(freelocalep) locale_t loc = (locale_t) 0; char *x = NULL; double d = 0; + locale_t loc; assert(s); assert(ret_d); @@ -551,11 +489,16 @@ int safe_atod(const char *s, double *ret_d) { errno = 0; d = strtod_l(s, &x, loc); - if (errno > 0) + if (errno > 0) { + freelocale(loc); return -errno; - if (!x || x == s || *x != 0) + } + if (!x || x == s || *x) { + freelocale(loc); return -EINVAL; + } + freelocale(loc); *ret_d = (double) d; return 0; } @@ -598,20 +541,19 @@ int parse_fractional_part_u(const char **p, size_t digits, unsigned *res) { int parse_percent_unbounded(const char *p) { const char *pc, *n; - int r, v; + unsigned v; + int r; pc = endswith(p, "%"); if (!pc) return -EINVAL; n = strndupa(p, pc - p); - r = safe_atoi(n, &v); + r = safe_atou(n, &v); if (r < 0) return r; - if (v < 0) - return -ERANGE; - return v; + return (int) v; } int parse_percent(const char *p) { @@ -624,6 +566,7 @@ int parse_percent(const char *p) { return v; } +#if 0 /* NM_IGNORED */ int parse_nice(const char *p, int *ret) { int n, r; diff --git a/src/systemd/src/basic/parse-util.h b/src/systemd/src/basic/parse-util.h index 1605cc4f..dc09782c 100644 --- a/src/systemd/src/basic/parse-util.h +++ b/src/systemd/src/basic/parse-util.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once /*** @@ -38,34 +37,18 @@ int parse_ifindex(const char *s, int *ret); int parse_size(const char *t, uint64_t base, uint64_t *size); int parse_range(const char *t, unsigned *lower, unsigned *upper); -int parse_errno(const char *t); -int parse_syscall_and_errno(const char *in, char **name, int *error); #define FORMAT_BYTES_MAX 8 char *format_bytes(char *buf, size_t l, uint64_t t); -int safe_atou_full(const char *s, unsigned base, unsigned *ret_u); - -static inline int safe_atou(const char *s, unsigned *ret_u) { - return safe_atou_full(s, 0, ret_u); -} - +int safe_atou(const char *s, unsigned *ret_u); int safe_atoi(const char *s, int *ret_i); int safe_atollu(const char *s, unsigned long long *ret_u); int safe_atolli(const char *s, long long int *ret_i); int safe_atou8(const char *s, uint8_t *ret); -int safe_atou16_full(const char *s, unsigned base, uint16_t *ret); - -static inline int safe_atou16(const char *s, uint16_t *ret) { - return safe_atou16_full(s, 0, ret); -} - -static inline int safe_atoux16(const char *s, uint16_t *ret) { - return safe_atou16_full(s, 16, ret); -} - +int safe_atou16(const char *s, uint16_t *ret); int safe_atoi16(const char *s, int16_t *ret); static inline int safe_atou32(const char *s, uint32_t *ret_u) { diff --git a/src/systemd/src/basic/path-util.c b/src/systemd/src/basic/path-util.c index 23827c19..1bdcc653 100644 --- a/src/systemd/src/basic/path-util.c +++ b/src/systemd/src/basic/path-util.c @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. @@ -84,36 +83,14 @@ char *path_make_absolute(const char *p, const char *prefix) { /* Makes every item in the list an absolute path by prepending * the prefix, if specified and necessary */ - if (path_is_absolute(p) || isempty(prefix)) + if (path_is_absolute(p) || !prefix) return strdup(p); - if (endswith(prefix, "/")) - return strjoin(prefix, p); - else - return strjoin(prefix, "/", p); -} - -int safe_getcwd(char **ret) { - char *cwd; - - cwd = get_current_dir_name(); - if (!cwd) - return negative_errno(); - - /* Let's make sure the directory is really absolute, to protect us from the logic behind - * CVE-2018-1000001 */ - if (cwd[0] != '/') { - free(cwd); - return -ENOMEDIUM; - } - - *ret = cwd; - return 0; + return strjoin(prefix, "/", p); } int path_make_absolute_cwd(const char *p, char **ret) { char *c; - int r; assert(p); assert(ret); @@ -126,14 +103,11 @@ int path_make_absolute_cwd(const char *p, char **ret) { else { _cleanup_free_ char *cwd = NULL; - r = safe_getcwd(&cwd); - if (r < 0) - return r; + cwd = get_current_dir_name(); + if (!cwd) + return negative_errno(); - if (endswith(cwd, "/")) - c = strjoin(cwd, p); - else - c = strjoin(cwd, "/", p); + c = strjoin(cwd, "/", p); } if (!c) return -ENOMEM; @@ -251,8 +225,8 @@ int path_strv_make_absolute_cwd(char **l) { if (r < 0) return r; - path_kill_slashes(t); - free_and_replace(*s, t); + free(*s); + *s = t; } return 0; @@ -293,7 +267,8 @@ char **path_strv_resolve(char **l, const char *root) { r = chase_symlinks(t, root, 0, &u); if (r == -ENOENT) { if (root) { - u = TAKE_PTR(orig); + u = orig; + orig = NULL; free(t); } else u = t; @@ -567,7 +542,7 @@ bool paths_check_timestamp(const char* const* paths, usec_t *timestamp, bool upd assert(timestamp); - if (!paths) + if (paths == NULL) return false; STRV_FOREACH(i, paths) { @@ -731,37 +706,6 @@ char* dirname_malloc(const char *path) { return dir2; } - -const char *last_path_component(const char *path) { - /* Finds the last component of the path, preserving the - * optional trailing slash that signifies a directory. - * a/b/c → c - * a/b/c/ → c/ - * / → / - * // → / - * /foo/a → a - * /foo/a/ → a/ - * This is different than basename, which returns "" when - * a trailing slash is present. - */ - - unsigned l, k; - - l = k = strlen(path); - if (l == 0) /* special case — an empty string */ - return path; - - while (k > 0 && path[k-1] == '/') - k--; - - if (k == 0) /* the root directory */ - return path + l - 1; - - while (k > 0 && path[k-1] != '/') - k--; - - return path + k; -} #endif /* NM_IGNORED */ bool filename_is_valid(const char *p) { @@ -784,7 +728,7 @@ bool filename_is_valid(const char *p) { } #if 0 /* NM_IGNORED */ -bool path_is_normalized(const char *p) { +bool path_is_safe(const char *p) { if (isempty(p)) return false; @@ -798,6 +742,7 @@ bool path_is_normalized(const char *p) { if (strlen(p)+1 > PATH_MAX) return false; + /* The following two checks are not really dangerous, but hey, they still are confusing */ if (startswith(p, "./") || endswith(p, "/.") || strstr(p, "/./")) return false; @@ -913,9 +858,7 @@ int systemd_installation_has_version(const char *root, unsigned minimal_version) * for Gentoo which does a merge without making /lib a symlink. */ "lib/systemd/libsystemd-shared-*.so\0" - "lib64/systemd/libsystemd-shared-*.so\0" - "usr/lib/systemd/libsystemd-shared-*.so\0" - "usr/lib64/systemd/libsystemd-shared-*.so\0") { + "usr/lib/systemd/libsystemd-shared-*.so\0") { _cleanup_strv_free_ char **names = NULL; _cleanup_free_ char *path = NULL; diff --git a/src/systemd/src/basic/path-util.h b/src/systemd/src/basic/path-util.h index 8848abe9..399ed5f9 100644 --- a/src/systemd/src/basic/path-util.h +++ b/src/systemd/src/basic/path-util.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once /*** @@ -29,14 +28,8 @@ #include "time-util.h" #if 0 /* NM_IGNORED */ -#if HAVE_SPLIT_BIN -# define PATH_SBIN_BIN(x) x "sbin:" x "bin" -#else -# define PATH_SBIN_BIN(x) x "bin" -#endif - -#define DEFAULT_PATH_NORMAL PATH_SBIN_BIN("/usr/local/") ":" PATH_SBIN_BIN("/usr/") -#define DEFAULT_PATH_SPLIT_USR DEFAULT_PATH_NORMAL ":" PATH_SBIN_BIN("/") +#define DEFAULT_PATH_NORMAL "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin" +#define DEFAULT_PATH_SPLIT_USR DEFAULT_PATH_NORMAL ":/sbin:/bin" #if HAVE_SPLIT_USR # define DEFAULT_PATH DEFAULT_PATH_SPLIT_USR @@ -49,7 +42,6 @@ bool is_path(const char *p) _pure_; int path_split_and_make_absolute(const char *p, char ***ret); bool path_is_absolute(const char *p) _pure_; char* path_make_absolute(const char *p, const char *prefix); -int safe_getcwd(char **ret); int path_make_absolute_cwd(const char *p, char **ret); int path_make_relative(const char *from_dir, const char *to_path, char **_r); char* path_kill_slashes(char *path); @@ -139,10 +131,9 @@ char *prefix_root(const char *root, const char *path); int parse_path_argument_and_warn(const char *path, bool suppress_root, char **arg); char* dirname_malloc(const char *path); -const char *last_path_component(const char *path); bool filename_is_valid(const char *p) _pure_; -bool path_is_normalized(const char *p) _pure_; +bool path_is_safe(const char *p) _pure_; char *file_in_same_dir(const char *path, const char *filename); diff --git a/src/systemd/src/basic/prioq.c b/src/systemd/src/basic/prioq.c index 1e81bc71..64ad638e 100644 --- a/src/systemd/src/basic/prioq.c +++ b/src/systemd/src/basic/prioq.c @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. @@ -175,7 +174,7 @@ int prioq_put(Prioq *q, void *data, unsigned *idx) { struct prioq_item *j; n = MAX((q->n_items+1) * 2, 16u); - j = reallocarray(q->items, n, sizeof(struct prioq_item)); + j = realloc(q->items, sizeof(struct prioq_item) * n); if (!j) return -ENOMEM; diff --git a/src/systemd/src/basic/prioq.h b/src/systemd/src/basic/prioq.h index a222955d..113c73d0 100644 --- a/src/systemd/src/basic/prioq.h +++ b/src/systemd/src/basic/prioq.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once /*** diff --git a/src/systemd/src/basic/process-util.c b/src/systemd/src/basic/process-util.c index 4128ac54..272030d1 100644 --- a/src/systemd/src/basic/process-util.c +++ b/src/systemd/src/basic/process-util.c @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. @@ -28,7 +27,6 @@ #include <signal.h> #include <stdbool.h> #include <stdio.h> -#include <stdio_ext.h> #include <stdlib.h> #include <string.h> #include <sys/mman.h> @@ -60,7 +58,6 @@ #include "stat-util.h" #include "string-table.h" #include "string-util.h" -#include "terminal-util.h" #include "user-util.h" #include "util.h" @@ -137,8 +134,6 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char * return -errno; } - (void) __fsetlocking(f, FSETLOCKING_BYCALLER); - if (max_length == 1) { /* If there's only room for one byte, return the empty string */ @@ -302,17 +297,10 @@ int rename_process(const char name[]) { if (isempty(name)) return -EINVAL; /* let's not confuse users unnecessarily with an empty name */ - if (!is_main_thread()) - return -EPERM; /* Let's not allow setting the process name from other threads than the main one, as we - * cache things without locking, and we make assumptions that PR_SET_NAME sets the - * process name that isn't correct on any other threads */ - l = strlen(name); - /* First step, change the comm field. The main thread's comm is identical to the process comm. This means we - * can use PR_SET_NAME, which sets the thread name for the calling thread. */ - if (prctl(PR_SET_NAME, name) < 0) - log_debug_errno(errno, "PR_SET_NAME failed: %m"); + /* First step, change the comm field. */ + (void) prctl(PR_SET_NAME, name); if (l > 15) /* Linux process names can be 15 chars at max */ truncated = true; @@ -403,61 +391,35 @@ use_saved_argv: } int is_kernel_thread(pid_t pid) { - _cleanup_free_ char *line = NULL; - unsigned long long flags; - size_t l, i; const char *p; - char *q; - int r; + size_t count; + char c; + bool eof; + FILE *f; if (IN_SET(pid, 0, 1) || pid == getpid_cached()) /* pid 1, and we ourselves certainly aren't a kernel thread */ return 0; - if (!pid_is_valid(pid)) - return -EINVAL; - p = procfs_file_alloca(pid, "stat"); - r = read_one_line_file(p, &line); - if (r == -ENOENT) - return -ESRCH; - if (r < 0) - return r; + assert(pid > 1); - /* Skip past the comm field */ - q = strrchr(line, ')'); - if (!q) - return -EINVAL; - q++; - - /* Skip 6 fields to reach the flags field */ - for (i = 0; i < 6; i++) { - l = strspn(q, WHITESPACE); - if (l < 1) - return -EINVAL; - q += l; - - l = strcspn(q, WHITESPACE); - if (l < 1) - return -EINVAL; - q += l; + p = procfs_file_alloca(pid, "cmdline"); + f = fopen(p, "re"); + if (!f) { + if (errno == ENOENT) + return -ESRCH; + return -errno; } - /* Skip preceeding whitespace */ - l = strspn(q, WHITESPACE); - if (l < 1) - return -EINVAL; - q += l; + count = fread(&c, 1, 1, f); + eof = feof(f); + fclose(f); - /* Truncate the rest */ - l = strcspn(q, WHITESPACE); - if (l < 1) - return -EINVAL; - q[l] = 0; + /* Kernel threads have an empty cmdline */ - r = safe_atollu(q, &flags); - if (r < 0) - return r; + if (count <= 0) + return eof ? 1 : -errno; - return !!(flags & PF_KTHREAD); + return 0; } int get_process_capeff(pid_t pid, char **capeff) { @@ -529,8 +491,6 @@ static int get_process_id(pid_t pid, const char *field, uid_t *uid) { return -errno; } - (void) __fsetlocking(f, FSETLOCKING_BYCALLER); - FOREACH_LINE(line, f, return -errno) { char *l; @@ -609,8 +569,6 @@ int get_process_environ(pid_t pid, char **env) { return -errno; } - (void) __fsetlocking(f, FSETLOCKING_BYCALLER); - while ((c = fgetc(f)) != EOF) { if (!GREEDY_REALLOC(outcome, allocated, sz + 5)) return -ENOMEM; @@ -628,7 +586,8 @@ int get_process_environ(pid_t pid, char **env) { } else outcome[sz] = '\0'; - *env = TAKE_PTR(outcome); + *env = outcome; + outcome = NULL; return 0; } @@ -715,104 +674,32 @@ int wait_for_terminate(pid_t pid, siginfo_t *status) { * A warning is emitted if the process terminates abnormally, * and also if it returns non-zero unless check_exit_code is true. */ -int wait_for_terminate_and_check(const char *name, pid_t pid, WaitFlags flags) { - _cleanup_free_ char *buffer = NULL; +int wait_for_terminate_and_warn(const char *name, pid_t pid, bool check_exit_code) { + int r; siginfo_t status; - int r, prio; + assert(name); assert(pid > 1); - if (!name) { - r = get_process_comm(pid, &buffer); - if (r < 0) - log_debug_errno(r, "Failed to acquire process name of " PID_FMT ", ignoring: %m", pid); - else - name = buffer; - } - - prio = flags & WAIT_LOG_ABNORMAL ? LOG_ERR : LOG_DEBUG; - r = wait_for_terminate(pid, &status); if (r < 0) - return log_full_errno(prio, r, "Failed to wait for %s: %m", strna(name)); + return log_warning_errno(r, "Failed to wait for %s: %m", name); if (status.si_code == CLD_EXITED) { - if (status.si_status != EXIT_SUCCESS) - log_full(flags & WAIT_LOG_NON_ZERO_EXIT_STATUS ? LOG_ERR : LOG_DEBUG, - "%s failed with exit status %i.", strna(name), status.si_status); + if (status.si_status != 0) + log_full(check_exit_code ? LOG_WARNING : LOG_DEBUG, + "%s failed with error code %i.", name, status.si_status); else log_debug("%s succeeded.", name); return status.si_status; - } else if (IN_SET(status.si_code, CLD_KILLED, CLD_DUMPED)) { - log_full(prio, "%s terminated by signal %s.", strna(name), signal_to_string(status.si_status)); + log_warning("%s terminated by signal %s.", name, signal_to_string(status.si_status)); return -EPROTO; } - log_full(prio, "%s failed due to unknown reason.", strna(name)); - return -EPROTO; -} - -/* - * Return values: - * < 0 : wait_for_terminate_with_timeout() failed to get the state of the - * process, the process timed out, the process was terminated by a - * signal, or failed for an unknown reason. - * >=0 : The process terminated normally with no failures. - * - * Success is indicated by a return value of zero, a timeout is indicated - * by ETIMEDOUT, and all other child failure states are indicated by error - * is indicated by a non-zero value. - */ -int wait_for_terminate_with_timeout(pid_t pid, usec_t timeout) { - sigset_t mask; - int r; - usec_t until; - - assert_se(sigemptyset(&mask) == 0); - assert_se(sigaddset(&mask, SIGCHLD) == 0); - - /* Drop into a sigtimewait-based timeout. Waiting for the - * pid to exit. */ - until = now(CLOCK_MONOTONIC) + timeout; - for (;;) { - usec_t n; - siginfo_t status = {}; - struct timespec ts; - - n = now(CLOCK_MONOTONIC); - if (n >= until) - break; - - r = sigtimedwait(&mask, NULL, timespec_store(&ts, until - n)) < 0 ? -errno : 0; - /* Assuming we woke due to the child exiting. */ - if (waitid(P_PID, pid, &status, WEXITED|WNOHANG) == 0) { - if (status.si_pid == pid) { - /* This is the correct child.*/ - if (status.si_code == CLD_EXITED) - return (status.si_status == 0) ? 0 : -EPROTO; - else - return -EPROTO; - } - } - /* Not the child, check for errors and proceed appropriately */ - if (r < 0) { - switch (r) { - case -EAGAIN: - /* Timed out, child is likely hung. */ - return -ETIMEDOUT; - case -EINTR: - /* Received a different signal and should retry */ - continue; - default: - /* Return any unexpected errors */ - return r; - } - } - } - + log_warning("%s failed due to unknown reason.", name); return -EPROTO; } @@ -824,8 +711,6 @@ void sigkill_wait(pid_t pid) { } void sigkill_waitp(pid_t *pid) { - PROTECT_ERRNO; - if (!pid) return; if (*pid <= 1) @@ -834,13 +719,6 @@ void sigkill_waitp(pid_t *pid) { sigkill_wait(*pid); } -void sigterm_wait(pid_t pid) { - assert(pid > 1); - - if (kill_and_sigcont(pid, SIGTERM) > 0) - (void) wait_for_terminate(pid, NULL); -} - int kill_and_sigcont(pid_t pid, int sig) { int r; @@ -854,33 +732,17 @@ int kill_and_sigcont(pid_t pid, int sig) { return r; } -int getenv_for_pid(pid_t pid, const char *field, char **ret) { +int getenv_for_pid(pid_t pid, const char *field, char **_value) { _cleanup_fclose_ FILE *f = NULL; char *value = NULL; + int r; bool done = false; - const char *path; size_t l; + const char *path; assert(pid >= 0); assert(field); - assert(ret); - - if (pid == 0 || pid == getpid_cached()) { - const char *e; - - e = getenv(field); - if (!e) { - *ret = NULL; - return 0; - } - - value = strdup(e); - if (!value) - return -ENOMEM; - - *ret = value; - return 1; - } + assert(_value); path = procfs_file_alloca(pid, "environ"); @@ -888,13 +750,11 @@ int getenv_for_pid(pid_t pid, const char *field, char **ret) { if (!f) { if (errno == ENOENT) return -ESRCH; - return -errno; } - (void) __fsetlocking(f, FSETLOCKING_BYCALLER); - l = strlen(field); + r = 0; do { char line[LINE_MAX]; @@ -919,14 +779,14 @@ int getenv_for_pid(pid_t pid, const char *field, char **ret) { if (!value) return -ENOMEM; - *ret = value; - return 1; + r = 1; + break; } } while (!done); - *ret = NULL; - return 0; + *_value = value; + return r; } bool pid_is_unwaited(pid_t pid) { @@ -993,7 +853,7 @@ bool is_main_thread(void) { } #if 0 /* NM_IGNORED */ -_noreturn_ void freeze(void) { +noreturn void freeze(void) { log_close(); @@ -1002,17 +862,6 @@ _noreturn_ void freeze(void) { sync(); - /* Let's not freeze right away, but keep reaping zombies. */ - for (;;) { - int r; - siginfo_t si = {}; - - r = waitid(P_ALL, 0, &si, WEXITED); - if (r < 0 && errno != EINTR) - break; - } - - /* waitid() failed with an unexpected error, things are really borked. Freeze now! */ for (;;) pause(); } @@ -1161,7 +1010,7 @@ int ioprio_parse_priority(const char *s, int *ret) { static pid_t cached_pid = CACHED_PID_UNSET; -void reset_cached_pid(void) { +static void reset_cached_pid(void) { /* Invoked in the child after a fork(), i.e. at the first moment the PID changed */ cached_pid = CACHED_PID_UNSET; } @@ -1173,7 +1022,6 @@ extern int __register_atfork(void (*prepare) (void), void (*parent) (void), void extern void* __dso_handle __attribute__ ((__weak__)); pid_t getpid_cached(void) { - static bool installed = false; pid_t current_value; /* getpid_cached() is much like getpid(), but caches the value in local memory, to avoid having to invoke a @@ -1192,20 +1040,12 @@ pid_t getpid_cached(void) { case CACHED_PID_UNSET: { /* Not initialized yet, then do so now */ pid_t new_pid; - new_pid = raw_getpid(); - - if (!installed) { - /* __register_atfork() either returns 0 or -ENOMEM, in its glibc implementation. Since it's - * only half-documented (glibc doesn't document it but LSB does — though only superficially) - * we'll check for errors only in the most generic fashion possible. */ - - if (__register_atfork(NULL, NULL, reset_cached_pid, __dso_handle) != 0) { - /* OOM? Let's try again later */ - cached_pid = CACHED_PID_UNSET; - return new_pid; - } + new_pid = getpid(); - installed = true; + if (__register_atfork(NULL, NULL, reset_cached_pid, __dso_handle) != 0) { + /* OOM? Let's try again later */ + cached_pid = CACHED_PID_UNSET; + return new_pid; } cached_pid = new_pid; @@ -1213,7 +1053,7 @@ pid_t getpid_cached(void) { } case CACHED_PID_BUSY: /* Somebody else is currently initializing */ - return raw_getpid(); + return getpid(); default: /* Properly initialized */ return current_value; @@ -1221,252 +1061,6 @@ pid_t getpid_cached(void) { } #if 0 /* NM_IGNORED */ -int must_be_root(void) { - - if (geteuid() == 0) - return 0; - - log_error("Need to be root."); - return -EPERM; -} - -int safe_fork_full( - const char *name, - const int except_fds[], - size_t n_except_fds, - ForkFlags flags, - pid_t *ret_pid) { - - pid_t original_pid, pid; - sigset_t saved_ss, ss; - bool block_signals = false; - int prio, r; - - /* A wrapper around fork(), that does a couple of important initializations in addition to mere forking. Always - * returns the child's PID in *ret_pid. Returns == 0 in the child, and > 0 in the parent. */ - - prio = flags & FORK_LOG ? LOG_ERR : LOG_DEBUG; - - original_pid = getpid_cached(); - - if (flags & (FORK_RESET_SIGNALS|FORK_DEATHSIG)) { - - /* We temporarily block all signals, so that the new child has them blocked initially. This way, we can - * be sure that SIGTERMs are not lost we might send to the child. */ - - if (sigfillset(&ss) < 0) - return log_full_errno(prio, errno, "Failed to reset signal set: %m"); - - block_signals = true; - - } else if (flags & FORK_WAIT) { - - /* Let's block SIGCHLD at least, so that we can safely watch for the child process */ - - if (sigemptyset(&ss) < 0) - return log_full_errno(prio, errno, "Failed to clear signal set: %m"); - - if (sigaddset(&ss, SIGCHLD) < 0) - return log_full_errno(prio, errno, "Failed to add SIGCHLD to signal set: %m"); - - block_signals = true; - } - - if (block_signals) - if (sigprocmask(SIG_SETMASK, &ss, &saved_ss) < 0) - return log_full_errno(prio, errno, "Failed to set signal mask: %m"); - - if (flags & FORK_NEW_MOUNTNS) - pid = raw_clone(SIGCHLD|CLONE_NEWNS); - else - pid = fork(); - if (pid < 0) { - r = -errno; - - if (block_signals) /* undo what we did above */ - (void) sigprocmask(SIG_SETMASK, &saved_ss, NULL); - - return log_full_errno(prio, r, "Failed to fork: %m"); - } - if (pid > 0) { - /* We are in the parent process */ - - log_debug("Successfully forked off '%s' as PID " PID_FMT ".", strna(name), pid); - - if (flags & FORK_WAIT) { - r = wait_for_terminate_and_check(name, pid, (flags & FORK_LOG ? WAIT_LOG : 0)); - if (r < 0) - return r; - if (r != EXIT_SUCCESS) /* exit status > 0 should be treated as failure, too */ - return -EPROTO; - } - - if (block_signals) /* undo what we did above */ - (void) sigprocmask(SIG_SETMASK, &saved_ss, NULL); - - if (ret_pid) - *ret_pid = pid; - - return 1; - } - - /* We are in the child process */ - - if (flags & FORK_REOPEN_LOG) { - /* Close the logs if requested, before we log anything. And make sure we reopen it if needed. */ - log_close(); - log_set_open_when_needed(true); - } - - if (name) { - r = rename_process(name); - if (r < 0) - log_full_errno(flags & FORK_LOG ? LOG_WARNING : LOG_DEBUG, - r, "Failed to rename process, ignoring: %m"); - } - - if (flags & FORK_DEATHSIG) - if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0) { - log_full_errno(prio, errno, "Failed to set death signal: %m"); - _exit(EXIT_FAILURE); - } - - if (flags & FORK_RESET_SIGNALS) { - r = reset_all_signal_handlers(); - if (r < 0) { - log_full_errno(prio, r, "Failed to reset signal handlers: %m"); - _exit(EXIT_FAILURE); - } - - /* This implicitly undoes the signal mask stuff we did before the fork()ing above */ - r = reset_signal_mask(); - if (r < 0) { - log_full_errno(prio, r, "Failed to reset signal mask: %m"); - _exit(EXIT_FAILURE); - } - } else if (block_signals) { /* undo what we did above */ - if (sigprocmask(SIG_SETMASK, &saved_ss, NULL) < 0) { - log_full_errno(prio, errno, "Failed to restore signal mask: %m"); - _exit(EXIT_FAILURE); - } - } - - if (flags & FORK_DEATHSIG) { - pid_t ppid; - /* Let's see if the parent PID is still the one we started from? If not, then the parent - * already died by the time we set PR_SET_PDEATHSIG, hence let's emulate the effect */ - - ppid = getppid(); - if (ppid == 0) - /* Parent is in a differn't PID namespace. */; - else if (ppid != original_pid) { - log_debug("Parent died early, raising SIGTERM."); - (void) raise(SIGTERM); - _exit(EXIT_FAILURE); - } - } - - if (flags & FORK_CLOSE_ALL_FDS) { - /* Close the logs here in case it got reopened above, as close_all_fds() would close them for us */ - log_close(); - - r = close_all_fds(except_fds, n_except_fds); - if (r < 0) { - log_full_errno(prio, r, "Failed to close all file descriptors: %m"); - _exit(EXIT_FAILURE); - } - } - - /* When we were asked to reopen the logs, do so again now */ - if (flags & FORK_REOPEN_LOG) { - log_open(); - log_set_open_when_needed(false); - } - - if (flags & FORK_NULL_STDIO) { - r = make_null_stdio(); - if (r < 0) { - log_full_errno(prio, r, "Failed to connect stdin/stdout to /dev/null: %m"); - _exit(EXIT_FAILURE); - } - } - - if (ret_pid) - *ret_pid = getpid_cached(); - - return 0; -} - -int fork_agent(const char *name, const int except[], unsigned n_except, pid_t *ret_pid, const char *path, ...) { - bool stdout_is_tty, stderr_is_tty; - unsigned n, i; - va_list ap; - char **l; - int r; - - assert(path); - - /* Spawns a temporary TTY agent, making sure it goes away when we go away */ - - r = safe_fork_full(name, except, n_except, FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS, ret_pid); - if (r < 0) - return r; - if (r > 0) - return 0; - - /* In the child: */ - - stdout_is_tty = isatty(STDOUT_FILENO); - stderr_is_tty = isatty(STDERR_FILENO); - - if (!stdout_is_tty || !stderr_is_tty) { - int fd; - - /* Detach from stdout/stderr. and reopen - * /dev/tty for them. This is important to - * ensure that when systemctl is started via - * popen() or a similar call that expects to - * read EOF we actually do generate EOF and - * not delay this indefinitely by because we - * keep an unused copy of stdin around. */ - fd = open("/dev/tty", O_WRONLY); - if (fd < 0) { - log_error_errno(errno, "Failed to open /dev/tty: %m"); - _exit(EXIT_FAILURE); - } - - if (!stdout_is_tty && dup2(fd, STDOUT_FILENO) < 0) { - log_error_errno(errno, "Failed to dup2 /dev/tty: %m"); - _exit(EXIT_FAILURE); - } - - if (!stderr_is_tty && dup2(fd, STDERR_FILENO) < 0) { - log_error_errno(errno, "Failed to dup2 /dev/tty: %m"); - _exit(EXIT_FAILURE); - } - - safe_close_above_stdio(fd); - } - - /* Count arguments */ - va_start(ap, path); - for (n = 0; va_arg(ap, char*); n++) - ; - va_end(ap); - - /* Allocate strv */ - l = alloca(sizeof(char *) * (n + 1)); - - /* Fill in arguments */ - va_start(ap, path); - for (i = 0; i <= n; i++) - l[i] = va_arg(ap, char*); - va_end(ap); - - execv(path, l); - _exit(EXIT_FAILURE); -} - static const char *const ioprio_class_table[] = { [IOPRIO_CLASS_NONE] = "none", [IOPRIO_CLASS_RT] = "realtime", @@ -1474,7 +1068,7 @@ static const char *const ioprio_class_table[] = { [IOPRIO_CLASS_IDLE] = "idle" }; -DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ioprio_class, int, IOPRIO_N_CLASSES); +DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ioprio_class, int, INT_MAX); static const char *const sigchld_code_table[] = { [CLD_EXITED] = "exited", diff --git a/src/systemd/src/basic/process-util.h b/src/systemd/src/basic/process-util.h index 3525c2d6..e1bd2c5b 100644 --- a/src/systemd/src/basic/process-util.h +++ b/src/systemd/src/basic/process-util.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once /*** @@ -21,7 +20,6 @@ ***/ #include <alloca.h> -#include <errno.h> #include <sched.h> #include <signal.h> #include <stdbool.h> @@ -34,7 +32,6 @@ #include "format-util.h" #include "ioprio.h" #include "macro.h" -#include "time-util.h" #define procfs_file_alloca(pid, field) \ ({ \ @@ -43,7 +40,7 @@ if (_pid_ == 0) { \ _r_ = ("/proc/self/" field); \ } else { \ - _r_ = alloca(STRLEN("/proc/") + DECIMAL_STR_MAX(pid_t) + 1 + sizeof(field)); \ + _r_ = alloca(strlen("/proc/") + DECIMAL_STR_MAX(pid_t) + 1 + sizeof(field)); \ sprintf((char*) _r_, "/proc/"PID_FMT"/" field, _pid_); \ } \ _r_; \ @@ -62,21 +59,10 @@ int get_process_environ(pid_t pid, char **environ); int get_process_ppid(pid_t pid, pid_t *ppid); int wait_for_terminate(pid_t pid, siginfo_t *status); - -typedef enum WaitFlags { - WAIT_LOG_ABNORMAL = 1U << 0, - WAIT_LOG_NON_ZERO_EXIT_STATUS = 1U << 1, - - /* A shortcut for requesting the most complete logging */ - WAIT_LOG = WAIT_LOG_ABNORMAL|WAIT_LOG_NON_ZERO_EXIT_STATUS, -} WaitFlags; - -int wait_for_terminate_and_check(const char *name, pid_t pid, WaitFlags flags); -int wait_for_terminate_with_timeout(pid_t pid, usec_t timeout); +int wait_for_terminate_and_warn(const char *name, pid_t pid, bool check_exit_code); void sigkill_wait(pid_t pid); void sigkill_waitp(pid_t *pid); -void sigterm_wait(pid_t pid); int kill_and_sigcont(pid_t pid, int sig); @@ -91,7 +77,7 @@ int pid_from_same_root_fs(pid_t pid); bool is_main_thread(void); -_noreturn_ void freeze(void); +noreturn void freeze(void); bool oom_score_adjust_is_valid(int oa); @@ -117,13 +103,8 @@ int sigchld_code_from_string(const char *s) _pure_; int sched_policy_to_string_alloc(int i, char **s); int sched_policy_from_string(const char *s); -static inline pid_t PTR_TO_PID(const void *p) { - return (pid_t) ((uintptr_t) p); -} - -static inline void* PID_TO_PTR(pid_t pid) { - return (void*) ((uintptr_t) pid); -} +#define PTR_TO_PID(p) ((pid_t) ((uintptr_t) p)) +#define PID_TO_PTR(p) ((void*) ((uintptr_t) p)) void valgrind_summary_hack(void); @@ -153,56 +134,8 @@ static inline bool ioprio_priority_is_valid(int i) { static inline bool pid_is_valid(pid_t p) { return p > 0; } - -static inline int sched_policy_to_string_alloc_with_check(int n, char **s) { - if (!sched_policy_is_valid(n)) - return -EINVAL; - - return sched_policy_to_string_alloc(n, s); -} #endif /* NM_IGNORED */ int ioprio_parse_priority(const char *s, int *ret); pid_t getpid_cached(void); -void reset_cached_pid(void); - -int must_be_root(void); - -typedef enum ForkFlags { - FORK_RESET_SIGNALS = 1U << 0, - FORK_CLOSE_ALL_FDS = 1U << 1, - FORK_DEATHSIG = 1U << 2, - FORK_NULL_STDIO = 1U << 3, - FORK_REOPEN_LOG = 1U << 4, - FORK_LOG = 1U << 5, - FORK_WAIT = 1U << 6, - FORK_NEW_MOUNTNS = 1U << 7, -} ForkFlags; - -int safe_fork_full(const char *name, const int except_fds[], size_t n_except_fds, ForkFlags flags, pid_t *ret_pid); - -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 fork_agent(const char *name, const int except[], unsigned n_except, pid_t *pid, const char *path, ...); - -#if SIZEOF_PID_T == 4 -/* The highest possibly (theoretic) pid_t value on this architecture. */ -#define PID_T_MAX ((pid_t) INT32_MAX) -/* The maximum number of concurrent processes Linux allows on this architecture, as well as the highest valid PID value - * the kernel will potentially assign. This reflects a value compiled into the kernel (PID_MAX_LIMIT), and sets the - * upper boundary on what may be written to the /proc/sys/kernel/pid_max sysctl (but do note that the sysctl is off by - * 1, since PID 0 can never exist and there can hence only be one process less than the limit would suggest). Since - * these values are documented in proc(5) we feel quite confident that they are stable enough for the near future at - * least to define them here too. */ -#define TASKS_MAX 4194303U -#elif SIZEOF_PID_T == 2 -#define PID_T_MAX ((pid_t) INT16_MAX) -#define TASKS_MAX 32767U -#else -#error "Unknown pid_t size" -#endif - -assert_cc(TASKS_MAX <= (unsigned long) PID_T_MAX) diff --git a/src/systemd/src/basic/random-util.c b/src/systemd/src/basic/random-util.c index 29ee3b45..3b6ddb7d 100644 --- a/src/systemd/src/basic/random-util.c +++ b/src/systemd/src/basic/random-util.c @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. @@ -23,12 +22,11 @@ #include <elf.h> #include <errno.h> #include <fcntl.h> -#include <linux/random.h> #include <stdbool.h> -#include <stdint.h> #include <stdlib.h> -#include <string.h> #include <sys/time.h> +#include <linux/random.h> +#include <stdint.h> #if HAVE_SYS_AUXV_H # include <sys/auxv.h> diff --git a/src/systemd/src/basic/random-util.h b/src/systemd/src/basic/random-util.h index dd870151..804e225f 100644 --- a/src/systemd/src/basic/random-util.h +++ b/src/systemd/src/basic/random-util.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once /*** diff --git a/src/systemd/src/basic/refcnt.h b/src/systemd/src/basic/refcnt.h index ae2e446d..1d77a644 100644 --- a/src/systemd/src/basic/refcnt.h +++ b/src/systemd/src/basic/refcnt.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once /*** diff --git a/src/systemd/src/basic/set.h b/src/systemd/src/basic/set.h index 156ab4b0..12d0fda1 100644 --- a/src/systemd/src/basic/set.h +++ b/src/systemd/src/basic/set.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once /*** @@ -108,18 +107,6 @@ static inline void *set_steal_first(Set *s) { return internal_hashmap_steal_first(HASHMAP_BASE(s)); } -#define set_clear_with_destructor(_s, _f) \ - ({ \ - void *_item; \ - while ((_item = set_steal_first(_s))) \ - _f(_item); \ - }) -#define set_free_with_destructor(_s, _f) \ - ({ \ - set_clear_with_destructor(_s, _f); \ - set_free(_s); \ - }) - /* no set_steal_first_key */ /* no set_first_key */ diff --git a/src/systemd/src/basic/signal-util.h b/src/systemd/src/basic/signal-util.h index f6c3396e..dfd6eb56 100644 --- a/src/systemd/src/basic/signal-util.h +++ b/src/systemd/src/basic/signal-util.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once /*** @@ -45,20 +44,13 @@ static inline void block_signals_reset(sigset_t *ss) { assert_se(sigprocmask(SIG_SETMASK, ss, NULL) >= 0); } -#define BLOCK_SIGNALS(...) \ - _cleanup_(block_signals_reset) _unused_ sigset_t _saved_sigset = ({ \ - sigset_t _t; \ - assert_se(sigprocmask_many(SIG_BLOCK, &_t, __VA_ARGS__, -1) >= 0); \ - _t; \ +#define BLOCK_SIGNALS(...) \ + _cleanup_(block_signals_reset) _unused_ sigset_t _saved_sigset = ({ \ + sigset_t t; \ + assert_se(sigprocmask_many(SIG_BLOCK, &t, __VA_ARGS__, -1) >= 0); \ + t; \ }) static inline bool SIGNAL_VALID(int signo) { return signo > 0 && signo < _NSIG; } - -static inline const char* signal_to_string_with_check(int n) { - if (!SIGNAL_VALID(n)) - return NULL; - - return signal_to_string(n); -} diff --git a/src/systemd/src/basic/socket-util.c b/src/systemd/src/basic/socket-util.c index 8ae68b6f..798ab16e 100644 --- a/src/systemd/src/basic/socket-util.c +++ b/src/systemd/src/basic/socket-util.c @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. @@ -43,7 +42,6 @@ #include "missing.h" #include "parse-util.h" #include "path-util.h" -#include "process-util.h" #include "socket-util.h" #include "string-table.h" #include "string-util.h" @@ -54,24 +52,14 @@ #if 0 /* NM_IGNORED */ #if ENABLE_IDN -# define IDN_FLAGS NI_IDN +# define IDN_FLAGS (NI_IDN|NI_IDN_USE_STD3_ASCII_RULES) #else # define IDN_FLAGS 0 #endif -static const char* const socket_address_type_table[] = { - [SOCK_STREAM] = "Stream", - [SOCK_DGRAM] = "Datagram", - [SOCK_RAW] = "Raw", - [SOCK_RDM] = "ReliableDatagram", - [SOCK_SEQPACKET] = "SequentialPacket", - [SOCK_DCCP] = "DatagramCongestionControl", -}; - -DEFINE_STRING_TABLE_LOOKUP(socket_address_type, int); - int socket_address_parse(SocketAddress *a, const char *s) { char *e, *n; + unsigned u; int r; assert(a); @@ -81,8 +69,6 @@ int socket_address_parse(SocketAddress *a, const char *s) { a->type = SOCK_STREAM; if (*s == '[') { - uint16_t port; - /* IPv6 in [x:.....:z]:p notation */ e = strchr(s+1, ']'); @@ -100,12 +86,15 @@ int socket_address_parse(SocketAddress *a, const char *s) { return -EINVAL; e++; - r = parse_ip_port(e, &port); + r = safe_atou(e, &u); if (r < 0) return r; + if (u <= 0 || u > 0xFFFF) + return -EINVAL; + a->sockaddr.in6.sin6_family = AF_INET6; - a->sockaddr.in6.sin6_port = htobe16(port); + a->sockaddr.in6.sin6_port = htobe16((uint16_t)u); a->size = sizeof(struct sockaddr_in6); } else if (*s == '/') { @@ -135,14 +124,13 @@ int socket_address_parse(SocketAddress *a, const char *s) { } else if (startswith(s, "vsock:")) { /* AF_VSOCK socket in vsock:cid:port notation */ - const char *cid_start = s + STRLEN("vsock:"); - unsigned port; + const char *cid_start = s + strlen("vsock:"); e = strchr(cid_start, ':'); if (!e) return -EINVAL; - r = safe_atou(e+1, &port); + r = safe_atou(e+1, &u); if (r < 0) return r; @@ -155,18 +143,19 @@ int socket_address_parse(SocketAddress *a, const char *s) { a->sockaddr.vm.svm_cid = VMADDR_CID_ANY; a->sockaddr.vm.svm_family = AF_VSOCK; - a->sockaddr.vm.svm_port = port; + a->sockaddr.vm.svm_port = u; a->size = sizeof(struct sockaddr_vm); } else { - uint16_t port; - e = strchr(s, ':'); if (e) { - r = parse_ip_port(e + 1, &port); + r = safe_atou(e+1, &u); if (r < 0) return r; + if (u <= 0 || u > 0xFFFF) + return -EINVAL; + n = strndupa(s, e-s); /* IPv4 in w.x.y.z:p notation? */ @@ -177,7 +166,7 @@ int socket_address_parse(SocketAddress *a, const char *s) { if (r > 0) { /* Gotcha, it's a traditional IPv4 address */ a->sockaddr.in.sin_family = AF_INET; - a->sockaddr.in.sin_port = htobe16(port); + a->sockaddr.in.sin_port = htobe16((uint16_t)u); a->size = sizeof(struct sockaddr_in); } else { unsigned idx; @@ -191,7 +180,7 @@ int socket_address_parse(SocketAddress *a, const char *s) { return -EINVAL; a->sockaddr.in6.sin6_family = AF_INET6; - a->sockaddr.in6.sin6_port = htobe16(port); + a->sockaddr.in6.sin6_port = htobe16((uint16_t)u); a->sockaddr.in6.sin6_scope_id = idx; a->sockaddr.in6.sin6_addr = in6addr_any; a->size = sizeof(struct sockaddr_in6); @@ -199,18 +188,21 @@ int socket_address_parse(SocketAddress *a, const char *s) { } else { /* Just a port */ - r = parse_ip_port(s, &port); + r = safe_atou(s, &u); if (r < 0) return r; + if (u <= 0 || u > 0xFFFF) + return -EINVAL; + if (socket_ipv6_is_supported()) { a->sockaddr.in6.sin6_family = AF_INET6; - a->sockaddr.in6.sin6_port = htobe16(port); + a->sockaddr.in6.sin6_port = htobe16((uint16_t)u); a->sockaddr.in6.sin6_addr = in6addr_any; a->size = sizeof(struct sockaddr_in6); } else { a->sockaddr.in.sin_family = AF_INET; - a->sockaddr.in.sin_port = htobe16(port); + a->sockaddr.in.sin_port = htobe16((uint16_t)u); a->sockaddr.in.sin_addr.s_addr = INADDR_ANY; a->size = sizeof(struct sockaddr_in); } @@ -538,25 +530,22 @@ bool socket_address_matches_fd(const SocketAddress *a, int fd) { return socket_address_equal(a, &b); } -int sockaddr_port(const struct sockaddr *_sa, unsigned *ret_port) { +int sockaddr_port(const struct sockaddr *_sa, unsigned *port) { union sockaddr_union *sa = (union sockaddr_union*) _sa; - /* Note, this returns the port as 'unsigned' rather than 'uint16_t', as AF_VSOCK knows larger ports */ - assert(sa); switch (sa->sa.sa_family) { - case AF_INET: - *ret_port = be16toh(sa->in.sin_port); + *port = be16toh(sa->in.sin_port); return 0; case AF_INET6: - *ret_port = be16toh(sa->in6.sin6_port); + *port = be16toh(sa->in6.sin6_port); return 0; case AF_VSOCK: - *ret_port = sa->vm.svm_port; + *port = sa->vm.svm_port; return 0; default: @@ -761,6 +750,19 @@ int socknameinfo_pretty(union sockaddr_union *sa, socklen_t salen, char **_ret) return 0; } +int getnameinfo_pretty(int fd, char **ret) { + union sockaddr_union sa; + socklen_t salen = sizeof(sa); + + assert(fd >= 0); + assert(ret); + + if (getsockname(fd, &sa.sa, &salen) < 0) + return -errno; + + return socknameinfo_pretty(&sa, salen, ret); +} + int socket_address_unlink(SocketAddress *a) { assert(a); @@ -807,18 +809,6 @@ static const char* const socket_address_bind_ipv6_only_table[_SOCKET_ADDRESS_BIN DEFINE_STRING_TABLE_LOOKUP(socket_address_bind_ipv6_only, SocketAddressBindIPv6Only); -SocketAddressBindIPv6Only parse_socket_address_bind_ipv6_only_or_bool(const char *n) { - int r; - - r = parse_boolean(n); - if (r > 0) - return SOCKET_ADDRESS_IPV6_ONLY; - if (r == 0) - return SOCKET_ADDRESS_BOTH; - - return socket_address_bind_ipv6_only_from_string(n); -} - bool sockaddr_equal(const union sockaddr_union *a, const union sockaddr_union *b) { assert(a); assert(b); @@ -953,77 +943,56 @@ int getpeercred(int fd, struct ucred *ucred) { if (n != sizeof(struct ucred)) return -EIO; - /* Check if the data is actually useful and not suppressed due to namespacing issues */ - if (!pid_is_valid(u.pid)) + /* Check if the data is actually useful and not suppressed due + * to namespacing issues */ + if (u.pid <= 0) + return -ENODATA; + if (u.uid == UID_INVALID) + return -ENODATA; + if (u.gid == GID_INVALID) return -ENODATA; - - /* Note that we don't check UID/GID here, as namespace translation works differently there: instead of - * receiving in "invalid" user/group we get the overflow UID/GID. */ *ucred = u; return 0; } int getpeersec(int fd, char **ret) { - _cleanup_free_ char *s = NULL; socklen_t n = 64; + char *s; + int r; assert(fd >= 0); assert(ret); - for (;;) { - s = new0(char, n+1); - if (!s) - return -ENOMEM; + s = new0(char, n); + if (!s) + return -ENOMEM; - if (getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n) >= 0) - break; + r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n); + if (r < 0) { + free(s); if (errno != ERANGE) return -errno; - s = mfree(s); - } - - if (isempty(s)) - return -EOPNOTSUPP; - - *ret = TAKE_PTR(s); - - return 0; -} - -int getpeergroups(int fd, gid_t **ret) { - socklen_t n = sizeof(gid_t) * 64; - _cleanup_free_ gid_t *d = NULL; - - assert(fd >= 0); - assert(ret); - - for (;;) { - d = malloc(n); - if (!d) + s = new0(char, n); + if (!s) return -ENOMEM; - if (getsockopt(fd, SOL_SOCKET, SO_PEERGROUPS, d, &n) >= 0) - break; - - if (errno != ERANGE) + r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n); + if (r < 0) { + free(s); return -errno; - - d = mfree(d); + } } - assert_se(n % sizeof(gid_t) == 0); - n /= sizeof(gid_t); - - if ((socklen_t) (int) n != n) - return -E2BIG; - - *ret = d; - d = NULL; + if (isempty(s)) { + free(s); + return -EOPNOTSUPP; + } - return (int) n; + *ret = s; + return 0; } int send_one_fd_sa( diff --git a/src/systemd/src/basic/socket-util.h b/src/systemd/src/basic/socket-util.h index ac957a76..d7e2d85f 100644 --- a/src/systemd/src/basic/socket-util.h +++ b/src/systemd/src/basic/socket-util.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once /*** @@ -36,28 +35,18 @@ #include "util.h" union sockaddr_union { - /* The minimal, abstract version */ struct sockaddr sa; - - /* The libc provided version that allocates "enough room" for every protocol */ - struct sockaddr_storage storage; - - /* Protoctol-specific implementations */ struct sockaddr_in in; struct sockaddr_in6 in6; struct sockaddr_un un; struct sockaddr_nl nl; + struct sockaddr_storage storage; struct sockaddr_ll ll; #if 0 /* NM_IGNORED */ struct sockaddr_vm vm; #endif /* NM_IGNORED */ - /* Ensure there is enough space to store Infiniband addresses */ uint8_t ll_buffer[offsetof(struct sockaddr_ll, sll_addr) + CONST_MAX(ETH_ALEN, INFINIBAND_ALEN)]; - - /* Ensure there is enough space after the AF_UNIX sun_path for one more NUL byte, just to be sure that the path - * component is always followed by at least one NUL byte. */ - uint8_t un_buffer[sizeof(struct sockaddr_un) + 1]; }; typedef struct SocketAddress { @@ -84,9 +73,6 @@ typedef enum SocketAddressBindIPv6Only { #define socket_address_family(a) ((a)->sockaddr.sa.sa_family) -const char* socket_address_type_to_string(int t) _const_; -int socket_address_type_from_string(const char *s) _pure_; - int socket_address_parse(SocketAddress *a, const char *s); int socket_address_parse_and_warn(SocketAddress *a, const char *s); int socket_address_parse_netlink(SocketAddress *a, const char *s); @@ -128,10 +114,10 @@ int getpeername_pretty(int fd, bool include_port, char **ret); int getsockname_pretty(int fd, char **ret); int socknameinfo_pretty(union sockaddr_union *sa, socklen_t salen, char **_ret); +int getnameinfo_pretty(int fd, char **ret); const char* socket_address_bind_ipv6_only_to_string(SocketAddressBindIPv6Only b) _const_; SocketAddressBindIPv6Only socket_address_bind_ipv6_only_from_string(const char *s) _pure_; -SocketAddressBindIPv6Only parse_socket_address_bind_ipv6_only_or_bool(const char *s); int netlink_family_to_string_alloc(int b, char **s); int netlink_family_from_string(const char *s) _pure_; @@ -149,7 +135,6 @@ bool address_label_valid(const char *p); int getpeercred(int fd, struct ucred *ucred); int getpeersec(int fd, char **ret); -int getpeergroups(int fd, gid_t **ret); int send_one_fd_sa(int transport_fd, int fd, diff --git a/src/systemd/src/basic/sparse-endian.h b/src/systemd/src/basic/sparse-endian.h index 5e59de54..a3573b84 100644 --- a/src/systemd/src/basic/sparse-endian.h +++ b/src/systemd/src/basic/sparse-endian.h @@ -1,6 +1,4 @@ -/* SPDX-License-Identifier: MIT - * - * Copyright (c) 2012 Josh Triplett <josh@joshtriplett.org> +/* Copyright (c) 2012 Josh Triplett <josh@joshtriplett.org> * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to diff --git a/src/systemd/src/basic/stdio-util.h b/src/systemd/src/basic/stdio-util.h index d3fed365..bd1144b4 100644 --- a/src/systemd/src/basic/stdio-util.h +++ b/src/systemd/src/basic/stdio-util.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once /*** @@ -27,11 +26,9 @@ #include "macro.h" -#define snprintf_ok(buf, len, fmt, ...) \ - ((size_t) snprintf(buf, len, fmt, __VA_ARGS__) < (len)) - #define xsprintf(buf, fmt, ...) \ - assert_message_se(snprintf_ok(buf, ELEMENTSOF(buf), fmt, __VA_ARGS__), "xsprintf: " #buf "[] must be big enough") + assert_message_se((size_t) snprintf(buf, ELEMENTSOF(buf), fmt, __VA_ARGS__) < ELEMENTSOF(buf), "xsprintf: " #buf "[] must be big enough") + #define VA_FORMAT_ADVANCE(format, ap) \ do { \ diff --git a/src/systemd/src/basic/string-table.c b/src/systemd/src/basic/string-table.c index 8ec3b266..df26d5fb 100644 --- a/src/systemd/src/basic/string-table.c +++ b/src/systemd/src/basic/string-table.c @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. diff --git a/src/systemd/src/basic/string-table.h b/src/systemd/src/basic/string-table.h index e78a6dbd..369610ef 100644 --- a/src/systemd/src/basic/string-table.h +++ b/src/systemd/src/basic/string-table.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once @@ -93,11 +92,13 @@ ssize_t string_table_lookup(const char * const *table, size_t len, const char *k #define _DEFINE_STRING_TABLE_LOOKUP(name,type,scope) \ _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \ - _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,scope) + _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,scope) \ + struct __useless_struct_to_allow_trailing_semicolon__ #define _DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes,scope) \ _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \ - _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(name,type,yes,scope) + _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(name,type,yes,scope) \ + struct __useless_struct_to_allow_trailing_semicolon__ #define DEFINE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,) #define DEFINE_PRIVATE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,static) @@ -109,7 +110,8 @@ ssize_t string_table_lookup(const char * const *table, size_t len, const char *k /* For string conversions where numbers are also acceptable */ #define DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(name,type,max) \ _DEFINE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(name,type,max,) \ - _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max,) + _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max,) \ + struct __useless_struct_to_allow_trailing_semicolon__ #define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(name,type,max) \ _DEFINE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(name,type,max,static) diff --git a/src/systemd/src/basic/string-util.c b/src/systemd/src/basic/string-util.c index a8e595db..047eb162 100644 --- a/src/systemd/src/basic/string-util.c +++ b/src/systemd/src/basic/string-util.c @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. @@ -24,7 +23,6 @@ #include <stdarg.h> #include <stdint.h> #include <stdio.h> -#include <stdio_ext.h> #include <stdlib.h> #include <string.h> @@ -32,7 +30,6 @@ #include "gunicode.h" #include "macro.h" #include "string-util.h" -#include "terminal-util.h" #include "utf8.h" #include "util.h" @@ -223,7 +220,6 @@ char *strappend(const char *s, const char *suffix) { return strnappend(s, suffix, strlen_ptr(suffix)); } -#if 0 /* NM_IGNORED */ char *strjoin_real(const char *x, ...) { va_list ap; size_t l; @@ -284,9 +280,6 @@ char *strjoin_real(const char *x, ...) { char *strstrip(char *s) { char *e; - if (!s) - return NULL; - /* Drops trailing whitespace. Modifies the string in * place. Returns pointer to first non-space character */ @@ -304,13 +297,7 @@ char *strstrip(char *s) { char *delete_chars(char *s, const char *bad) { char *f, *t; - /* Drops all specified bad characters, regardless where in the string */ - - if (!s) - return NULL; - - if (!bad) - bad = WHITESPACE; + /* Drops all whitespace, regardless where in the string */ for (f = s, t = s; *f; f++) { if (strchr(bad, *f)) @@ -324,27 +311,6 @@ char *delete_chars(char *s, const char *bad) { return s; } -char *delete_trailing_chars(char *s, const char *bad) { - char *p, *c = s; - - /* Drops all specified bad characters, at the end of the string */ - - if (!s) - return NULL; - - if (!bad) - bad = WHITESPACE; - - for (p = s; *p; p++) - if (!strchr(bad, *p)) - c = p + 1; - - *c = 0; - - return s; -} -#endif /* NM_IGNORED */ - char *truncate_nl(char *s) { assert(s); @@ -509,10 +475,6 @@ char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigne assert(s); assert(percent <= 100); - - if (new_length == (size_t) -1) - return strndup(s, old_length); - assert(new_length >= 3); /* if no multibyte characters use ascii_ellipsize_mem for speed */ @@ -580,10 +542,6 @@ char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigne } char *ellipsize(const char *s, size_t length, unsigned percent) { - - if (length == (size_t) -1) - return strdup(s); - return ellipsize_mem(s, strlen(s), length, percent); } #endif /* NM_IGNORED */ @@ -611,26 +569,26 @@ char* strshorten(char *s, size_t l) { } char *strreplace(const char *text, const char *old_string, const char *new_string) { - size_t l, old_len, new_len, allocated = 0; - char *t, *ret = NULL; const char *f; + char *t, *r; + size_t l, old_len, new_len; + assert(text); assert(old_string); assert(new_string); - if (!text) - return NULL; - old_len = strlen(old_string); new_len = strlen(new_string); l = strlen(text); - if (!GREEDY_REALLOC(ret, allocated, l+1)) + r = new(char, l+1); + if (!r) return NULL; f = text; - t = ret; + t = r; while (*f) { + char *a; size_t d, nl; if (!startswith(f, old_string)) { @@ -638,34 +596,28 @@ char *strreplace(const char *text, const char *old_string, const char *new_strin continue; } - d = t - ret; + d = t - r; nl = l - old_len + new_len; - - if (!GREEDY_REALLOC(ret, allocated, nl + 1)) - return mfree(ret); + a = realloc(r, nl + 1); + if (!a) + goto oom; l = nl; - t = ret + d; + r = a; + t = r + d; t = stpcpy(t, new_string); f += old_len; } *t = 0; - return ret; -} - -static void advance_offsets(ssize_t diff, size_t offsets[2], size_t shift[2], size_t size) { - if (!offsets) - return; + return r; - if ((size_t) diff < offsets[0]) - shift[0] += size; - if ((size_t) diff < offsets[1]) - shift[1] += size; +oom: + return mfree(r); } -char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) { +char *strip_tab_ansi(char **ibuf, size_t *_isz) { const char *i, *begin = NULL; enum { STATE_OTHER, @@ -673,7 +625,7 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) { STATE_BRACKET } state = STATE_OTHER; char *obuf = NULL; - size_t osz = 0, isz, shift[2] = {}; + size_t osz = 0, isz; FILE *f; assert(ibuf); @@ -687,10 +639,10 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) { 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); + /* Note we use the _unlocked() stdio variants on f for performance + * reasons. It's safe to do so since we created f here and it + * doesn't leave our scope. + */ for (i = *ibuf; i < *ibuf + isz + 1; i++) { @@ -701,26 +653,22 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) { break; else if (*i == '\x1B') state = STATE_ESCAPE; - else if (*i == '\t') { - fputs(" ", f); - advance_offsets(i - *ibuf, highlight, shift, 7); - } else - fputc(*i, f); - + else if (*i == '\t') + fputs_unlocked(" ", f); + else + fputc_unlocked(*i, f); break; case STATE_ESCAPE: if (i >= *ibuf + isz) { /* EOT */ - fputc('\x1B', f); - advance_offsets(i - *ibuf, highlight, shift, 1); + fputc_unlocked('\x1B', f); break; } else if (*i == '[') { state = STATE_BRACKET; begin = i + 1; } else { - fputc('\x1B', f); - fputc(*i, f); - advance_offsets(i - *ibuf, highlight, shift, 1); + fputc_unlocked('\x1B', f); + fputc_unlocked(*i, f); state = STATE_OTHER; } @@ -730,9 +678,8 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) { if (i >= *ibuf + isz || /* EOT */ (!(*i >= '0' && *i <= '9') && !IN_SET(*i, ';', 'm'))) { - fputc('\x1B', f); - fputc('[', f); - advance_offsets(i - *ibuf, highlight, shift, 2); + fputc_unlocked('\x1B', f); + fputc_unlocked('[', f); state = STATE_OTHER; i = begin-1; } else if (*i == 'm') @@ -754,29 +701,19 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) { if (_isz) *_isz = osz; - if (highlight) { - highlight[0] += shift[0]; - highlight[1] += shift[1]; - } - return obuf; } -#if 0 /* NM_IGNORED */ -char *strextend_with_separator(char **x, const char *separator, ...) { - bool need_separator; - size_t f, l, l_separator; - char *r, *p; +char *strextend(char **x, ...) { va_list ap; + size_t f, l; + char *r, *p; assert(x); l = f = strlen_ptr(*x); - need_separator = !isempty(*x); - l_separator = strlen_ptr(separator); - - va_start(ap, separator); + va_start(ap, x); for (;;) { const char *t; size_t n; @@ -786,29 +723,22 @@ char *strextend_with_separator(char **x, const char *separator, ...) { break; n = strlen(t); - - if (need_separator) - n += l_separator; - if (n > ((size_t) -1) - l) { va_end(ap); return NULL; } l += n; - need_separator = true; } va_end(ap); - need_separator = !isempty(*x); - r = realloc(*x, l+1); if (!r) return NULL; p = r + f; - va_start(ap, separator); + va_start(ap, x); for (;;) { const char *t; @@ -816,23 +746,15 @@ char *strextend_with_separator(char **x, const char *separator, ...) { if (!t) break; - if (need_separator && separator) - p = stpcpy(p, separator); - p = stpcpy(p, t); - - need_separator = true; } va_end(ap); - assert(p == r + l); - *p = 0; *x = r; return r + l; } -#endif /* NM_IGNORED */ char *strrep(const char *s, unsigned n) { size_t l; diff --git a/src/systemd/src/basic/string-util.h b/src/systemd/src/basic/string-util.h index 08eda4fc..4c94b182 100644 --- a/src/systemd/src/basic/string-util.h +++ b/src/systemd/src/basic/string-util.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once /*** @@ -52,15 +51,15 @@ static inline bool streq_ptr(const char *a, const char *b) { } static inline const char* strempty(const char *s) { - return s ?: ""; + return s ? s : ""; } static inline const char* strnull(const char *s) { - return s ?: "(null)"; + return s ? s : "(null)"; } static inline const char *strna(const char *s) { - return s ?: "n/a"; + return s ? s : "n/a"; } static inline bool isempty(const char *p) { @@ -134,20 +133,8 @@ char *strjoin_real(const char *x, ...) _sentinel_; char *strstrip(char *s); char *delete_chars(char *s, const char *bad); -char *delete_trailing_chars(char *s, const char *bad); char *truncate_nl(char *s); -static inline char *skip_leading_chars(const char *s, const char *bad) { - - if (!s) - return NULL; - - if (!bad) - bad = WHITESPACE; - - return (char*) s + strspn(s, bad); -} - char ascii_tolower(char x); char *ascii_strlower(char *s); char *ascii_strlower_n(char *s, size_t n); @@ -177,11 +164,9 @@ char* strshorten(char *s, size_t l); char *strreplace(const char *text, const char *old_string, const char *new_string); -char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]); - -char *strextend_with_separator(char **x, const char *separator, ...) _sentinel_; +char *strip_tab_ansi(char **p, size_t *l); -#define strextend(x, ...) strextend_with_separator(x, NULL, __VA_ARGS__) +char *strextend(char **x, ...) _sentinel_; char *strrep(const char *s, unsigned n); diff --git a/src/systemd/src/basic/strv.c b/src/systemd/src/basic/strv.c index dee5bbd7..08bcff6e 100644 --- a/src/systemd/src/basic/strv.c +++ b/src/systemd/src/basic/strv.c @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. @@ -216,7 +215,7 @@ int strv_extend_strv(char ***a, char **b, bool filter_duplicates) { p = strv_length(*a); q = strv_length(b); - t = reallocarray(*a, p + q + 1, sizeof(char *)); + t = realloc(*a, sizeof(char*) * (p + q + 1)); if (!t) return -ENOMEM; @@ -344,7 +343,8 @@ int strv_split_extract(char ***t, const char *s, const char *separators, Extract if (!GREEDY_REALLOC(l, allocated, n + 2)) return -ENOMEM; - l[n++] = TAKE_PTR(word); + l[n++] = word; + word = NULL; l[n] = NULL; } @@ -355,7 +355,8 @@ int strv_split_extract(char ***t, const char *s, const char *separators, Extract return -ENOMEM; } - *t = TAKE_PTR(l); + *t = l; + l = NULL; return (int) n; } @@ -395,6 +396,42 @@ char *strv_join(char **l, const char *separator) { return r; } +char *strv_join_quoted(char **l) { + char *buf = NULL; + char **s; + size_t allocated = 0, len = 0; + + STRV_FOREACH(s, l) { + /* assuming here that escaped string cannot be more + * than twice as long, and reserving space for the + * separator and quotes. + */ + _cleanup_free_ char *esc = NULL; + size_t needed; + + if (!GREEDY_REALLOC(buf, allocated, + len + strlen(*s) * 2 + 3)) + goto oom; + + esc = cescape(*s); + if (!esc) + goto oom; + + needed = snprintf(buf + len, allocated - len, "%s\"%s\"", + len > 0 ? " " : "", esc); + assert(needed < allocated - len); + len += needed; + } + + if (!buf) + buf = malloc0(1); + + return buf; + + oom: + return mfree(buf); +} + int strv_push(char ***l, char *value) { char **c; unsigned n, m; @@ -409,7 +446,7 @@ int strv_push(char ***l, char *value) { if (m < n) return -ENOMEM; - c = reallocarray(*l, m, sizeof(char*)); + c = realloc_multiply(*l, sizeof(char*), m); if (!c) return -ENOMEM; @@ -434,7 +471,7 @@ int strv_push_pair(char ***l, char *a, char *b) { if (m < n) return -ENOMEM; - c = reallocarray(*l, m, sizeof(char*)); + c = realloc_multiply(*l, sizeof(char*), m); if (!c) return -ENOMEM; @@ -448,7 +485,7 @@ int strv_push_pair(char ***l, char *a, char *b) { return 0; } -int strv_insert(char ***l, unsigned position, char *value) { +int strv_push_prepend(char ***l, char *value) { char **c; unsigned n, m, i; @@ -456,7 +493,6 @@ int strv_insert(char ***l, unsigned position, char *value) { return 0; n = strv_length(*l); - position = MIN(position, n); /* increase and check for overflow */ m = n + 2; @@ -467,12 +503,10 @@ int strv_insert(char ***l, unsigned position, char *value) { if (!c) return -ENOMEM; - for (i = 0; i < position; i++) - c[i] = (*l)[i]; - c[position] = value; - for (i = position; i < n; i++) + for (i = 0; i < n; i++) c[i+1] = (*l)[i]; + c[0] = value; c[n+1] = NULL; free(*l); @@ -548,7 +582,7 @@ int strv_extend_front(char ***l, const char *value) { if (!v) return -ENOMEM; - c = reallocarray(*l, m, sizeof(char*)); + c = realloc_multiply(*l, sizeof(char*), m); if (!c) { free(v); return -ENOMEM; @@ -863,7 +897,7 @@ int strv_extend_n(char ***l, const char *value, size_t n) { k = strv_length(*l); - nl = reallocarray(*l, k + n + 1, sizeof(char *)); + nl = realloc(*l, sizeof(char*) * (k + n + 1)); if (!nl) return -ENOMEM; diff --git a/src/systemd/src/basic/strv.h b/src/systemd/src/basic/strv.h index f169ac5d..385ad177 100644 --- a/src/systemd/src/basic/strv.h +++ b/src/systemd/src/basic/strv.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once /*** @@ -54,12 +53,7 @@ int strv_extendf(char ***l, const char *format, ...) _printf_(2,0); int strv_extend_front(char ***l, const char *value); int strv_push(char ***l, char *value); int strv_push_pair(char ***l, char *a, char *b); -int strv_insert(char ***l, unsigned position, char *value); - -static inline int strv_push_prepend(char ***l, char *value) { - return strv_insert(l, 0, value); -} - +int strv_push_prepend(char ***l, char *value); int strv_consume(char ***l, char *value); int strv_consume_pair(char ***l, char *a, char *b); int strv_consume_prepend(char ***l, char *value); @@ -91,6 +85,7 @@ char **strv_split_newlines(const char *s); int strv_split_extract(char ***t, const char *s, const char *separators, ExtractFlags flags); char *strv_join(char **l, const char *separator); +char *strv_join_quoted(char **l); char **strv_parse_nulstr(const char *s, size_t l); char **strv_split_nulstr(const char *s); @@ -179,18 +174,9 @@ static inline bool strv_fnmatch_or_empty(char* const* patterns, const char *s, i } char ***strv_free_free(char ***l); -DEFINE_TRIVIAL_CLEANUP_FUNC(char***, strv_free_free); char **strv_skip(char **l, size_t n); int strv_extend_n(char ***l, const char *value, size_t n); int fputstrv(FILE *f, char **l, const char *separator, bool *space); - -#define strv_free_and_replace(a, b) \ - ({ \ - strv_free(a); \ - (a) = (b); \ - (b) = NULL; \ - 0; \ - }) diff --git a/src/systemd/src/basic/time-util.c b/src/systemd/src/basic/time-util.c index 95fbbd91..7f1c3f7c 100644 --- a/src/systemd/src/basic/time-util.c +++ b/src/systemd/src/basic/time-util.c @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. @@ -40,7 +39,6 @@ #include "macro.h" #include "parse-util.h" #include "path-util.h" -#include "process-util.h" #include "string-util.h" #include "strv.h" #include "time-util.h" @@ -893,24 +891,28 @@ int parse_timestamp(const char *t, usec_t *usec) { char *last_space, *tz = NULL; ParseTimestampResult *shared, tmp; int r; + pid_t pid; last_space = strrchr(t, ' '); if (last_space != NULL && timezone_is_valid(last_space + 1)) tz = last_space + 1; - if (!tz || endswith_no_case(t, " UTC")) + if (tz == NULL || endswith_no_case(t, " UTC")) return parse_timestamp_impl(t, usec, false); shared = mmap(NULL, sizeof *shared, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0); if (shared == MAP_FAILED) return negative_errno(); - r = safe_fork("(sd-timestamp)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_WAIT, NULL); - if (r < 0) { + pid = fork(); + + if (pid == -1) { + int fork_errno = errno; (void) munmap(shared, sizeof *shared); - return r; + return -fork_errno; } - if (r == 0) { + + if (pid == 0) { bool with_tz = true; if (setenv("TZ", tz, 1) != 0) { @@ -933,6 +935,12 @@ int parse_timestamp(const char *t, usec_t *usec) { _exit(EXIT_SUCCESS); } + r = wait_for_terminate(pid, NULL); + if (r < 0) { + (void) munmap(shared, sizeof *shared); + return r; + } + tmp = *shared; if (munmap(shared, sizeof *shared) != 0) return negative_errno(); @@ -1379,7 +1387,8 @@ bool clock_supported(clockid_t clock) { if (!clock_boottime_supported()) return false; - _fallthrough_; + /* fall through */ + default: /* For everything else, check properly */ return clock_gettime(clock, &ts) >= 0; @@ -1454,10 +1463,4 @@ usec_t usec_shift_clock(usec_t x, clockid_t from, clockid_t to) { /* x lies in the past */ return usec_sub_unsigned(b, usec_sub_unsigned(a, x)); } - -bool in_utc_timezone(void) { - tzset(); - - return timezone == 0 && daylight == 0; -} #endif /* NM_IGNORED */ diff --git a/src/systemd/src/basic/time-util.h b/src/systemd/src/basic/time-util.h index a8c5a837..73f7e400 100644 --- a/src/systemd/src/basic/time-util.h +++ b/src/systemd/src/basic/time-util.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once /*** @@ -100,12 +99,12 @@ triple_timestamp* triple_timestamp_from_realtime(triple_timestamp *ts, usec_t u) #define TRIPLE_TIMESTAMP_HAS_CLOCK(clock) \ IN_SET(clock, CLOCK_REALTIME, CLOCK_REALTIME_ALARM, CLOCK_MONOTONIC, CLOCK_BOOTTIME, CLOCK_BOOTTIME_ALARM) -static inline bool dual_timestamp_is_set(const dual_timestamp *ts) { +static inline bool dual_timestamp_is_set(dual_timestamp *ts) { return ((ts->realtime > 0 && ts->realtime != USEC_INFINITY) || (ts->monotonic > 0 && ts->monotonic != USEC_INFINITY)); } -static inline bool triple_timestamp_is_set(const triple_timestamp *ts) { +static inline bool triple_timestamp_is_set(triple_timestamp *ts) { return ((ts->realtime > 0 && ts->realtime != USEC_INFINITY) || (ts->monotonic > 0 && ts->monotonic != USEC_INFINITY) || (ts->boottime > 0 && ts->boottime != USEC_INFINITY)); @@ -156,8 +155,6 @@ struct tm *localtime_or_gmtime_r(const time_t *t, struct tm *tm, bool utc); unsigned long usec_to_jiffies(usec_t usec); -bool in_utc_timezone(void); - static inline usec_t usec_add(usec_t a, usec_t b) { usec_t c; diff --git a/src/systemd/src/basic/umask-util.h b/src/systemd/src/basic/umask-util.h index 638b37d7..359d87d2 100644 --- a/src/systemd/src/basic/umask-util.h +++ b/src/systemd/src/basic/umask-util.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once /*** diff --git a/src/systemd/src/basic/utf8.c b/src/systemd/src/basic/utf8.c index c88eef38..ff281e43 100644 --- a/src/systemd/src/basic/utf8.c +++ b/src/systemd/src/basic/utf8.c @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. @@ -410,22 +409,3 @@ int utf8_encoded_valid_unichar(const char *str) { return len; } - -size_t utf8_n_codepoints(const char *str) { - size_t n = 0; - - /* Returns the number of UTF-8 codepoints in this string, or (size_t) -1 if the string is not valid UTF-8. */ - - while (*str != 0) { - int k; - - k = utf8_encoded_valid_unichar(str); - if (k < 0) - return (size_t) -1; - - str += k; - n++; - } - - return n; -} diff --git a/src/systemd/src/basic/utf8.h b/src/systemd/src/basic/utf8.h index c5243c24..322dac20 100644 --- a/src/systemd/src/basic/utf8.h +++ b/src/systemd/src/basic/utf8.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once /*** @@ -61,5 +60,3 @@ static inline bool utf16_is_trailing_surrogate(char16_t c) { static inline char32_t utf16_surrogate_pair_to_unichar(char16_t lead, char16_t trail) { return ((lead - 0xd800) << 10) + (trail - 0xdc00) + 0x10000; } - -size_t utf8_n_codepoints(const char *str); diff --git a/src/systemd/src/basic/util.c b/src/systemd/src/basic/util.c index d8c9e82d..c8a22d68 100644 --- a/src/systemd/src/basic/util.c +++ b/src/systemd/src/basic/util.c @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. @@ -41,7 +40,6 @@ #include "build.h" #include "cgroup-util.h" #include "def.h" -#include "device-nodes.h" #include "dirent-util.h" #include "fd-util.h" #include "fileio.h" @@ -54,7 +52,6 @@ #include "parse-util.h" #include "path-util.h" #include "process-util.h" -#include "procfs-util.h" #include "set.h" #include "signal-util.h" #include "stat-util.h" @@ -64,7 +61,6 @@ #include "umask-util.h" #include "user-util.h" #include "util.h" -#include "virt.h" #if 0 /* NM_IGNORED */ int saved_argc = 0; @@ -112,7 +108,7 @@ int socket_from_display(const char *display, char **path) { k = strspn(display+1, "0123456789"); - f = new(char, STRLEN("/tmp/.X11-unix/X") + k + 1); + f = new(char, strlen("/tmp/.X11-unix/X") + k + 1); if (!f) return -ENOMEM; @@ -125,6 +121,66 @@ int socket_from_display(const char *display, char **path) { return 0; } +int block_get_whole_disk(dev_t d, dev_t *ret) { + char *p, *s; + int r; + unsigned n, m; + + assert(ret); + + /* If it has a queue this is good enough for us */ + if (asprintf(&p, "/sys/dev/block/%u:%u/queue", major(d), minor(d)) < 0) + return -ENOMEM; + + r = access(p, F_OK); + free(p); + + if (r >= 0) { + *ret = d; + return 0; + } + + /* If it is a partition find the originating device */ + if (asprintf(&p, "/sys/dev/block/%u:%u/partition", major(d), minor(d)) < 0) + return -ENOMEM; + + r = access(p, F_OK); + free(p); + + if (r < 0) + return -ENOENT; + + /* Get parent dev_t */ + if (asprintf(&p, "/sys/dev/block/%u:%u/../dev", major(d), minor(d)) < 0) + return -ENOMEM; + + r = read_one_line_file(p, &s); + free(p); + + if (r < 0) + return r; + + r = sscanf(s, "%u:%u", &m, &n); + free(s); + + if (r != 2) + return -EINVAL; + + /* Only return this if it is really good enough for us. */ + if (asprintf(&p, "/sys/dev/block/%u:%u/queue", m, n) < 0) + return -ENOMEM; + + r = access(p, F_OK); + free(p); + + if (r >= 0) { + *ret = makedev(m, n); + return 0; + } + + return -ENOENT; +} + bool kexec_loaded(void) { _cleanup_free_ char *s = NULL; @@ -152,6 +208,112 @@ int prot_from_flags(int flags) { } } +int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...) { + bool stdout_is_tty, stderr_is_tty; + pid_t parent_pid, agent_pid; + sigset_t ss, saved_ss; + unsigned n, i; + va_list ap; + char **l; + + assert(pid); + assert(path); + + /* Spawns a temporary TTY agent, making sure it goes away when + * we go away */ + + parent_pid = getpid_cached(); + + /* First we temporarily block all signals, so that the new + * child has them blocked initially. This way, we can be sure + * that SIGTERMs are not lost we might send to the agent. */ + assert_se(sigfillset(&ss) >= 0); + assert_se(sigprocmask(SIG_SETMASK, &ss, &saved_ss) >= 0); + + agent_pid = fork(); + if (agent_pid < 0) { + assert_se(sigprocmask(SIG_SETMASK, &saved_ss, NULL) >= 0); + return -errno; + } + + if (agent_pid != 0) { + assert_se(sigprocmask(SIG_SETMASK, &saved_ss, NULL) >= 0); + *pid = agent_pid; + return 0; + } + + /* In the child: + * + * Make sure the agent goes away when the parent dies */ + if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0) + _exit(EXIT_FAILURE); + + /* Make sure we actually can kill the agent, if we need to, in + * case somebody invoked us from a shell script that trapped + * SIGTERM or so... */ + (void) reset_all_signal_handlers(); + (void) reset_signal_mask(); + + /* Check whether our parent died before we were able + * to set the death signal and unblock the signals */ + if (getppid() != parent_pid) + _exit(EXIT_SUCCESS); + + /* Don't leak fds to the agent */ + close_all_fds(except, n_except); + + stdout_is_tty = isatty(STDOUT_FILENO); + stderr_is_tty = isatty(STDERR_FILENO); + + if (!stdout_is_tty || !stderr_is_tty) { + int fd; + + /* Detach from stdout/stderr. and reopen + * /dev/tty for them. This is important to + * ensure that when systemctl is started via + * popen() or a similar call that expects to + * read EOF we actually do generate EOF and + * not delay this indefinitely by because we + * keep an unused copy of stdin around. */ + fd = open("/dev/tty", O_WRONLY); + if (fd < 0) { + log_error_errno(errno, "Failed to open /dev/tty: %m"); + _exit(EXIT_FAILURE); + } + + if (!stdout_is_tty && dup2(fd, STDOUT_FILENO) < 0) { + log_error_errno(errno, "Failed to dup2 /dev/tty: %m"); + _exit(EXIT_FAILURE); + } + + if (!stderr_is_tty && dup2(fd, STDERR_FILENO) < 0) { + log_error_errno(errno, "Failed to dup2 /dev/tty: %m"); + _exit(EXIT_FAILURE); + } + + if (fd > STDERR_FILENO) + close(fd); + } + + /* Count arguments */ + va_start(ap, path); + for (n = 0; va_arg(ap, char*); n++) + ; + va_end(ap); + + /* Allocate strv */ + l = alloca(sizeof(char *) * (n + 1)); + + /* Fill in arguments */ + va_start(ap, path); + for (i = 0; i <= n; i++) + l[i] = va_arg(ap, char*); + va_end(ap); + + execv(path, l); + _exit(EXIT_FAILURE); +} + bool in_initrd(void) { struct statfs s; @@ -186,13 +348,11 @@ void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size, const void *p; int comparison; - assert(!size_multiply_overflow(nmemb, size)); - l = 0; u = nmemb; while (l < u) { idx = (l + u) / 2; - p = (const uint8_t*) base + idx * size; + p = (const char *) base + idx * size; comparison = compar(key, p, arg); if (comparison < 0) u = idx; @@ -481,22 +641,31 @@ uint64_t physical_memory_scale(uint64_t v, uint64_t max) { uint64_t system_tasks_max(void) { +#if SIZEOF_PID_T == 4 +#define TASKS_MAX ((uint64_t) (INT32_MAX-1)) +#elif SIZEOF_PID_T == 2 +#define TASKS_MAX ((uint64_t) (INT16_MAX-1)) +#else +#error "Unknown pid_t size" +#endif + + _cleanup_free_ char *value = NULL, *root = NULL; uint64_t a = TASKS_MAX, b = TASKS_MAX; - _cleanup_free_ char *root = NULL; /* Determine the maximum number of tasks that may run on this system. We check three sources to determine this * limit: * - * a) the maximum tasks value the kernel allows on this architecture + * a) the maximum value for the pid_t type * b) the cgroups pids_max attribute for the system - * c) the kernel's configured maximum PID value + * c) the kernel's configure maximum PID value * * And then pick the smallest of the three */ - (void) procfs_tasks_get_limit(&a); + if (read_one_line_file("/proc/sys/kernel/pid_max", &value) >= 0) + (void) safe_atou64(value, &a); if (cg_get_root_path(&root) >= 0) { - _cleanup_free_ char *value = NULL; + value = mfree(value); if (cg_get_attribute("pids", root, "pids.max", &value) >= 0) (void) safe_atou64(value, &b); @@ -525,83 +694,162 @@ uint64_t system_tasks_max_scale(uint64_t v, uint64_t max) { return m / max; } +int update_reboot_parameter_and_warn(const char *param) { + int r; + + if (isempty(param)) { + if (unlink("/run/systemd/reboot-param") < 0) { + if (errno == ENOENT) + return 0; + + return log_warning_errno(errno, "Failed to unlink reboot parameter file: %m"); + } + + return 0; + } + + RUN_WITH_UMASK(0022) { + r = write_string_file("/run/systemd/reboot-param", param, WRITE_STRING_FILE_CREATE); + if (r < 0) + return log_warning_errno(r, "Failed to write reboot parameter file: %m"); + } + + return 0; +} + int version(void) { puts(PACKAGE_STRING "\n" SYSTEMD_FEATURES); return 0; } -/* This is a direct translation of str_verscmp from boot.c */ -static bool is_digit(int c) { - return c >= '0' && c <= '9'; -} +int get_block_device(const char *path, dev_t *dev) { + struct stat st; + struct statfs sfs; -static int c_order(int c) { - if (c == 0 || is_digit(c)) - return 0; + assert(path); + assert(dev); - if ((c >= 'a') && (c <= 'z')) - return c; + /* Get's the block device directly backing a file system. If + * the block device is encrypted, returns the device mapper + * block device. */ - return c + 0x10000; -} + if (lstat(path, &st)) + return -errno; + + if (major(st.st_dev) != 0) { + *dev = st.st_dev; + return 1; + } -int str_verscmp(const char *s1, const char *s2) { - const char *os1, *os2; + if (statfs(path, &sfs) < 0) + return -errno; - assert(s1); - assert(s2); + if (F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC)) + return btrfs_get_block_device(path, dev); - os1 = s1; - os2 = s2; + return 0; +} - while (*s1 || *s2) { - int first; +int get_block_device_harder(const char *path, dev_t *dev) { + _cleanup_closedir_ DIR *d = NULL; + _cleanup_free_ char *p = NULL, *t = NULL; + struct dirent *de, *found = NULL; + const char *q; + unsigned maj, min; + dev_t dt; + int r; - while ((*s1 && !is_digit(*s1)) || (*s2 && !is_digit(*s2))) { - int order; + assert(path); + assert(dev); - order = c_order(*s1) - c_order(*s2); - if (order != 0) - return order; - s1++; - s2++; - } + /* Gets the backing block device for a file system, and + * handles LUKS encrypted file systems, looking for its + * immediate parent, if there is one. */ - while (*s1 == '0') - s1++; - while (*s2 == '0') - s2++; - - first = 0; - while (is_digit(*s1) && is_digit(*s2)) { - if (first == 0) - first = *s1 - *s2; - s1++; - s2++; - } + r = get_block_device(path, &dt); + if (r <= 0) + return r; + + if (asprintf(&p, "/sys/dev/block/%u:%u/slaves", major(dt), minor(dt)) < 0) + return -ENOMEM; - if (is_digit(*s1)) - return 1; - if (is_digit(*s2)) - return -1; + d = opendir(p); + if (!d) { + if (errno == ENOENT) + goto fallback; - if (first != 0) - return first; + return -errno; } - return strcmp(os1, os2); -} + FOREACH_DIRENT_ALL(de, d, return -errno) { -/* Turn off core dumps but only if we're running outside of a container. */ -void disable_coredumps(void) { - int r; + if (dot_or_dot_dot(de->d_name)) + continue; - if (detect_container() > 0) - return; + if (!IN_SET(de->d_type, DT_LNK, DT_UNKNOWN)) + continue; - r = write_string_file("/proc/sys/kernel/core_pattern", "|/bin/false", 0); + if (found) { + _cleanup_free_ char *u = NULL, *v = NULL, *a = NULL, *b = NULL; + + /* We found a device backed by multiple other devices. We don't really support automatic + * discovery on such setups, with the exception of dm-verity partitions. In this case there are + * two backing devices: the data partition and the hash partition. We are fine with such + * setups, however, only if both partitions are on the same physical device. Hence, let's + * verify this. */ + + u = strjoin(p, "/", de->d_name, "/../dev"); + if (!u) + return -ENOMEM; + + v = strjoin(p, "/", found->d_name, "/../dev"); + if (!v) + return -ENOMEM; + + r = read_one_line_file(u, &a); + if (r < 0) { + log_debug_errno(r, "Failed to read %s: %m", u); + goto fallback; + } + + r = read_one_line_file(v, &b); + if (r < 0) { + log_debug_errno(r, "Failed to read %s: %m", v); + goto fallback; + } + + /* Check if the parent device is the same. If not, then the two backing devices are on + * different physical devices, and we don't support that. */ + if (!streq(a, b)) + goto fallback; + } + + found = de; + } + + if (!found) + goto fallback; + + q = strjoina(p, "/", found->d_name, "/dev"); + + r = read_one_line_file(q, &t); + if (r == -ENOENT) + goto fallback; if (r < 0) - log_debug_errno(r, "Failed to turn off coredumps, ignoring: %m"); + return r; + + if (sscanf(t, "%u:%u", &maj, &min) != 2) + return -EINVAL; + + if (maj == 0) + goto fallback; + + *dev = makedev(maj, min); + return 1; + +fallback: + *dev = dt; + return 1; } #endif /* NM_IGNORED */ diff --git a/src/systemd/src/basic/util.h b/src/systemd/src/basic/util.h index 19e9eae1..b31dfd1c 100644 --- a/src/systemd/src/basic/util.h +++ b/src/systemd/src/basic/util.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once /*** @@ -71,6 +70,8 @@ bool plymouth_running(void); bool display_is_local(const char *display) _pure_; int socket_from_display(const char *display, char **path); +int block_get_whole_disk(dev_t d, dev_t *ret); + #define NULSTR_FOREACH(i, l) \ for ((i) = (l); (i) && *(i); (i) = strchr((i), 0)+1) @@ -84,6 +85,8 @@ bool kexec_loaded(void); int prot_from_flags(int flags) _const_; +int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...); + bool in_initrd(void); void in_initrd_force(bool value); @@ -92,19 +95,6 @@ void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size, void *arg); /** - * Normal bsearch requires base to be nonnull. Here were require - * that only if nmemb > 0. - */ -static inline void* bsearch_safe(const void *key, const void *base, - size_t nmemb, size_t size, comparison_fn_t compar) { - if (nmemb <= 0) - return NULL; - - assert(base); - return bsearch(key, base, nmemb, size, compar); -} - -/** * Normal qsort requires base to be nonnull. Here were require * that only if nmemb > 0. */ @@ -199,8 +189,9 @@ uint64_t physical_memory_scale(uint64_t v, uint64_t max); uint64_t system_tasks_max(void); uint64_t system_tasks_max_scale(uint64_t v, uint64_t max); -int version(void); +int update_reboot_parameter_and_warn(const char *param); -int str_verscmp(const char *s1, const char *s2); +int version(void); -void disable_coredumps(void); +int get_block_device(const char *path, dev_t *dev); +int get_block_device_harder(const char *path, dev_t *dev); diff --git a/src/systemd/src/libsystemd-network/arp-util.c b/src/systemd/src/libsystemd-network/arp-util.c index 9b721ee6..69bd3e75 100644 --- a/src/systemd/src/libsystemd-network/arp-util.c +++ b/src/systemd/src/libsystemd-network/arp-util.c @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. @@ -26,7 +25,6 @@ #include "arp-util.h" #include "fd-util.h" -#include "unaligned.h" #include "util.h" int arp_network_bind_raw_socket(int ifindex, be32_t address, const struct ether_addr *eth_mac) { @@ -51,12 +49,12 @@ int arp_network_bind_raw_socket(int ifindex, be32_t address, const struct ether_ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ARPOP_REPLY, 1, 0), /* protocol == reply ? */ BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ /* Sender Hardware Address must be different from our own */ - BPF_STMT(BPF_LD + BPF_IMM, unaligned_read_be32(ð_mac->ether_addr_octet[0])),/* A <- 4 bytes of client's MAC */ + BPF_STMT(BPF_LD + BPF_IMM, htobe32(*((uint32_t *) eth_mac))), /* A <- 4 bytes of client's MAC */ BPF_STMT(BPF_MISC + BPF_TAX, 0), /* X <- A */ BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(struct ether_arp, arp_sha)), /* A <- 4 bytes of SHA */ BPF_STMT(BPF_ALU + BPF_XOR + BPF_X, 0), /* A xor X */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 0, 6), /* A == 0 ? */ - BPF_STMT(BPF_LD + BPF_IMM, unaligned_read_be16(ð_mac->ether_addr_octet[4])),/* A <- remainder of client's MAC */ + BPF_STMT(BPF_LD + BPF_IMM, htobe16(*((uint16_t *) (((char *) eth_mac) + 4)))), /* A <- remainder of client's MAC */ BPF_STMT(BPF_MISC + BPF_TAX, 0), /* X <- A */ BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(struct ether_arp, arp_sha) + 4), /* A <- remainder of SHA */ BPF_STMT(BPF_ALU + BPF_XOR + BPF_X, 0), /* A xor X */ @@ -105,7 +103,10 @@ int arp_network_bind_raw_socket(int ifindex, be32_t address, const struct ether_ if (r < 0) return -errno; - return TAKE_FD(s); + r = s; + s = -1; + + return r; } static int arp_send_packet(int fd, int ifindex, diff --git a/src/systemd/src/libsystemd-network/arp-util.h b/src/systemd/src/libsystemd-network/arp-util.h index decfce3f..3ef56b00 100644 --- a/src/systemd/src/libsystemd-network/arp-util.h +++ b/src/systemd/src/libsystemd-network/arp-util.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once /*** diff --git a/src/systemd/src/libsystemd-network/dhcp-identifier.c b/src/systemd/src/libsystemd-network/dhcp-identifier.c index df4d8afb..c1fa8763 100644 --- a/src/systemd/src/libsystemd-network/dhcp-identifier.c +++ b/src/systemd/src/libsystemd-network/dhcp-identifier.c @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. diff --git a/src/systemd/src/libsystemd-network/dhcp-identifier.h b/src/systemd/src/libsystemd-network/dhcp-identifier.h index 0ccee7a7..1cc0f9fb 100644 --- a/src/systemd/src/libsystemd-network/dhcp-identifier.h +++ b/src/systemd/src/libsystemd-network/dhcp-identifier.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once /*** diff --git a/src/systemd/src/libsystemd-network/dhcp-internal.h b/src/systemd/src/libsystemd-network/dhcp-internal.h index a5352695..3fdf02da 100644 --- a/src/systemd/src/libsystemd-network/dhcp-internal.h +++ b/src/systemd/src/libsystemd-network/dhcp-internal.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once /*** diff --git a/src/systemd/src/libsystemd-network/dhcp-lease-internal.h b/src/systemd/src/libsystemd-network/dhcp-lease-internal.h index 65c182f4..7847ce07 100644 --- a/src/systemd/src/libsystemd-network/dhcp-lease-internal.h +++ b/src/systemd/src/libsystemd-network/dhcp-lease-internal.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once /*** @@ -34,8 +33,6 @@ struct sd_dhcp_route { struct in_addr dst_addr; struct in_addr gw_addr; unsigned char dst_prefixlen; - - uint8_t option; }; struct sd_dhcp_raw_option { diff --git a/src/systemd/src/libsystemd-network/dhcp-network.c b/src/systemd/src/libsystemd-network/dhcp-network.c index d9067ffb..f01b2cfe 100644 --- a/src/systemd/src/libsystemd-network/dhcp-network.c +++ b/src/systemd/src/libsystemd-network/dhcp-network.c @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. @@ -34,7 +33,6 @@ #include "dhcp-internal.h" #include "fd-util.h" #include "socket-util.h" -#include "unaligned.h" static int _bind_raw_socket(int ifindex, union sockaddr_union *link, uint32_t xid, const uint8_t *mac_addr, @@ -73,13 +71,13 @@ static int _bind_raw_socket(int ifindex, union sockaddr_union *link, BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(DHCPPacket, dhcp.xid)), /* A <- client identifier */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, xid, 1, 0), /* client identifier == xid ? */ BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ - BPF_STMT(BPF_LD + BPF_IMM, unaligned_read_be32(ð_mac->ether_addr_octet[0])), /* A <- 4 bytes of client's MAC */ + BPF_STMT(BPF_LD + BPF_IMM, htobe32(*((unsigned int *) eth_mac))), /* A <- 4 bytes of client's MAC */ BPF_STMT(BPF_MISC + BPF_TAX, 0), /* X <- A */ BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(DHCPPacket, dhcp.chaddr)), /* A <- 4 bytes of MAC from dhcp.chaddr */ BPF_STMT(BPF_ALU + BPF_XOR + BPF_X, 0), /* A xor X */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 1, 0), /* A == 0 ? */ BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ - BPF_STMT(BPF_LD + BPF_IMM, unaligned_read_be16(ð_mac->ether_addr_octet[4])), /* A <- remainder of client's MAC */ + BPF_STMT(BPF_LD + BPF_IMM, htobe16(*((unsigned short *) (((char *) eth_mac) + 4)))), /* A <- remainder of client's MAC */ BPF_STMT(BPF_MISC + BPF_TAX, 0), /* X <- A */ BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(DHCPPacket, dhcp.chaddr) + 4), /* A <- remainder of MAC from dhcp.chaddr */ BPF_STMT(BPF_ALU + BPF_XOR + BPF_X, 0), /* A xor X */ @@ -125,7 +123,10 @@ static int _bind_raw_socket(int ifindex, union sockaddr_union *link, if (r < 0) return -errno; - return TAKE_FD(s); + r = s; + s = -1; + + return r; } int dhcp_network_bind_raw_socket(int ifindex, union sockaddr_union *link, @@ -210,7 +211,10 @@ int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port) { if (r < 0) return -errno; - return TAKE_FD(s); + r = s; + s = -1; + + return r; } int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link, diff --git a/src/systemd/src/libsystemd-network/dhcp-option.c b/src/systemd/src/libsystemd-network/dhcp-option.c index 08ed8a9f..e003e088 100644 --- a/src/systemd/src/libsystemd-network/dhcp-option.c +++ b/src/systemd/src/libsystemd-network/dhcp-option.c @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. @@ -193,7 +192,9 @@ static int parse_options(const uint8_t options[], size_t buflen, uint8_t *overlo if (!ascii_is_valid(string)) return -EINVAL; - free_and_replace(*error_message, string); + free(*error_message); + *error_message = string; + string = NULL; } break; @@ -255,8 +256,10 @@ int dhcp_option_parse(DHCPMessage *message, size_t len, dhcp_option_callback_t c if (message_type == 0) return -ENOMSG; - if (_error_message && IN_SET(message_type, DHCP_NAK, DHCP_DECLINE)) - *_error_message = TAKE_PTR(error_message); + if (_error_message && IN_SET(message_type, DHCP_NAK, DHCP_DECLINE)) { + *_error_message = error_message; + error_message = NULL; + } return message_type; } diff --git a/src/systemd/src/libsystemd-network/dhcp-packet.c b/src/systemd/src/libsystemd-network/dhcp-packet.c index 6d8f01f2..1bb1bfcf 100644 --- a/src/systemd/src/libsystemd-network/dhcp-packet.c +++ b/src/systemd/src/libsystemd-network/dhcp-packet.c @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. diff --git a/src/systemd/src/libsystemd-network/dhcp-protocol.h b/src/systemd/src/libsystemd-network/dhcp-protocol.h index 73a9f75e..5cf7abbf 100644 --- a/src/systemd/src/libsystemd-network/dhcp-protocol.h +++ b/src/systemd/src/libsystemd-network/dhcp-protocol.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once /*** diff --git a/src/systemd/src/libsystemd-network/dhcp6-internal.h b/src/systemd/src/libsystemd-network/dhcp6-internal.h index 13844a86..945c3b97 100644 --- a/src/systemd/src/libsystemd-network/dhcp6-internal.h +++ b/src/systemd/src/libsystemd-network/dhcp6-internal.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once /*** @@ -29,65 +28,25 @@ #include "macro.h" #include "sparse-endian.h" -/* Common option header */ -typedef struct DHCP6Option { - be16_t code; - be16_t len; - uint8_t data[]; -} _packed_ DHCP6Option; - -/* Address option */ -struct iaaddr { - struct in6_addr address; - be32_t lifetime_preferred; - be32_t lifetime_valid; -} _packed_; - -/* Prefix Delegation Prefix option */ -struct iapdprefix { - be32_t lifetime_preferred; - be32_t lifetime_valid; - uint8_t prefixlen; - struct in6_addr address; -} _packed_; - typedef struct DHCP6Address DHCP6Address; struct DHCP6Address { LIST_FIELDS(DHCP6Address, addresses); - union { - struct iaaddr iaaddr; - struct iapdprefix iapdprefix; - }; + struct { + struct in6_addr address; + be32_t lifetime_preferred; + be32_t lifetime_valid; + } iaaddr _packed_; }; -/* Non-temporary Address option */ -struct ia_na { - be32_t id; - be32_t lifetime_t1; - be32_t lifetime_t2; -} _packed_; - -/* Prefix Delegation option */ -struct ia_pd { - be32_t id; - be32_t lifetime_t1; - be32_t lifetime_t2; -} _packed_; - -/* Temporary Address option */ -struct ia_ta { - be32_t id; -} _packed_; - struct DHCP6IA { uint16_t type; - union { - struct ia_na ia_na; - struct ia_pd ia_pd; - struct ia_ta ia_ta; - }; + struct { + be32_t id; + be32_t lifetime_t1; + be32_t lifetime_t2; + } _packed_; sd_event_source *timeout_t1; sd_event_source *timeout_t2; @@ -102,12 +61,10 @@ typedef struct DHCP6IA DHCP6IA; int dhcp6_option_append(uint8_t **buf, size_t *buflen, uint16_t code, size_t optlen, const void *optval); int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, DHCP6IA *ia); -int dhcp6_option_append_pd(uint8_t *buf, size_t len, DHCP6IA *pd); -int dhcp6_option_append_fqdn(uint8_t **buf, size_t *buflen, const char *fqdn); int dhcp6_option_parse(uint8_t **buf, size_t *buflen, uint16_t *optcode, size_t *optlen, uint8_t **optvalue); -int dhcp6_option_parse_status(DHCP6Option *option); -int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia); +int dhcp6_option_parse_ia(uint8_t **buf, size_t *buflen, uint16_t iatype, + DHCP6IA *ia); int dhcp6_option_parse_ip6addrs(uint8_t *optval, uint16_t optlen, struct in6_addr **addrs, size_t count, size_t *allocated); diff --git a/src/systemd/src/libsystemd-network/dhcp6-lease-internal.h b/src/systemd/src/libsystemd-network/dhcp6-lease-internal.h index 45e0e824..14e708ef 100644 --- a/src/systemd/src/libsystemd-network/dhcp6-lease-internal.h +++ b/src/systemd/src/libsystemd-network/dhcp6-lease-internal.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once /*** @@ -36,10 +35,8 @@ struct sd_dhcp6_lease { bool rapid_commit; DHCP6IA ia; - DHCP6IA pd; DHCP6Address *addr_iter; - DHCP6Address *prefix_iter; struct in6_addr *dns; size_t dns_count; diff --git a/src/systemd/src/libsystemd-network/dhcp6-network.c b/src/systemd/src/libsystemd-network/dhcp6-network.c index 85231084..e4883019 100644 --- a/src/systemd/src/libsystemd-network/dhcp6-network.c +++ b/src/systemd/src/libsystemd-network/dhcp6-network.c @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. @@ -69,7 +68,9 @@ int dhcp6_network_bind_udp_socket(int index, struct in6_addr *local_address) { if (r < 0) return -errno; - return TAKE_FD(s); + r = s; + s = -1; + return r; } int dhcp6_network_send_udp_socket(int s, struct in6_addr *server_address, diff --git a/src/systemd/src/libsystemd-network/dhcp6-option.c b/src/systemd/src/libsystemd-network/dhcp6-option.c index d449a9c7..3a77e34d 100644 --- a/src/systemd/src/libsystemd-network/dhcp6-option.c +++ b/src/systemd/src/libsystemd-network/dhcp6-option.c @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. @@ -28,7 +27,6 @@ #include "alloc-util.h" #include "dhcp6-internal.h" -#include "dhcp6-lease-internal.h" #include "dhcp6-protocol.h" #include "dns-domain.h" #include "sparse-endian.h" @@ -36,27 +34,14 @@ #include "unaligned.h" #include "util.h" -typedef struct DHCP6StatusOption { - struct DHCP6Option option; - be16_t status; - char msg[]; -} _packed_ DHCP6StatusOption; +#define DHCP6_OPTION_IA_NA_LEN 12 +#define DHCP6_OPTION_IA_TA_LEN 4 -typedef struct DHCP6AddressOption { - struct DHCP6Option option; - struct iaaddr iaaddr; - uint8_t options[]; -} _packed_ DHCP6AddressOption; - -typedef struct DHCP6PDPrefixOption { - struct DHCP6Option option; - struct iapdprefix iapdprefix; - uint8_t options[]; -} _packed_ DHCP6PDPrefixOption; - -#define DHCP6_OPTION_IA_NA_LEN (sizeof(struct ia_na)) -#define DHCP6_OPTION_IA_PD_LEN (sizeof(struct ia_pd)) -#define DHCP6_OPTION_IA_TA_LEN (sizeof(struct ia_ta)) +typedef struct DHCP6Option { + be16_t code; + be16_t len; + uint8_t data[]; +} _packed_ DHCP6Option; static int option_append_hdr(uint8_t **buf, size_t *buflen, uint16_t optcode, size_t optlen) { @@ -99,7 +84,7 @@ int dhcp6_option_append(uint8_t **buf, size_t *buflen, uint16_t code, int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, DHCP6IA *ia) { uint16_t len; uint8_t *ia_hdr; - size_t iaid_offset, ia_buflen, ia_addrlen = 0; + size_t ia_buflen, ia_addrlen = 0; DHCP6Address *addr; int r; @@ -108,12 +93,10 @@ int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, DHCP6IA *ia) { switch (ia->type) { case SD_DHCP6_OPTION_IA_NA: len = DHCP6_OPTION_IA_NA_LEN; - iaid_offset = offsetof(DHCP6IA, ia_na); break; case SD_DHCP6_OPTION_IA_TA: len = DHCP6_OPTION_IA_TA_LEN; - iaid_offset = offsetof(DHCP6IA, ia_ta); break; default: @@ -129,7 +112,7 @@ int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, DHCP6IA *ia) { *buf += sizeof(DHCP6Option); *buflen -= sizeof(DHCP6Option); - memcpy(*buf, (char*) ia + iaid_offset, len); + memcpy(*buf, &ia->id, len); *buf += len; *buflen -= len; @@ -155,69 +138,6 @@ int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, DHCP6IA *ia) { return 0; } -int dhcp6_option_append_fqdn(uint8_t **buf, size_t *buflen, const char *fqdn) { - uint8_t buffer[1 + DNS_WIRE_FOMAT_HOSTNAME_MAX]; - int r; - - assert_return(buf && *buf && buflen && fqdn, -EINVAL); - - buffer[0] = DHCP6_FQDN_FLAG_S; /* Request server to perform AAAA RR DNS updates */ - - /* Store domain name after flags field */ - r = dns_name_to_wire_format(fqdn, buffer + 1, sizeof(buffer) - 1, false); - if (r <= 0) - return r; - - /* - * According to RFC 4704, chapter 4.2 only add terminating zero-length - * label in case a FQDN is provided. Since dns_name_to_wire_format - * always adds terminating zero-length label remove if only a hostname - * is provided. - */ - if (dns_name_is_single_label(fqdn)) - r--; - - r = dhcp6_option_append(buf, buflen, SD_DHCP6_OPTION_FQDN, 1 + r, buffer); - - return r; -} - -int dhcp6_option_append_pd(uint8_t *buf, size_t len, DHCP6IA *pd) { - DHCP6Option *option = (DHCP6Option *)buf; - size_t i = sizeof(*option) + sizeof(pd->ia_pd); - DHCP6Address *prefix; - - assert_return(buf, -EINVAL); - assert_return(pd, -EINVAL); - assert_return(pd->type == SD_DHCP6_OPTION_IA_PD, -EINVAL); - - if (len < i) - return -ENOBUFS; - - option->code = htobe16(SD_DHCP6_OPTION_IA_PD); - - memcpy(&option->data, &pd->ia_pd, sizeof(pd->ia_pd)); - - LIST_FOREACH(addresses, prefix, pd->addresses) { - DHCP6PDPrefixOption *prefix_opt; - - if (len < i + sizeof(*prefix_opt)) - return -ENOBUFS; - - prefix_opt = (DHCP6PDPrefixOption *)&buf[i]; - prefix_opt->option.code = htobe16(SD_DHCP6_OPTION_IA_PD_PREFIX); - prefix_opt->option.len = htobe16(sizeof(prefix_opt->iapdprefix)); - - memcpy(&prefix_opt->iapdprefix, &prefix->iapdprefix, - sizeof(struct iapdprefix)); - - i += sizeof(*prefix_opt); - } - - option->len = htobe16(i - sizeof(*option)); - - return i; -} static int option_parse_hdr(uint8_t **buf, size_t *buflen, uint16_t *optcode, size_t *optlen) { DHCP6Option *option = (DHCP6Option*) *buf; @@ -264,147 +184,35 @@ int dhcp6_option_parse(uint8_t **buf, size_t *buflen, uint16_t *optcode, return 0; } -int dhcp6_option_parse_status(DHCP6Option *option) { - DHCP6StatusOption *statusopt = (DHCP6StatusOption *)option; - - if (be16toh(option->len) + sizeof(DHCP6Option) < sizeof(*statusopt)) - return -ENOBUFS; - - return be16toh(statusopt->status); -} - -static int dhcp6_option_parse_address(DHCP6Option *option, DHCP6IA *ia, - uint32_t *lifetime_valid) { - DHCP6AddressOption *addr_option = (DHCP6AddressOption *)option; - DHCP6Address *addr; - uint32_t lt_valid, lt_pref; - int r; - - if (be16toh(option->len) + sizeof(DHCP6Option) < sizeof(*addr_option)) - return -ENOBUFS; - - lt_valid = be32toh(addr_option->iaaddr.lifetime_valid); - lt_pref = be32toh(addr_option->iaaddr.lifetime_preferred); - - if (lt_valid == 0 || lt_pref > lt_valid) { - log_dhcp6_client(client, "Valid lifetime of an IA address is zero or preferred lifetime %d > valid lifetime %d", - lt_pref, lt_valid); - - return 0; - } - - if (be16toh(option->len) + sizeof(DHCP6Option) > sizeof(*addr_option)) { - r = dhcp6_option_parse_status((DHCP6Option *)addr_option->options); - if (r != 0) - return r < 0 ? r: 0; - } - - addr = new0(DHCP6Address, 1); - if (!addr) - return -ENOMEM; - - LIST_INIT(addresses, addr); - memcpy(&addr->iaaddr, option->data, sizeof(addr->iaaddr)); - - LIST_PREPEND(addresses, ia->addresses, addr); - - *lifetime_valid = be32toh(addr->iaaddr.lifetime_valid); - - return 0; -} - -static int dhcp6_option_parse_pdprefix(DHCP6Option *option, DHCP6IA *ia, - uint32_t *lifetime_valid) { - DHCP6PDPrefixOption *pdprefix_option = (DHCP6PDPrefixOption *)option; - DHCP6Address *prefix; - uint32_t lt_valid, lt_pref; +int dhcp6_option_parse_ia(uint8_t **buf, size_t *buflen, uint16_t iatype, + DHCP6IA *ia) { int r; - - if (be16toh(option->len) + sizeof(DHCP6Option) < sizeof(*pdprefix_option)) - return -ENOBUFS; - - lt_valid = be32toh(pdprefix_option->iapdprefix.lifetime_valid); - lt_pref = be32toh(pdprefix_option->iapdprefix.lifetime_preferred); - - if (lt_valid == 0 || lt_pref > lt_valid) { - log_dhcp6_client(client, "Valid lifetieme of a PD prefix is zero or preferred lifetime %d > valid lifetime %d", - lt_pref, lt_valid); - - return 0; - } - - if (be16toh(option->len) + sizeof(DHCP6Option) > sizeof(*pdprefix_option)) { - r = dhcp6_option_parse_status((DHCP6Option *)pdprefix_option->options); - if (r != 0) - return r < 0 ? r: 0; - } - - prefix = new0(DHCP6Address, 1); - if (!prefix) - return -ENOMEM; - - LIST_INIT(addresses, prefix); - memcpy(&prefix->iapdprefix, option->data, sizeof(prefix->iapdprefix)); - - LIST_PREPEND(addresses, ia->addresses, prefix); - - *lifetime_valid = be32toh(prefix->iapdprefix.lifetime_valid); - - return 0; -} - -int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia) { - uint16_t iatype, optlen; - size_t i, len; - int r = 0, status; - uint16_t opt; + uint16_t opt, status; + size_t optlen; size_t iaaddr_offset; - uint32_t lt_t1, lt_t2, lt_valid = 0, lt_min = UINT32_MAX; + DHCP6Address *addr; + uint32_t lt_t1, lt_t2, lt_valid, lt_pref, lt_min = ~0; assert_return(ia, -EINVAL); assert_return(!ia->addresses, -EINVAL); - iatype = be16toh(iaoption->code); - len = be16toh(iaoption->len); - switch (iatype) { case SD_DHCP6_OPTION_IA_NA: - if (len < DHCP6_OPTION_IA_NA_LEN) { + if (*buflen < DHCP6_OPTION_IA_NA_LEN + sizeof(DHCP6Option) + + sizeof(addr->iaaddr)) { r = -ENOBUFS; goto error; } iaaddr_offset = DHCP6_OPTION_IA_NA_LEN; - memcpy(&ia->ia_na, iaoption->data, sizeof(ia->ia_na)); - - lt_t1 = be32toh(ia->ia_na.lifetime_t1); - lt_t2 = be32toh(ia->ia_na.lifetime_t2); - - if (lt_t1 && lt_t2 && lt_t1 > lt_t2) { - log_dhcp6_client(client, "IA NA T1 %ds > T2 %ds", - lt_t1, lt_t2); - r = -EINVAL; - goto error; - } - - break; + memcpy(&ia->id, *buf, iaaddr_offset); - case SD_DHCP6_OPTION_IA_PD: - - if (len < sizeof(ia->ia_pd)) { - r = -ENOBUFS; - goto error; - } - - iaaddr_offset = sizeof(ia->ia_pd); - memcpy(&ia->ia_pd, iaoption->data, sizeof(ia->ia_pd)); - - lt_t1 = be32toh(ia->ia_pd.lifetime_t1); - lt_t2 = be32toh(ia->ia_pd.lifetime_t2); + lt_t1 = be32toh(ia->lifetime_t1); + lt_t2 = be32toh(ia->lifetime_t2); if (lt_t1 && lt_t2 && lt_t1 > lt_t2) { - log_dhcp6_client(client, "IA PD T1 %ds > T2 %ds", + log_dhcp6_client(client, "IA T1 %ds > T2 %ds", lt_t1, lt_t2); r = -EINVAL; goto error; @@ -413,13 +221,17 @@ int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia) { break; case SD_DHCP6_OPTION_IA_TA: - if (len < DHCP6_OPTION_IA_TA_LEN) { + if (*buflen < DHCP6_OPTION_IA_TA_LEN + sizeof(DHCP6Option) + + sizeof(addr->iaaddr)) { r = -ENOBUFS; goto error; } iaaddr_offset = DHCP6_OPTION_IA_TA_LEN; - memcpy(&ia->ia_ta.id, iaoption->data, sizeof(ia->ia_ta)); + memcpy(&ia->id, *buf, iaaddr_offset); + + ia->lifetime_t1 = 0; + ia->lifetime_t2 = 0; break; @@ -429,63 +241,48 @@ int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia) { } ia->type = iatype; - i = iaaddr_offset; - while (i < len) { - DHCP6Option *option = (DHCP6Option *)&iaoption->data[i]; - - if (len < i + sizeof(*option) || len < i + sizeof(*option) + be16toh(option->len)) { - r = -ENOBUFS; - goto error; - } + *buflen -= iaaddr_offset; + *buf += iaaddr_offset; - opt = be16toh(option->code); - optlen = be16toh(option->len); + while ((r = option_parse_hdr(buf, buflen, &opt, &optlen)) >= 0) { switch (opt) { case SD_DHCP6_OPTION_IAADDR: - if (!IN_SET(ia->type, SD_DHCP6_OPTION_IA_NA, SD_DHCP6_OPTION_IA_TA)) { - log_dhcp6_client(client, "IA Address option not in IA NA or TA option"); - r = -EINVAL; + addr = new0(DHCP6Address, 1); + if (!addr) { + r = -ENOMEM; goto error; } - r = dhcp6_option_parse_address(option, ia, <_valid); - if (r < 0) - goto error; - - if (lt_valid < lt_min) - lt_min = lt_valid; + LIST_INIT(addresses, addr); - break; + memcpy(&addr->iaaddr, *buf, sizeof(addr->iaaddr)); - case SD_DHCP6_OPTION_IA_PD_PREFIX: + lt_valid = be32toh(addr->iaaddr.lifetime_valid); + lt_pref = be32toh(addr->iaaddr.lifetime_valid); - if (!IN_SET(ia->type, SD_DHCP6_OPTION_IA_PD)) { - log_dhcp6_client(client, "IA PD Prefix option not in IA PD option"); - r = -EINVAL; - goto error; + if (!lt_valid || lt_pref > lt_valid) { + log_dhcp6_client(client, "IA preferred %ds > valid %ds", + lt_pref, lt_valid); + free(addr); + } else { + LIST_PREPEND(addresses, ia->addresses, addr); + if (lt_valid < lt_min) + lt_min = lt_valid; } - r = dhcp6_option_parse_pdprefix(option, ia, <_valid); - if (r < 0) - goto error; - - if (lt_valid < lt_min) - lt_min = lt_valid; - break; case SD_DHCP6_OPTION_STATUS_CODE: + if (optlen < sizeof(status)) + break; - status = dhcp6_option_parse_status(option); + status = (*buf)[0] << 8 | (*buf)[1]; if (status) { log_dhcp6_client(client, "IA status %d", status); - - dhcp6_lease_free_ia(ia); - r = -EINVAL; goto error; } @@ -497,41 +294,30 @@ int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia) { break; } - i += sizeof(*option) + optlen; + *buflen -= optlen; + *buf += optlen; } - switch(iatype) { - case SD_DHCP6_OPTION_IA_NA: - if (!ia->ia_na.lifetime_t1 && !ia->ia_na.lifetime_t2) { - lt_t1 = lt_min / 2; - lt_t2 = lt_min / 10 * 8; - ia->ia_na.lifetime_t1 = htobe32(lt_t1); - ia->ia_na.lifetime_t2 = htobe32(lt_t2); - - log_dhcp6_client(client, "Computed IA NA T1 %ds and T2 %ds as both were zero", - lt_t1, lt_t2); - } - - break; - - case SD_DHCP6_OPTION_IA_PD: - if (!ia->ia_pd.lifetime_t1 && !ia->ia_pd.lifetime_t2) { - lt_t1 = lt_min / 2; - lt_t2 = lt_min / 10 * 8; - ia->ia_pd.lifetime_t1 = htobe32(lt_t1); - ia->ia_pd.lifetime_t2 = htobe32(lt_t2); + if (r == -ENOMSG) + r = 0; - log_dhcp6_client(client, "Computed IA PD T1 %ds and T2 %ds as both were zero", - lt_t1, lt_t2); - } + if (!ia->lifetime_t1 && !ia->lifetime_t2) { + lt_t1 = lt_min / 2; + lt_t2 = lt_min / 10 * 8; + ia->lifetime_t1 = htobe32(lt_t1); + ia->lifetime_t2 = htobe32(lt_t2); - break; - - default: - break; + log_dhcp6_client(client, "Computed IA T1 %ds and T2 %ds as both were zero", + lt_t1, lt_t2); } + if (*buflen) + r = -ENOMSG; + error: + *buf += *buflen; + *buflen = 0; + return r; } @@ -619,7 +405,8 @@ int dhcp6_option_parse_domainname(const uint8_t *optval, uint16_t optlen, char * idx++; } - *str_arr = TAKE_PTR(names); + *str_arr = names; + names = NULL; return idx; diff --git a/src/systemd/src/libsystemd-network/dhcp6-protocol.h b/src/systemd/src/libsystemd-network/dhcp6-protocol.h index 5f7e809b..2487c470 100644 --- a/src/systemd/src/libsystemd-network/dhcp6-protocol.h +++ b/src/systemd/src/libsystemd-network/dhcp6-protocol.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once /*** @@ -34,7 +33,6 @@ struct DHCP6Message { } _packed_; be32_t transaction_id; }; - uint8_t options[]; } _packed_; typedef struct DHCP6Message DHCP6Message; @@ -106,9 +104,3 @@ enum { DHCP6_STATUS_USE_MULTICAST = 5, _DHCP6_STATUS_MAX = 6, }; - -enum { - DHCP6_FQDN_FLAG_S = (1 << 0), - DHCP6_FQDN_FLAG_O = (1 << 1), - DHCP6_FQDN_FLAG_N = (1 << 2), -}; diff --git a/src/systemd/src/libsystemd-network/lldp-internal.h b/src/systemd/src/libsystemd-network/lldp-internal.h index 2673aa1c..becc162f 100644 --- a/src/systemd/src/libsystemd-network/lldp-internal.h +++ b/src/systemd/src/libsystemd-network/lldp-internal.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once /*** diff --git a/src/systemd/src/libsystemd-network/lldp-neighbor.c b/src/systemd/src/libsystemd-network/lldp-neighbor.c index cffbfb98..c560a864 100644 --- a/src/systemd/src/libsystemd-network/lldp-neighbor.c +++ b/src/systemd/src/libsystemd-network/lldp-neighbor.c @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. diff --git a/src/systemd/src/libsystemd-network/lldp-neighbor.h b/src/systemd/src/libsystemd-network/lldp-neighbor.h index 76d4c0c7..c1a7606d 100644 --- a/src/systemd/src/libsystemd-network/lldp-neighbor.h +++ b/src/systemd/src/libsystemd-network/lldp-neighbor.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once /*** diff --git a/src/systemd/src/libsystemd-network/lldp-network.c b/src/systemd/src/libsystemd-network/lldp-network.c index b8a10d54..4466a050 100644 --- a/src/systemd/src/libsystemd-network/lldp-network.c +++ b/src/systemd/src/libsystemd-network/lldp-network.c @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. @@ -94,5 +93,8 @@ int lldp_network_bind_raw_socket(int ifindex) { if (r < 0) return -errno; - return TAKE_FD(fd); + r = fd; + fd = -1; + + return r; } diff --git a/src/systemd/src/libsystemd-network/lldp-network.h b/src/systemd/src/libsystemd-network/lldp-network.h index c0f8cbe1..c4cf8c79 100644 --- a/src/systemd/src/libsystemd-network/lldp-network.h +++ b/src/systemd/src/libsystemd-network/lldp-network.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once /*** diff --git a/src/systemd/src/libsystemd-network/network-internal.c b/src/systemd/src/libsystemd-network/network-internal.c index a8a5658b..de37b9f0 100644 --- a/src/systemd/src/libsystemd-network/network-internal.c +++ b/src/systemd/src/libsystemd-network/network-internal.c @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. @@ -24,7 +23,6 @@ #include <linux/if.h> #include <netinet/ether.h> -#include "sd-id128.h" #include "sd-ndisc.h" #include "alloc-util.h" @@ -120,8 +118,7 @@ bool net_match_config(const struct ether_addr *match_mac, char * const *match_names, Condition *match_host, Condition *match_virt, - Condition *match_kernel_cmdline, - Condition *match_kernel_version, + Condition *match_kernel, Condition *match_arch, const struct ether_addr *dev_mac, const char *dev_path, @@ -136,10 +133,7 @@ bool net_match_config(const struct ether_addr *match_mac, if (match_virt && condition_test(match_virt) <= 0) return false; - if (match_kernel_cmdline && condition_test(match_kernel_cmdline) <= 0) - return false; - - if (match_kernel_version && condition_test(match_kernel_version) <= 0) + if (match_kernel && condition_test(match_kernel) <= 0) return false; if (match_arch && condition_test(match_arch) <= 0) @@ -279,9 +273,10 @@ int config_parse_ifalias(const char *unit, } free(*s); - if (*n) - *s = TAKE_PTR(n); - else + if (*n) { + *s = n; + n = NULL; + } else *s = NULL; return 0; @@ -427,7 +422,7 @@ int deserialize_in_addrs(struct in_addr **ret, const char *string) { if (r == 0) break; - new_addresses = reallocarray(addresses, size + 1, sizeof(struct in_addr)); + new_addresses = realloc(addresses, (size + 1) * sizeof(struct in_addr)); if (!new_addresses) return -ENOMEM; else @@ -440,7 +435,8 @@ int deserialize_in_addrs(struct in_addr **ret, const char *string) { size++; } - *ret = TAKE_PTR(addresses); + *ret = addresses; + addresses = NULL; return size; } @@ -480,7 +476,7 @@ int deserialize_in6_addrs(struct in6_addr **ret, const char *string) { if (r == 0) break; - new_addresses = reallocarray(addresses, size + 1, sizeof(struct in6_addr)); + new_addresses = realloc(addresses, (size + 1) * sizeof(struct in6_addr)); if (!new_addresses) return -ENOMEM; else @@ -493,7 +489,8 @@ int deserialize_in6_addrs(struct in6_addr **ret, const char *string) { size++; } - *ret = TAKE_PTR(addresses); + *ret = addresses; + addresses = NULL; return size; } @@ -586,7 +583,8 @@ int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t *ret_size = size; *ret_allocated = allocated; - *ret = TAKE_PTR(routes); + *ret = routes; + routes = NULL; return 0; } diff --git a/src/systemd/src/libsystemd-network/network-internal.h b/src/systemd/src/libsystemd-network/network-internal.h index 4e69f1a5..4666f174 100644 --- a/src/systemd/src/libsystemd-network/network-internal.h +++ b/src/systemd/src/libsystemd-network/network-internal.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once /*** @@ -37,8 +36,7 @@ bool net_match_config(const struct ether_addr *match_mac, char * const *match_name, Condition *match_host, Condition *match_virt, - Condition *match_kernel_cmdline, - Condition *match_kernel_version, + Condition *match_kernel, Condition *match_arch, const struct ether_addr *dev_mac, const char *dev_path, diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-client.c b/src/systemd/src/libsystemd-network/sd-dhcp-client.c index b93b7334..5eab0050 100644 --- a/src/systemd/src/libsystemd-network/sd-dhcp-client.c +++ b/src/systemd/src/libsystemd-network/sd-dhcp-client.c @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. @@ -358,10 +357,9 @@ int sd_dhcp_client_set_client_id( * without further modification. Otherwise, if duid_type is supported, DUID * is set based on that type. Otherwise, an error is returned. */ -static int dhcp_client_set_iaid_duid( +int sd_dhcp_client_set_iaid_duid( sd_dhcp_client *client, uint32_t iaid, - bool append_iaid, uint16_t duid_type, const void *duid, size_t duid_len) { @@ -382,17 +380,15 @@ static int dhcp_client_set_iaid_duid( zero(client->client_id); client->client_id.type = 255; - if (append_iaid) { - /* If IAID is not configured, generate it. */ - if (iaid == 0) { - r = dhcp_identifier_set_iaid(client->ifindex, client->mac_addr, - client->mac_addr_len, - &client->client_id.ns.iaid); - if (r < 0) - return r; - } else - client->client_id.ns.iaid = htobe32(iaid); - } + /* If IAID is not configured, generate it. */ + if (iaid == 0) { + r = dhcp_identifier_set_iaid(client->ifindex, client->mac_addr, + client->mac_addr_len, + &client->client_id.ns.iaid); + if (r < 0) + return r; + } else + client->client_id.ns.iaid = htobe32(iaid); if (duid != NULL) { client->client_id.ns.duid.type = htobe16(duid_type); @@ -406,7 +402,7 @@ static int dhcp_client_set_iaid_duid( return -EOPNOTSUPP; client->client_id_len = sizeof(client->client_id.type) + len + - (append_iaid ? sizeof(client->client_id.ns.iaid) : 0); + sizeof(client->client_id.ns.iaid); if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) { log_dhcp_client(client, "Configured IAID+DUID, restarting."); @@ -416,23 +412,6 @@ static int dhcp_client_set_iaid_duid( return 0; } - -int sd_dhcp_client_set_iaid_duid( - sd_dhcp_client *client, - uint32_t iaid, - uint16_t duid_type, - const void *duid, - size_t duid_len) { - return dhcp_client_set_iaid_duid(client, iaid, true, duid_type, duid, duid_len); -} - -int sd_dhcp_client_set_duid( - sd_dhcp_client *client, - uint16_t duid_type, - const void *duid, - size_t duid_len) { - return dhcp_client_set_iaid_duid(client, 0, false, duid_type, duid, duid_len); -} #endif /* NM_IGNORED */ int sd_dhcp_client_set_hostname( @@ -441,9 +420,9 @@ int sd_dhcp_client_set_hostname( assert_return(client, -EINVAL); - /* Make sure hostnames qualify as DNS and as Linux hostnames */ + /* Refuse hostnames that neither qualify as DNS nor as Linux hosntames */ if (hostname && - !(hostname_is_valid(hostname, false) && dns_name_is_valid(hostname) > 0)) + !(hostname_is_valid(hostname, false) || dns_name_is_valid(hostname) > 0)) return -EINVAL; return free_and_strdup(&client->hostname, hostname); @@ -854,6 +833,7 @@ static int client_send_request(sd_dhcp_client *client) { client’s IP address. */ + /* fall through */ case DHCP_STATE_REBINDING: /* ’server identifier’ MUST NOT be filled in, ’requested IP address’ option MUST NOT be filled in, ’ciaddr’ MUST be filled in with @@ -1285,9 +1265,9 @@ static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer, size_ if (!lease->have_subnet_mask) { r = dhcp_lease_set_default_subnet_mask(lease); if (r < 0) { - log_dhcp_client(client, - "received lease lacks subnet mask, " - "and a fallback one cannot be generated, ignoring"); + log_dhcp_client(client, "received lease lacks subnet " + "mask, and a fallback one can not be " + "generated, ignoring"); return -ENOMSG; } } @@ -1356,9 +1336,9 @@ static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack, size_t le if (lease->subnet_mask == INADDR_ANY) { r = dhcp_lease_set_default_subnet_mask(lease); if (r < 0) { - log_dhcp_client(client, - "received lease lacks subnet mask, " - "and a fallback one cannot be generated, ignoring"); + log_dhcp_client(client, "received lease lacks subnet " + "mask, and a fallback one can not be " + "generated, ignoring"); return -ENOMSG; } } diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-lease.c b/src/systemd/src/libsystemd-network/sd-dhcp-lease.c index c272a61e..c00190b5 100644 --- a/src/systemd/src/libsystemd-network/sd-dhcp-lease.c +++ b/src/systemd/src/libsystemd-network/sd-dhcp-lease.c @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. @@ -24,7 +23,6 @@ #include <arpa/inet.h> #include <errno.h> #include <stdio.h> -#include <stdio_ext.h> #include <stdlib.h> #include <string.h> @@ -396,7 +394,9 @@ static int lease_parse_domain(const uint8_t *option, size_t len, char **ret) { if (dns_name_is_root(normalized)) return -EINVAL; - free_and_replace(*ret, normalized); + free(*ret); + *ret = normalized; + normalized = NULL; return 0; } @@ -473,7 +473,6 @@ static int lease_parse_routes( struct sd_dhcp_route *route = *routes + *routes_size; int r; - route->option = SD_DHCP_OPTION_STATIC_ROUTE; r = in4_addr_default_prefixlen((struct in_addr*) option, &route->dst_prefixlen); if (r < 0) { log_debug("Failed to determine destination prefix length from class based IP, ignoring"); @@ -517,7 +516,6 @@ static int lease_parse_classless_routes( return -ENOMEM; route = *routes + *routes_size; - route->option = SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE; dst_octets = (*option == 0 ? 0 : ((*option - 1) / 8) + 1); route->dst_prefixlen = *option; @@ -687,7 +685,9 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void return 0; } - free_and_replace(lease->timezone, tz); + free(lease->timezone); + lease->timezone = tz; + tz = NULL; break; } @@ -809,7 +809,8 @@ int dhcp_lease_parse_search_domains(const uint8_t *option, size_t len, char ***d pos = next_chunk; } - *domains = TAKE_PTR(names); + *domains = names; + names = NULL; return cnt; } @@ -880,8 +881,7 @@ 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); + fchmod(fileno(f), 0644); fprintf(f, "# This is private data. Do not parse.\n"); @@ -928,16 +928,16 @@ int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) { r = sd_dhcp_lease_get_dns(lease, &addresses); if (r > 0) { - fputs("DNS=", f); + fputs_unlocked("DNS=", f); serialize_in_addrs(f, addresses, r); - fputs("\n", f); + fputs_unlocked("\n", f); } r = sd_dhcp_lease_get_ntp(lease, &addresses); if (r > 0) { - fputs("NTP=", f); + fputs_unlocked("NTP=", f); serialize_in_addrs(f, addresses, r); - fputs("\n", f); + fputs_unlocked("\n", f); } r = sd_dhcp_lease_get_domainname(lease, &string); @@ -946,9 +946,9 @@ int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) { r = sd_dhcp_lease_get_search_domains(lease, &search_domains); if (r > 0) { - fputs("DOMAIN_SEARCH_LIST=", f); + fputs_unlocked("DOMAIN_SEARCH_LIST=", f); fputstrv(f, search_domains, NULL, NULL); - fputs("\n", f); + fputs_unlocked("\n", f); } r = sd_dhcp_lease_get_hostname(lease, &string); @@ -992,7 +992,7 @@ int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) { } LIST_FOREACH(options, option, lease->private_options) { - char key[STRLEN("OPTION_000")+1]; + char key[strlen("OPTION_000")+1]; xsprintf(key, "OPTION_%" PRIu8, option->tag); r = serialize_dhcp_option(f, key, option->data, option->length); diff --git a/src/systemd/src/libsystemd-network/sd-dhcp6-client.c b/src/systemd/src/libsystemd-network/sd-dhcp6-client.c index f22daa3c..f512b65b 100644 --- a/src/systemd/src/libsystemd-network/sd-dhcp6-client.c +++ b/src/systemd/src/libsystemd-network/sd-dhcp6-client.c @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. @@ -32,9 +31,7 @@ #include "dhcp6-internal.h" #include "dhcp6-lease-internal.h" #include "dhcp6-protocol.h" -#include "dns-domain.h" #include "fd-util.h" -#include "hostname-util.h" #include "in-addr-util.h" #include "network-internal.h" #include "random-util.h" @@ -56,8 +53,6 @@ struct sd_dhcp6_client { size_t mac_addr_len; uint16_t arp_type; DHCP6IA ia_na; - DHCP6IA ia_pd; - bool prefix_delegation; be32_t transaction_id; usec_t transaction_start; struct sd_dhcp6_lease *lease; @@ -66,7 +61,6 @@ struct sd_dhcp6_client { be16_t *req_opts; size_t req_opts_allocated; size_t req_opts_len; - char *fqdn; sd_event_source *receive_message; usec_t retransmit_time; uint8_t retransmit_count; @@ -235,27 +229,12 @@ int sd_dhcp6_client_set_iaid(sd_dhcp6_client *client, uint32_t iaid) { assert_return(client, -EINVAL); assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY); - client->ia_na.ia_na.id = htobe32(iaid); - client->ia_pd.ia_pd.id = htobe32(iaid); + client->ia_na.id = htobe32(iaid); return 0; } #endif /* NM_IGNORED */ -int sd_dhcp6_client_set_fqdn( - sd_dhcp6_client *client, - const char *fqdn) { - - assert_return(client, -EINVAL); - - /* Make sure FQDN qualifies as DNS and as Linux hostname */ - if (fqdn && - !(hostname_is_valid(fqdn, false) && dns_name_is_valid(fqdn) > 0)) - return -EINVAL; - - return free_and_strdup(&client->fqdn, fqdn); -} - int sd_dhcp6_client_set_information_request(sd_dhcp6_client *client, int enabled) { assert_return(client, -EINVAL); assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY); @@ -286,7 +265,6 @@ int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client, uint16_t option) case SD_DHCP6_OPTION_DOMAIN_LIST: case SD_DHCP6_OPTION_SNTP_SERVERS: case SD_DHCP6_OPTION_NTP_SERVER: - case SD_DHCP6_OPTION_RAPID_COMMIT: break; default: @@ -306,14 +284,6 @@ int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client, uint16_t option) return 0; } -int sd_dhcp6_client_set_prefix_delegation(sd_dhcp6_client *client, bool delegation) { - assert_return(client, -EINVAL); - - client->prefix_delegation = delegation; - - return 0; -} - int sd_dhcp6_client_get_lease(sd_dhcp6_client *client, sd_dhcp6_lease **ret) { assert_return(client, -EINVAL); @@ -352,6 +322,8 @@ static int client_reset(sd_dhcp6_client *client) { client->receive_message = sd_event_source_unref(client->receive_message); + client->fd = safe_close(client->fd); + client->transaction_id = 0; client->transaction_start = 0; @@ -421,21 +393,6 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) { if (r < 0) return r; - if (client->fqdn) { - r = dhcp6_option_append_fqdn(&opt, &optlen, client->fqdn); - if (r < 0) - return r; - } - - if (client->prefix_delegation) { - r = dhcp6_option_append_pd(opt, optlen, &client->ia_pd); - if (r < 0) - return r; - - opt += r; - optlen -= r; - } - break; case DHCP6_STATE_REQUEST: @@ -456,21 +413,6 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) { if (r < 0) return r; - if (client->fqdn) { - r = dhcp6_option_append_fqdn(&opt, &optlen, client->fqdn); - if (r < 0) - return r; - } - - if (client->prefix_delegation) { - r = dhcp6_option_append_pd(opt, optlen, &client->lease->pd); - if (r < 0) - return r; - - opt += r; - optlen -= r; - } - break; case DHCP6_STATE_REBIND: @@ -480,21 +422,6 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) { if (r < 0) return r; - if (client->fqdn) { - r = dhcp6_option_append_fqdn(&opt, &optlen, client->fqdn); - if (r < 0) - return r; - } - - if (client->prefix_delegation) { - r = dhcp6_option_append_pd(opt, optlen, &client->lease->pd); - if (r < 0) - return r; - - opt += r; - optlen -= r; - } - break; case DHCP6_STATE_STOPPED: @@ -508,7 +435,7 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) { if (r < 0) return r; - assert(client->duid_len); + assert (client->duid_len); r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_CLIENTID, client->duid_len, &client->duid); if (r < 0) @@ -750,20 +677,16 @@ error: static int client_ensure_iaid(sd_dhcp6_client *client) { int r; - be32_t iaid; assert(client); - if (client->ia_na.ia_na.id) + if (client->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, &client->ia_na.id); if (r < 0) return r; - client->ia_na.ia_na.id = iaid; - client->ia_pd.ia_pd.id = iaid; - return 0; } @@ -772,33 +695,23 @@ static int client_parse_message( DHCP6Message *message, size_t len, sd_dhcp6_lease *lease) { - size_t pos = 0; int r; + uint8_t *optval, *option, *id = NULL; + uint16_t optcode, status; + size_t optlen, id_len; bool clientid = false; - uint32_t lt_t1 = ~0, lt_t2 = ~0; + be32_t iaid_lease; assert(client); assert(message); assert(len >= sizeof(DHCP6Message)); assert(lease); + option = (uint8_t *)message + sizeof(DHCP6Message); len -= sizeof(DHCP6Message); - while (pos < len) { - DHCP6Option *option = (DHCP6Option *)&message->options[pos]; - uint16_t optcode, optlen; - int status; - uint8_t *optval; - be32_t iaid_lease; - - if (len < offsetof(DHCP6Option, data) || - len < offsetof(DHCP6Option, data) + be16toh(option->len)) - return -ENOBUFS; - - optcode = be16toh(option->code); - optlen = be16toh(option->len); - optval = option->data; - + while ((r = dhcp6_option_parse(&option, &len, &optcode, &optlen, + &optval)) >= 0) { switch (optcode) { case SD_DHCP6_OPTION_CLIENTID: if (clientid) { @@ -819,8 +732,8 @@ static int client_parse_message( break; case SD_DHCP6_OPTION_SERVERID: - r = dhcp6_lease_get_serverid(lease, NULL, NULL); - if (r >= 0) { + r = dhcp6_lease_get_serverid(lease, &id, &id_len); + if (r >= 0 && id) { log_dhcp6_client(client, "%s contains multiple serverids", dhcp6_message_type_to_string(message->type)); return -EINVAL; @@ -836,21 +749,21 @@ static int client_parse_message( if (optlen != 1) return -EINVAL; - r = dhcp6_lease_set_preference(lease, optval[0]); + r = dhcp6_lease_set_preference(lease, *optval); if (r < 0) return r; break; case SD_DHCP6_OPTION_STATUS_CODE: - status = dhcp6_option_parse_status(option); + if (optlen < 2) + return -EINVAL; + + status = optval[0] << 8 | optval[1]; if (status) { log_dhcp6_client(client, "%s Status %s", dhcp6_message_type_to_string(message->type), dhcp6_message_status_to_string(status)); - dhcp6_lease_free_ia(&lease->ia); - dhcp6_lease_free_ia(&lease->pd); - return -EINVAL; } @@ -863,35 +776,8 @@ static int client_parse_message( break; } - r = dhcp6_option_parse_ia(option, &lease->ia); - if (r < 0 && r != -ENOMSG) - return r; - - r = dhcp6_lease_get_iaid(lease, &iaid_lease); - if (r < 0) - return r; - - if (client->ia_na.ia_na.id != iaid_lease) { - log_dhcp6_client(client, "%s has wrong IAID for IA NA", - dhcp6_message_type_to_string(message->type)); - return -EINVAL; - } - - if (lease->ia.addresses) { - lt_t1 = MIN(lt_t1, be32toh(lease->ia.ia_na.lifetime_t1)); - lt_t2 = MIN(lt_t2, be32toh(lease->ia.ia_na.lifetime_t1)); - } - - break; - - case SD_DHCP6_OPTION_IA_PD: - if (client->state == DHCP6_STATE_INFORMATION_REQUEST) { - log_dhcp6_client(client, "Information request ignoring IA PD option"); - - break; - } - - r = dhcp6_option_parse_ia(option, &lease->pd); + r = dhcp6_option_parse_ia(&optval, &optlen, optcode, + &lease->ia); if (r < 0 && r != -ENOMSG) return r; @@ -899,17 +785,12 @@ static int client_parse_message( if (r < 0) return r; - if (client->ia_pd.ia_pd.id != iaid_lease) { - log_dhcp6_client(client, "%s has wrong IAID for IA PD", + if (client->ia_na.id != iaid_lease) { + log_dhcp6_client(client, "%s has wrong IAID", dhcp6_message_type_to_string(message->type)); return -EINVAL; } - if (lease->pd.addresses) { - lt_t1 = MIN(lt_t1, be32toh(lease->pd.ia_pd.lifetime_t1)); - lt_t2 = MIN(lt_t2, be32toh(lease->pd.ia_pd.lifetime_t2)); - } - break; case SD_DHCP6_OPTION_RAPID_COMMIT: @@ -948,36 +829,25 @@ static int client_parse_message( break; } - pos += sizeof(*option) + optlen; } - if (!clientid) { + if (r == -ENOMSG) + r = 0; + + if (r < 0 || !clientid) { log_dhcp6_client(client, "%s has incomplete options", dhcp6_message_type_to_string(message->type)); return -EINVAL; } if (client->state != DHCP6_STATE_INFORMATION_REQUEST) { - r = dhcp6_lease_get_serverid(lease, NULL, NULL); - if (r < 0) { + r = dhcp6_lease_get_serverid(lease, &id, &id_len); + if (r < 0) log_dhcp6_client(client, "%s has no server id", dhcp6_message_type_to_string(message->type)); - return -EINVAL; - } - - } else { - if (lease->ia.addresses) { - lease->ia.ia_na.lifetime_t1 = htobe32(lt_t1); - lease->ia.ia_na.lifetime_t2 = htobe32(lt_t2); - } - - if (lease->pd.addresses) { - lease->pd.ia_pd.lifetime_t1 = htobe32(lt_t1); - lease->pd.ia_pd.lifetime_t2 = htobe32(lt_t2); - } } - return 0; + return r; } static int client_receive_reply(sd_dhcp6_client *client, DHCP6Message *reply, size_t len) { @@ -1133,7 +1003,7 @@ static int client_receive_message( break; } - _fallthrough_; /* for Soliciation Rapid Commit option check */ + /* fall through */ /* for Soliciation Rapid Commit option check */ case DHCP6_STATE_REQUEST: case DHCP6_STATE_RENEW: case DHCP6_STATE_REBIND: @@ -1190,24 +1060,6 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state) { if (r < 0) return r; - if (!client->receive_message) { - r = sd_event_add_io(client->event, &client->receive_message, - client->fd, EPOLLIN, client_receive_message, - client); - if (r < 0) - goto error; - - r = sd_event_source_set_priority(client->receive_message, - client->event_priority); - if (r < 0) - goto error; - - r = sd_event_source_set_description(client->receive_message, - "dhcp6-receive-message"); - if (r < 0) - goto error; - } - switch (state) { case DHCP6_STATE_STOPPED: if (client->state == DHCP6_STATE_INFORMATION_REQUEST) { @@ -1216,7 +1068,7 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state) { return 0; } - _fallthrough_; + /* fall through */ case DHCP6_STATE_SOLICITATION: client->state = DHCP6_STATE_SOLICITATION; @@ -1233,17 +1085,17 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state) { case DHCP6_STATE_BOUND: - if (client->lease->ia.ia_na.lifetime_t1 == 0xffffffff || - client->lease->ia.ia_na.lifetime_t2 == 0xffffffff) { + if (client->lease->ia.lifetime_t1 == 0xffffffff || + client->lease->ia.lifetime_t2 == 0xffffffff) { log_dhcp6_client(client, "Infinite T1 0x%08x or T2 0x%08x", - be32toh(client->lease->ia.ia_na.lifetime_t1), - be32toh(client->lease->ia.ia_na.lifetime_t2)); + be32toh(client->lease->ia.lifetime_t1), + be32toh(client->lease->ia.lifetime_t2)); return 0; } - timeout = client_timeout_compute_random(be32toh(client->lease->ia.ia_na.lifetime_t1) * USEC_PER_SEC); + timeout = client_timeout_compute_random(be32toh(client->lease->ia.lifetime_t1) * USEC_PER_SEC); log_dhcp6_client(client, "T1 expires in %s", format_timespan(time_string, FORMAT_TIMESPAN_MAX, timeout, USEC_PER_SEC)); @@ -1254,18 +1106,18 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state) { 10 * USEC_PER_SEC, client_timeout_t1, client); if (r < 0) - goto error; + return r; r = sd_event_source_set_priority(client->lease->ia.timeout_t1, client->event_priority); if (r < 0) - goto error; + return r; r = sd_event_source_set_description(client->lease->ia.timeout_t1, "dhcp6-t1-timeout"); if (r < 0) - goto error; + return r; - timeout = client_timeout_compute_random(be32toh(client->lease->ia.ia_na.lifetime_t2) * USEC_PER_SEC); + timeout = client_timeout_compute_random(be32toh(client->lease->ia.lifetime_t2) * USEC_PER_SEC); log_dhcp6_client(client, "T2 expires in %s", format_timespan(time_string, FORMAT_TIMESPAN_MAX, timeout, USEC_PER_SEC)); @@ -1276,16 +1128,16 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state) { 10 * USEC_PER_SEC, client_timeout_t2, client); if (r < 0) - goto error; + return r; r = sd_event_source_set_priority(client->lease->ia.timeout_t2, client->event_priority); if (r < 0) - goto error; + return r; r = sd_event_source_set_description(client->lease->ia.timeout_t2, "dhcp6-t2-timeout"); if (r < 0) - goto error; + return r; client->state = state; @@ -1299,22 +1151,18 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state) { clock_boottime_or_monotonic(), 0, 0, client_timeout_resend, client); if (r < 0) - goto error; + return r; r = sd_event_source_set_priority(client->timeout_resend, client->event_priority); if (r < 0) - goto error; + return r; r = sd_event_source_set_description(client->timeout_resend, "dhcp6-resend-timeout"); if (r < 0) - goto error; + return r; return 0; - - error: - client_reset(client); - return r; } int sd_dhcp6_client_stop(sd_dhcp6_client *client) { @@ -1322,8 +1170,6 @@ int sd_dhcp6_client_stop(sd_dhcp6_client *client) { client_stop(client, SD_DHCP6_CLIENT_EVENT_STOP); - client->fd = safe_close(client->fd); - return 0; } @@ -1357,19 +1203,33 @@ int sd_dhcp6_client_start(sd_dhcp6_client *client) { if (r < 0) return r; - if (client->fd < 0) { - r = dhcp6_network_bind_udp_socket(client->ifindex, &client->local_address); - if (r < 0) { - _cleanup_free_ char *p = NULL; - - (void) in_addr_to_string(AF_INET6, (const union in_addr_union*) &client->local_address, &p); - return log_dhcp6_client_errno(client, r, - "Failed to bind to UDP socket at address %s: %m", strna(p)); - } + r = dhcp6_network_bind_udp_socket(client->ifindex, &client->local_address); + if (r < 0) { + _cleanup_free_ char *p = NULL; - client->fd = r; + (void) in_addr_to_string(AF_INET6, (const union in_addr_union*) &client->local_address, &p); + return log_dhcp6_client_errno(client, r, + "Failed to bind to UDP socket at address %s: %m", strna(p)); } + client->fd = r; + + r = sd_event_add_io(client->event, &client->receive_message, + client->fd, EPOLLIN, client_receive_message, + client); + if (r < 0) + goto error; + + r = sd_event_source_set_priority(client->receive_message, + client->event_priority); + if (r < 0) + goto error; + + r = sd_event_source_set_description(client->receive_message, + "dhcp6-receive-message"); + if (r < 0) + goto error; + if (client->information_request) state = DHCP6_STATE_INFORMATION_REQUEST; @@ -1378,6 +1238,10 @@ int sd_dhcp6_client_start(sd_dhcp6_client *client) { "Managed"); return client_start(client, state); + +error: + client_reset(client); + return r; } int sd_dhcp6_client_attach_event(sd_dhcp6_client *client, sd_event *event, int64_t priority) { @@ -1437,12 +1301,9 @@ sd_dhcp6_client *sd_dhcp6_client_unref(sd_dhcp6_client *client) { client_reset(client); - client->fd = safe_close(client->fd); - sd_dhcp6_client_detach_event(client); free(client->req_opts); - free(client->fqdn); return mfree(client); } @@ -1458,7 +1319,6 @@ int sd_dhcp6_client_new(sd_dhcp6_client **ret) { 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->fd = -1; diff --git a/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c b/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c index 00b9fdf0..63a813aa 100644 --- a/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c +++ b/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. @@ -51,7 +50,7 @@ int dhcp6_lease_ia_rebind_expire(const DHCP6IA *ia, uint32_t *expire) { valid = t; } - t = be32toh(ia->ia_na.lifetime_t2); + t = be32toh(ia->lifetime_t2); if (t > valid) return -EINVAL; @@ -97,14 +96,11 @@ int dhcp6_lease_set_serverid(sd_dhcp6_lease *lease, const uint8_t *id, int dhcp6_lease_get_serverid(sd_dhcp6_lease *lease, uint8_t **id, size_t *len) { assert_return(lease, -EINVAL); + assert_return(id, -EINVAL); + assert_return(len, -EINVAL); - if (!lease->serverid) - return -ENOMSG; - - if (id) - *id = lease->serverid; - if (len) - *len = lease->serverid_len; + *id = lease->serverid; + *len = lease->serverid_len; return 0; } @@ -149,7 +145,7 @@ int dhcp6_lease_get_iaid(sd_dhcp6_lease *lease, be32_t *iaid) { assert_return(lease, -EINVAL); assert_return(iaid, -EINVAL); - *iaid = lease->ia.ia_na.id; + *iaid = lease->ia.id; return 0; } @@ -181,37 +177,6 @@ void sd_dhcp6_lease_reset_address_iter(sd_dhcp6_lease *lease) { lease->addr_iter = lease->ia.addresses; } -int sd_dhcp6_lease_get_pd(sd_dhcp6_lease *lease, struct in6_addr *prefix, - uint8_t *prefix_len, - uint32_t *lifetime_preferred, - uint32_t *lifetime_valid) { - assert_return(lease, -EINVAL); - assert_return(prefix, -EINVAL); - assert_return(prefix_len, -EINVAL); - assert_return(lifetime_preferred, -EINVAL); - assert_return(lifetime_valid, -EINVAL); - - if (!lease->prefix_iter) - return -ENOMSG; - - memcpy(prefix, &lease->prefix_iter->iapdprefix.address, - sizeof(struct in6_addr)); - *prefix_len = lease->prefix_iter->iapdprefix.prefixlen; - *lifetime_preferred = - be32toh(lease->prefix_iter->iapdprefix.lifetime_preferred); - *lifetime_valid = - be32toh(lease->prefix_iter->iapdprefix.lifetime_valid); - - lease->prefix_iter = lease->prefix_iter->addresses_next; - - return 0; -} - -void sd_dhcp6_lease_reset_pd_prefix_iter(sd_dhcp6_lease *lease) { - if (lease) - lease->prefix_iter = lease->pd.addresses; -} - int dhcp6_lease_set_dns(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen) { int r; @@ -418,7 +383,6 @@ sd_dhcp6_lease *sd_dhcp6_lease_unref(sd_dhcp6_lease *lease) { free(lease->serverid); dhcp6_lease_free_ia(&lease->ia); - dhcp6_lease_free_ia(&lease->pd); free(lease->dns); diff --git a/src/systemd/src/libsystemd-network/sd-ipv4acd.c b/src/systemd/src/libsystemd-network/sd-ipv4acd.c index 08f46dd2..694384b5 100644 --- a/src/systemd/src/libsystemd-network/sd-ipv4acd.c +++ b/src/systemd/src/libsystemd-network/sd-ipv4acd.c @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. @@ -290,7 +289,8 @@ static int ipv4acd_on_timeout(sd_event_source *s, uint64_t usec, void *userdata) break; } - _fallthrough_; + /* fall through */ + case IPV4ACD_STATE_WAITING_ANNOUNCE: /* Send announcement packet */ r = arp_send_announcement(acd->fd, acd->ifindex, acd->address, &acd->mac_addr); diff --git a/src/systemd/src/libsystemd-network/sd-ipv4ll.c b/src/systemd/src/libsystemd-network/sd-ipv4ll.c index f1e7b404..47fc141c 100644 --- a/src/systemd/src/libsystemd-network/sd-ipv4ll.c +++ b/src/systemd/src/libsystemd-network/sd-ipv4ll.c @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. @@ -27,7 +26,6 @@ #include <stdlib.h> #include <string.h> -#include "sd-id128.h" #include "sd-ipv4acd.h" #include "sd-ipv4ll.h" diff --git a/src/systemd/src/libsystemd-network/sd-lldp.c b/src/systemd/src/libsystemd-network/sd-lldp.c index 20956041..31e24486 100644 --- a/src/systemd/src/libsystemd-network/sd-lldp.c +++ b/src/systemd/src/libsystemd-network/sd-lldp.c @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. diff --git a/src/systemd/src/libsystemd/sd-event/sd-event.c b/src/systemd/src/libsystemd/sd-event/sd-event.c index 4fb8ed7f..9dfe6847 100644 --- a/src/systemd/src/libsystemd/sd-event/sd-event.c +++ b/src/systemd/src/libsystemd/sd-event/sd-event.c @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. @@ -124,7 +123,6 @@ struct sd_event_source { uint32_t events; uint32_t revents; bool registered:1; - bool owned:1; } io; struct { sd_event_time_handler_t callback; @@ -243,14 +241,8 @@ struct sd_event { unsigned delays[sizeof(usec_t) * 8]; }; -static thread_local sd_event *default_event = NULL; - static void source_disconnect(sd_event_source *s); -static sd_event *event_resolve(sd_event *e) { - return e == SD_EVENT_DEFAULT ? default_event : e; -} - static int pending_prioq_compare(const void *a, const void *b) { const sd_event_source *x = a, *y = b; @@ -459,8 +451,6 @@ _public_ int sd_event_new(sd_event** ret) { goto fail; } - e->epoll_fd = fd_move_above_stdio(e->epoll_fd); - if (secure_getenv("SD_EVENT_PROFILE_DELAYS")) { log_debug("Event loop profiling enabled. Logarithmic histogram of event loop iterations in the range 2^0 ... 2^63 us will be logged every 5s."); e->profile_delays = true; @@ -699,7 +689,7 @@ static int event_make_signal_data( return 0; } - d->fd = fd_move_above_stdio(r); + d->fd = r; ev.events = EPOLLIN; ev.data.ptr = d; @@ -894,10 +884,6 @@ static void source_free(sd_event_source *s) { assert(s); source_disconnect(s); - - if (s->type == SOURCE_IO && s->io.owned) - safe_close(s->io.fd); - free(s->description); free(s); } @@ -982,7 +968,6 @@ _public_ int sd_event_add_io( int r; assert_return(e, -EINVAL); - assert_return(e = event_resolve(e), -ENOPKG); assert_return(fd >= 0, -EBADF); assert_return(!(events & ~(EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLPRI|EPOLLERR|EPOLLHUP|EPOLLET)), -EINVAL); assert_return(callback, -EINVAL); @@ -1049,8 +1034,6 @@ static int event_setup_timer_fd( if (fd < 0) return -errno; - fd = fd_move_above_stdio(fd); - ev.events = EPOLLIN; ev.data.ptr = d; @@ -1085,7 +1068,6 @@ _public_ int sd_event_add_time( int r; assert_return(e, -EINVAL); - assert_return(e = event_resolve(e), -ENOPKG); assert_return(accuracy != (uint64_t) -1, -EINVAL); assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); assert_return(!event_pid_changed(e), -ECHILD); @@ -1168,7 +1150,6 @@ _public_ int sd_event_add_signal( int r; assert_return(e, -EINVAL); - assert_return(e = event_resolve(e), -ENOPKG); assert_return(SIGNAL_VALID(sig), -EINVAL); assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); assert_return(!event_pid_changed(e), -ECHILD); @@ -1229,7 +1210,6 @@ _public_ int sd_event_add_child( int r; assert_return(e, -EINVAL); - assert_return(e = event_resolve(e), -ENOPKG); assert_return(pid > 1, -EINVAL); assert_return(!(options & ~(WEXITED|WSTOPPED|WCONTINUED)), -EINVAL); assert_return(options != 0, -EINVAL); @@ -1287,7 +1267,6 @@ _public_ int sd_event_add_defer( int r; assert_return(e, -EINVAL); - assert_return(e = event_resolve(e), -ENOPKG); assert_return(callback, -EINVAL); assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); assert_return(!event_pid_changed(e), -ECHILD); @@ -1322,7 +1301,6 @@ _public_ int sd_event_add_post( int r; assert_return(e, -EINVAL); - assert_return(e = event_resolve(e), -ENOPKG); assert_return(callback, -EINVAL); assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); assert_return(!event_pid_changed(e), -ECHILD); @@ -1361,7 +1339,6 @@ _public_ int sd_event_add_exit( int r; assert_return(e, -EINVAL); - assert_return(e = event_resolve(e), -ENOPKG); assert_return(callback, -EINVAL); assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); assert_return(!event_pid_changed(e), -ECHILD); @@ -1507,21 +1484,6 @@ _public_ int sd_event_source_set_io_fd(sd_event_source *s, int fd) { return 0; } -_public_ int sd_event_source_get_io_fd_own(sd_event_source *s) { - assert_return(s, -EINVAL); - assert_return(s->type == SOURCE_IO, -EDOM); - - return s->io.owned; -} - -_public_ int sd_event_source_set_io_fd_own(sd_event_source *s, int own) { - assert_return(s, -EINVAL); - assert_return(s->type == SOURCE_IO, -EDOM); - - s->io.owned = own; - return 0; -} - _public_ int sd_event_source_get_io_events(sd_event_source *s, uint32_t* events) { assert_return(s, -EINVAL); assert_return(events, -EINVAL); @@ -2490,7 +2452,6 @@ _public_ int sd_event_prepare(sd_event *e) { int r; assert_return(e, -EINVAL); - assert_return(e = event_resolve(e), -ENOPKG); assert_return(!event_pid_changed(e), -ECHILD); assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); assert_return(e->state == SD_EVENT_INITIAL, -EBUSY); @@ -2548,7 +2509,6 @@ _public_ int sd_event_wait(sd_event *e, uint64_t timeout) { int r, m, i; assert_return(e, -EINVAL); - assert_return(e = event_resolve(e), -ENOPKG); assert_return(!event_pid_changed(e), -ECHILD); assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); assert_return(e->state == SD_EVENT_ARMED, -EBUSY); @@ -2655,7 +2615,6 @@ _public_ int sd_event_dispatch(sd_event *e) { int r; assert_return(e, -EINVAL); - assert_return(e = event_resolve(e), -ENOPKG); assert_return(!event_pid_changed(e), -ECHILD); assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); assert_return(e->state == SD_EVENT_PENDING, -EBUSY); @@ -2697,7 +2656,6 @@ _public_ int sd_event_run(sd_event *e, uint64_t timeout) { int r; assert_return(e, -EINVAL); - assert_return(e = event_resolve(e), -ENOPKG); assert_return(!event_pid_changed(e), -ECHILD); assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); assert_return(e->state == SD_EVENT_INITIAL, -EBUSY); @@ -2742,7 +2700,6 @@ _public_ int sd_event_loop(sd_event *e) { int r; assert_return(e, -EINVAL); - assert_return(e = event_resolve(e), -ENOPKG); assert_return(!event_pid_changed(e), -ECHILD); assert_return(e->state == SD_EVENT_INITIAL, -EBUSY); @@ -2764,7 +2721,6 @@ finish: _public_ int sd_event_get_fd(sd_event *e) { assert_return(e, -EINVAL); - assert_return(e = event_resolve(e), -ENOPKG); assert_return(!event_pid_changed(e), -ECHILD); return e->epoll_fd; @@ -2772,7 +2728,6 @@ _public_ int sd_event_get_fd(sd_event *e) { _public_ int sd_event_get_state(sd_event *e) { assert_return(e, -EINVAL); - assert_return(e = event_resolve(e), -ENOPKG); assert_return(!event_pid_changed(e), -ECHILD); return e->state; @@ -2780,7 +2735,6 @@ _public_ int sd_event_get_state(sd_event *e) { _public_ int sd_event_get_exit_code(sd_event *e, int *code) { assert_return(e, -EINVAL); - assert_return(e = event_resolve(e), -ENOPKG); assert_return(code, -EINVAL); assert_return(!event_pid_changed(e), -ECHILD); @@ -2793,7 +2747,6 @@ _public_ int sd_event_get_exit_code(sd_event *e, int *code) { _public_ int sd_event_exit(sd_event *e, int code) { assert_return(e, -EINVAL); - assert_return(e = event_resolve(e), -ENOPKG); assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); assert_return(!event_pid_changed(e), -ECHILD); @@ -2805,7 +2758,6 @@ _public_ int sd_event_exit(sd_event *e, int code) { _public_ int sd_event_now(sd_event *e, clockid_t clock, uint64_t *usec) { assert_return(e, -EINVAL); - assert_return(e = event_resolve(e), -ENOPKG); assert_return(usec, -EINVAL); assert_return(!event_pid_changed(e), -ECHILD); @@ -2830,6 +2782,8 @@ _public_ int sd_event_now(sd_event *e, clockid_t clock, uint64_t *usec) { } _public_ int sd_event_default(sd_event **ret) { + + static thread_local sd_event *default_event = NULL; sd_event *e = NULL; int r; @@ -2856,7 +2810,6 @@ _public_ int sd_event_default(sd_event **ret) { #if 0 /* NM_IGNORED */ _public_ int sd_event_get_tid(sd_event *e, pid_t *tid) { assert_return(e, -EINVAL); - assert_return(e = event_resolve(e), -ENOPKG); assert_return(tid, -EINVAL); assert_return(!event_pid_changed(e), -ECHILD); @@ -2872,7 +2825,6 @@ _public_ int sd_event_set_watchdog(sd_event *e, int b) { int r; assert_return(e, -EINVAL); - assert_return(e = event_resolve(e), -ENOPKG); assert_return(!event_pid_changed(e), -ECHILD); if (e->watchdog == !!b) @@ -2923,7 +2875,6 @@ fail: _public_ int sd_event_get_watchdog(sd_event *e) { assert_return(e, -EINVAL); - assert_return(e = event_resolve(e), -ENOPKG); assert_return(!event_pid_changed(e), -ECHILD); return e->watchdog; @@ -2931,7 +2882,6 @@ _public_ int sd_event_get_watchdog(sd_event *e) { _public_ int sd_event_get_iteration(sd_event *e, uint64_t *ret) { assert_return(e, -EINVAL); - assert_return(e = event_resolve(e), -ENOPKG); assert_return(!event_pid_changed(e), -ECHILD); *ret = e->iteration; diff --git a/src/systemd/src/libsystemd/sd-id128/id128-util.c b/src/systemd/src/libsystemd/sd-id128/id128-util.c index f1033346..19277021 100644 --- a/src/systemd/src/libsystemd/sd-id128/id128-util.c +++ b/src/systemd/src/libsystemd/sd-id128/id128-util.c @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. @@ -20,12 +19,10 @@ #include "nm-sd-adapt.h" -#include <errno.h> #include <fcntl.h> #include <unistd.h> #include "fd-util.h" -#include "fs-util.h" #include "hexdecoct.h" #include "id128-util.h" #include "io-util.h" @@ -123,7 +120,7 @@ int id128_read_fd(int fd, Id128Format f, sd_id128_t *ret) { if (buffer[32] != '\n') return -EINVAL; - _fallthrough_; + /* fall through */ case 32: /* plain UUID without trailing newline */ if (f == ID128_UUID) return -EINVAL; @@ -135,7 +132,7 @@ int id128_read_fd(int fd, Id128Format f, sd_id128_t *ret) { if (buffer[36] != '\n') return -EINVAL; - _fallthrough_; + /* fall through */ case 36: /* RFC UUID without trailing newline */ if (f == ID128_PLAIN) return -EINVAL; @@ -186,13 +183,9 @@ int id128_write_fd(int fd, Id128Format f, sd_id128_t id, bool do_sync) { if (do_sync) { if (fsync(fd) < 0) return -errno; - - r = fsync_directory_of_file(fd); - if (r < 0) - return r; } - return 0; + return r; } int id128_write(const char *p, Id128Format f, sd_id128_t id, bool do_sync) { diff --git a/src/systemd/src/libsystemd/sd-id128/id128-util.h b/src/systemd/src/libsystemd/sd-id128/id128-util.h index 9f3340e5..6b3855ac 100644 --- a/src/systemd/src/libsystemd/sd-id128/id128-util.h +++ b/src/systemd/src/libsystemd/sd-id128/id128-util.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once /*** diff --git a/src/systemd/src/libsystemd/sd-id128/sd-id128.c b/src/systemd/src/libsystemd/sd-id128/sd-id128.c index e5bd447a..052110d5 100644 --- a/src/systemd/src/libsystemd/sd-id128/sd-id128.c +++ b/src/systemd/src/libsystemd/sd-id128/sd-id128.c @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. diff --git a/src/systemd/src/shared/dns-domain.c b/src/systemd/src/shared/dns-domain.c index cfc1f3b3..c313a033 100644 --- a/src/systemd/src/shared/dns-domain.c +++ b/src/systemd/src/shared/dns-domain.c @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. @@ -302,7 +301,8 @@ int dns_label_escape_new(const char *p, size_t l, char **ret) { if (r < 0) return r; - *ret = TAKE_PTR(s); + *ret = s; + s = NULL; return r; } @@ -609,7 +609,8 @@ int dns_name_endswith(const char *name, const char *suffix) { /* Not the same, let's jump back, and try with the next label again */ s = suffix; - n = TAKE_PTR(saved_n); + n = saved_n; + saved_n = NULL; } } } @@ -700,26 +701,23 @@ int dns_name_change_suffix(const char *name, const char *old_suffix, const char } int dns_name_between(const char *a, const char *b, const char *c) { + int n; + /* Determine if b is strictly greater than a and strictly smaller than c. We consider the order of names to be circular, so that if a is strictly greater than c, we consider b to be between them if it is either greater than a or smaller than c. This is how the canonical DNS name order used in NSEC records work. */ - if (dns_name_compare_func(a, c) < 0) - /* - a and c are properly ordered: - a<---b--->c - */ + n = dns_name_compare_func(a, c); + if (n == 0) + return -EINVAL; + else if (n < 0) + /* a<---b--->c */ return dns_name_compare_func(a, b) < 0 && dns_name_compare_func(b, c) < 0; else - /* - a and c are equal or 'reversed': - <--b--c a-----> - or: - <-----c a--b--> - */ + /* <--b--c a--b--> */ return dns_name_compare_func(b, c) < 0 || dns_name_compare_func(a, b) < 0; } @@ -971,12 +969,6 @@ bool dns_srv_type_is_valid(const char *name) { return c == 2; /* exactly two labels */ } -bool dnssd_srv_type_is_valid(const char *name) { - return dns_srv_type_is_valid(name) && - ((dns_name_endswith(name, "_tcp") > 0) || - (dns_name_endswith(name, "_udp") > 0)); /* Specific to DNS-SD. RFC 6763, Section 7 */ -} - bool dns_service_name_is_valid(const char *name) { size_t l; diff --git a/src/systemd/src/shared/dns-domain.h b/src/systemd/src/shared/dns-domain.h index 3ebd4018..d1a99be7 100644 --- a/src/systemd/src/shared/dns-domain.h +++ b/src/systemd/src/shared/dns-domain.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once /*** @@ -98,7 +97,6 @@ bool dns_name_is_single_label(const char *name); int dns_name_to_wire_format(const char *domain, uint8_t *buffer, size_t len, bool canonical); bool dns_srv_type_is_valid(const char *name); -bool dnssd_srv_type_is_valid(const char *name); bool dns_service_name_is_valid(const char *name); int dns_service_join(const char *name, const char *type, const char *domain, char **ret); diff --git a/src/systemd/src/systemd/_sd-common.h b/src/systemd/src/systemd/_sd-common.h index b4400e7b..97c39438 100644 --- a/src/systemd/src/systemd/_sd-common.h +++ b/src/systemd/src/systemd/_sd-common.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #ifndef foosdcommonhfoo #define foosdcommonhfoo diff --git a/src/systemd/src/systemd/sd-dhcp-client.h b/src/systemd/src/systemd/sd-dhcp-client.h index 789cc501..5e46d8d0 100644 --- a/src/systemd/src/systemd/sd-dhcp-client.h +++ b/src/systemd/src/systemd/sd-dhcp-client.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #ifndef foosddhcpclienthfoo #define foosddhcpclienthfoo @@ -132,11 +131,6 @@ int sd_dhcp_client_set_iaid_duid( uint16_t duid_type, const void *duid, size_t duid_len); -int sd_dhcp_client_set_duid( - sd_dhcp_client *client, - uint16_t duid_type, - const void *duid, - size_t duid_len); int sd_dhcp_client_get_client_id( sd_dhcp_client *client, uint8_t *type, diff --git a/src/systemd/src/systemd/sd-dhcp-lease.h b/src/systemd/src/systemd/sd-dhcp-lease.h index 3cc7fcab..7ab99ccc 100644 --- a/src/systemd/src/systemd/sd-dhcp-lease.h +++ b/src/systemd/src/systemd/sd-dhcp-lease.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #ifndef foosddhcpleasehfoo #define foosddhcpleasehfoo diff --git a/src/systemd/src/systemd/sd-dhcp6-client.h b/src/systemd/src/systemd/sd-dhcp6-client.h index cadb32a0..7819f0d2 100644 --- a/src/systemd/src/systemd/sd-dhcp6-client.h +++ b/src/systemd/src/systemd/sd-dhcp6-client.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #ifndef foosddhcp6clienthfoo #define foosddhcp6clienthfoo @@ -23,7 +22,6 @@ #include <inttypes.h> #include <net/ethernet.h> -#include <stdbool.h> #include <sys/types.h> #include "sd-dhcp6-lease.h" @@ -65,15 +63,11 @@ enum { SD_DHCP6_OPTION_DNS_SERVERS = 23, /* RFC 3646 */ SD_DHCP6_OPTION_DOMAIN_LIST = 24, /* RFC 3646 */ - SD_DHCP6_OPTION_IA_PD = 25, /* RFC 3633, prefix delegation */ - SD_DHCP6_OPTION_IA_PD_PREFIX = 26, /* RFC 3633, prefix delegation */ SD_DHCP6_OPTION_SNTP_SERVERS = 31, /* RFC 4075, deprecated */ /* option code 35 is unassigned */ - SD_DHCP6_OPTION_FQDN = 39, /* RFC 4704 */ - SD_DHCP6_OPTION_NTP_SERVER = 56, /* RFC 5908 */ /* option codes 89-142 are unassigned */ @@ -107,9 +101,6 @@ int sd_dhcp6_client_set_duid( int sd_dhcp6_client_set_iaid( sd_dhcp6_client *client, uint32_t iaid); -int sd_dhcp6_client_set_fqdn( - sd_dhcp6_client *client, - const char *fqdn); int sd_dhcp6_client_set_information_request( sd_dhcp6_client *client, int enabled); @@ -119,8 +110,6 @@ int sd_dhcp6_client_get_information_request( int sd_dhcp6_client_set_request_option( sd_dhcp6_client *client, uint16_t option); -int sd_dhcp6_client_set_prefix_delegation(sd_dhcp6_client *client, - bool delegation); int sd_dhcp6_client_get_lease( sd_dhcp6_client *client, diff --git a/src/systemd/src/systemd/sd-dhcp6-lease.h b/src/systemd/src/systemd/sd-dhcp6-lease.h index 22a5f8ce..184fbb8e 100644 --- a/src/systemd/src/systemd/sd-dhcp6-lease.h +++ b/src/systemd/src/systemd/sd-dhcp6-lease.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #ifndef foosddhcp6leasehfoo #define foosddhcp6leasehfoo @@ -36,11 +35,6 @@ int sd_dhcp6_lease_get_address(sd_dhcp6_lease *lease, struct in6_addr *addr, uint32_t *lifetime_preferred, uint32_t *lifetime_valid); -void sd_dhcp6_lease_reset_pd_prefix_iter(sd_dhcp6_lease *lease); -int sd_dhcp6_lease_get_pd(sd_dhcp6_lease *lease, struct in6_addr *prefix, - uint8_t *prefix_len, - uint32_t *lifetime_preferred, - uint32_t *lifetime_valid); int sd_dhcp6_lease_get_dns(sd_dhcp6_lease *lease, struct in6_addr **addrs); int sd_dhcp6_lease_get_domains(sd_dhcp6_lease *lease, char ***domains); diff --git a/src/systemd/src/systemd/sd-event.h b/src/systemd/src/systemd/sd-event.h index ec4b7bcf..f8cb8956 100644 --- a/src/systemd/src/systemd/sd-event.h +++ b/src/systemd/src/systemd/sd-event.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #ifndef foosdeventhfoo #define foosdeventhfoo @@ -26,7 +25,6 @@ #include <sys/epoll.h> #include <sys/signalfd.h> #include <sys/types.h> -#include <time.h> #include "_sd-common.h" @@ -41,8 +39,6 @@ _SD_BEGIN_DECLARATIONS; -#define SD_EVENT_DEFAULT ((sd_event *) 1) - typedef struct sd_event sd_event; typedef struct sd_event_source sd_event_source; @@ -127,8 +123,6 @@ int sd_event_source_get_enabled(sd_event_source *s, int *enabled); int sd_event_source_set_enabled(sd_event_source *s, int enabled); int sd_event_source_get_io_fd(sd_event_source *s); int sd_event_source_set_io_fd(sd_event_source *s, int fd); -int sd_event_source_get_io_fd_own(sd_event_source *s); -int sd_event_source_set_io_fd_own(sd_event_source *s, int own); int sd_event_source_get_io_events(sd_event_source *s, uint32_t* events); int sd_event_source_set_io_events(sd_event_source *s, uint32_t events); int sd_event_source_get_io_revents(sd_event_source *s, uint32_t* revents); diff --git a/src/systemd/src/systemd/sd-id128.h b/src/systemd/src/systemd/sd-id128.h index 67fc5956..9b38969b 100644 --- a/src/systemd/src/systemd/sd-id128.h +++ b/src/systemd/src/systemd/sd-id128.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #ifndef foosdid128hfoo #define foosdid128hfoo diff --git a/src/systemd/src/systemd/sd-ipv4acd.h b/src/systemd/src/systemd/sd-ipv4acd.h index 677ae3b2..16d99983 100644 --- a/src/systemd/src/systemd/sd-ipv4acd.h +++ b/src/systemd/src/systemd/sd-ipv4acd.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #ifndef foosdipv4acdfoo #define foosdipv4acdfoo diff --git a/src/systemd/src/systemd/sd-ipv4ll.h b/src/systemd/src/systemd/sd-ipv4ll.h index c330b0ae..5ba92083 100644 --- a/src/systemd/src/systemd/sd-ipv4ll.h +++ b/src/systemd/src/systemd/sd-ipv4ll.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #ifndef foosdipv4llfoo #define foosdipv4llfoo diff --git a/src/systemd/src/systemd/sd-lldp.h b/src/systemd/src/systemd/sd-lldp.h index 0a76fa63..3f35eebe 100644 --- a/src/systemd/src/systemd/sd-lldp.h +++ b/src/systemd/src/systemd/sd-lldp.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #ifndef foosdlldphfoo #define foosdlldphfoo diff --git a/src/systemd/src/systemd/sd-ndisc.h b/src/systemd/src/systemd/sd-ndisc.h index 15211450..9f7d4ef7 100644 --- a/src/systemd/src/systemd/sd-ndisc.h +++ b/src/systemd/src/systemd/sd-ndisc.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #ifndef foosdndiscfoo #define foosdndiscfoo |