From cd87004dfbe6947a03f1aa7248c01fc9351c4bbd Mon Sep 17 00:00:00 2001 From: Fernando Fernandez Mancera Date: Mon, 19 Jun 2023 22:26:12 -0400 Subject: systemd: update code from upstream (2024-04-19) This is a direct dump from systemd git. $ git clean -fdx && \ git cat-file -p HEAD | sed '1,/^======$/ d' | bash - && \ git add . ====== SYSTEMD_DIR=../systemd COMMIT=fa6ea8095855696cf14cb65214020cdcdee79d6b ( cd "$SYSTEMD_DIR" git checkout "$COMMIT" git reset --hard git clean -fdx ) git ls-files -z :/src/libnm-systemd-core/src/ \ :/src/libnm-systemd-shared/src/ \ :/src/libnm-std-aux/unaligned-fundamental.h \ :/src/libnm-std-aux/unaligned.h | \ xargs -0 rm -f nm_copy_sd_shared() { mkdir -p "./src/libnm-systemd-shared/$(dirname "$1")" cp "$SYSTEMD_DIR/$1" "./src/libnm-systemd-shared/$1" } nm_copy_sd_core() { mkdir -p "./src/libnm-systemd-core/$(dirname "$1")" cp "$SYSTEMD_DIR/$1" "./src/libnm-systemd-core/$1" } nm_copy_sd_stdaux() { mkdir -p "./src/libnm-std-aux/" cp "$SYSTEMD_DIR/$1" "./src/libnm-std-aux/${1##*/}" } nm_copy_sd_core "src/libsystemd-network/dhcp-duid-internal.h" nm_copy_sd_core "src/libsystemd-network/dhcp6-client-internal.h" nm_copy_sd_core "src/libsystemd-network/dhcp6-internal.h" nm_copy_sd_core "src/libsystemd-network/dhcp6-lease-internal.h" nm_copy_sd_core "src/libsystemd-network/dhcp6-network.c" nm_copy_sd_core "src/libsystemd-network/dhcp6-option.c" nm_copy_sd_core "src/libsystemd-network/dhcp6-option.h" nm_copy_sd_core "src/libsystemd-network/dhcp6-protocol.c" nm_copy_sd_core "src/libsystemd-network/dhcp6-protocol.h" nm_copy_sd_core "src/libsystemd-network/network-common.c" nm_copy_sd_core "src/libsystemd-network/network-common.h" nm_copy_sd_core "src/libsystemd-network/network-internal.h" nm_copy_sd_core "src/libsystemd-network/sd-dhcp-duid.c" nm_copy_sd_core "src/libsystemd-network/sd-dhcp6-client.c" nm_copy_sd_core "src/libsystemd-network/sd-dhcp6-lease.c" nm_copy_sd_core "src/libsystemd/sd-device/device-internal.h" nm_copy_sd_core "src/libsystemd/sd-device/device-private.c" nm_copy_sd_core "src/libsystemd/sd-device/device-private.h" nm_copy_sd_core "src/libsystemd/sd-device/device-util.h" nm_copy_sd_core "src/libsystemd/sd-device/sd-device.c" nm_copy_sd_core "src/libsystemd/sd-event/event-source.h" nm_copy_sd_core "src/libsystemd/sd-event/event-util.c" nm_copy_sd_core "src/libsystemd/sd-event/event-util.h" nm_copy_sd_core "src/libsystemd/sd-event/sd-event.c" nm_copy_sd_core "src/libsystemd/sd-id128/id128-util.c" nm_copy_sd_core "src/libsystemd/sd-id128/id128-util.h" nm_copy_sd_core "src/libsystemd/sd-id128/sd-id128.c" nm_copy_sd_core "src/systemd/_sd-common.h" nm_copy_sd_core "src/systemd/sd-device.h" nm_copy_sd_core "src/systemd/sd-dhcp-duid.h" nm_copy_sd_core "src/systemd/sd-dhcp6-client.h" nm_copy_sd_core "src/systemd/sd-dhcp6-lease.h" nm_copy_sd_core "src/systemd/sd-dhcp6-option.h" nm_copy_sd_core "src/systemd/sd-dhcp6-protocol.h" nm_copy_sd_core "src/systemd/sd-event.h" nm_copy_sd_core "src/systemd/sd-id128.h" nm_copy_sd_core "src/systemd/sd-ndisc.h" nm_copy_sd_shared "src/basic/alloc-util.c" nm_copy_sd_shared "src/basic/alloc-util.h" nm_copy_sd_shared "src/basic/arphrd-util.h" nm_copy_sd_shared "src/basic/btrfs.c" nm_copy_sd_shared "src/basic/btrfs.h" nm_copy_sd_shared "src/basic/cgroup-util.h" nm_copy_sd_shared "src/basic/chase.h" nm_copy_sd_shared "src/basic/constants.h" nm_copy_sd_shared "src/basic/devnum-util.c" nm_copy_sd_shared "src/basic/devnum-util.h" nm_copy_sd_shared "src/basic/dns-def.h" nm_copy_sd_shared "src/basic/env-file.c" nm_copy_sd_shared "src/basic/env-file.h" nm_copy_sd_shared "src/basic/env-util.c" nm_copy_sd_shared "src/basic/env-util.h" nm_copy_sd_shared "src/basic/errno-util.h" nm_copy_sd_shared "src/basic/escape.c" nm_copy_sd_shared "src/basic/escape.h" nm_copy_sd_shared "src/basic/ether-addr-util.c" nm_copy_sd_shared "src/basic/ether-addr-util.h" nm_copy_sd_shared "src/basic/extract-word.c" nm_copy_sd_shared "src/basic/extract-word.h" nm_copy_sd_shared "src/basic/fd-util.c" nm_copy_sd_shared "src/basic/fd-util.h" nm_copy_sd_shared "src/basic/fileio.c" nm_copy_sd_shared "src/basic/fileio.h" nm_copy_sd_shared "src/basic/format-util.c" nm_copy_sd_shared "src/basic/format-util.h" nm_copy_sd_shared "src/basic/fs-util.c" nm_copy_sd_shared "src/basic/fs-util.h" nm_copy_sd_shared "src/basic/glyph-util.c" nm_copy_sd_shared "src/basic/glyph-util.h" nm_copy_sd_shared "src/basic/hash-funcs.c" nm_copy_sd_shared "src/basic/hash-funcs.h" nm_copy_sd_shared "src/basic/hashmap.c" nm_copy_sd_shared "src/basic/hashmap.h" nm_copy_sd_shared "src/basic/hexdecoct.c" nm_copy_sd_shared "src/basic/hexdecoct.h" nm_copy_sd_shared "src/basic/hostname-util.c" nm_copy_sd_shared "src/basic/hostname-util.h" nm_copy_sd_shared "src/basic/in-addr-util.c" nm_copy_sd_shared "src/basic/in-addr-util.h" nm_copy_sd_shared "src/basic/inotify-util.c" nm_copy_sd_shared "src/basic/inotify-util.h" nm_copy_sd_shared "src/basic/io-util.c" nm_copy_sd_shared "src/basic/io-util.h" nm_copy_sd_shared "src/basic/iovec-util.h" nm_copy_sd_shared "src/basic/label.c" nm_copy_sd_shared "src/basic/label.h" nm_copy_sd_shared "src/basic/list.h" nm_copy_sd_shared "src/basic/locale-util.c" nm_copy_sd_shared "src/basic/locale-util.h" nm_copy_sd_shared "src/basic/lock-util.h" nm_copy_sd_shared "src/basic/log.h" nm_copy_sd_shared "src/basic/macro.h" nm_copy_sd_shared "src/basic/memory-util.c" nm_copy_sd_shared "src/basic/memory-util.h" nm_copy_sd_shared "src/basic/mempool.c" nm_copy_sd_shared "src/basic/mempool.h" nm_copy_sd_shared "src/basic/missing_fcntl.h" nm_copy_sd_shared "src/basic/missing_random.h" nm_copy_sd_shared "src/basic/missing_socket.h" nm_copy_sd_shared "src/basic/missing_stat.h" nm_copy_sd_shared "src/basic/missing_syscall.h" nm_copy_sd_shared "src/basic/missing_threads.h" nm_copy_sd_shared "src/basic/missing_type.h" nm_copy_sd_shared "src/basic/namespace-util.h" nm_copy_sd_shared "src/basic/ordered-set.c" nm_copy_sd_shared "src/basic/ordered-set.h" nm_copy_sd_shared "src/basic/origin-id.h" nm_copy_sd_shared "src/basic/parse-util.c" nm_copy_sd_shared "src/basic/parse-util.h" nm_copy_sd_shared "src/basic/path-util.c" nm_copy_sd_shared "src/basic/path-util.h" nm_copy_sd_shared "src/basic/pidref.h" nm_copy_sd_shared "src/basic/prioq.c" nm_copy_sd_shared "src/basic/prioq.h" nm_copy_sd_shared "src/basic/process-util.c" nm_copy_sd_shared "src/basic/process-util.h" nm_copy_sd_shared "src/basic/random-util.c" nm_copy_sd_shared "src/basic/random-util.h" nm_copy_sd_shared "src/basic/ratelimit.c" nm_copy_sd_shared "src/basic/ratelimit.h" nm_copy_sd_shared "src/basic/set.h" nm_copy_sd_shared "src/basic/signal-util.c" nm_copy_sd_shared "src/basic/signal-util.h" nm_copy_sd_shared "src/basic/siphash24.h" nm_copy_sd_shared "src/basic/socket-util.c" nm_copy_sd_shared "src/basic/socket-util.h" nm_copy_sd_shared "src/basic/sort-util.h" nm_copy_sd_shared "src/basic/sparse-endian.h" nm_copy_sd_shared "src/basic/stat-util.c" nm_copy_sd_shared "src/basic/stat-util.h" nm_copy_sd_shared "src/basic/stdio-util.h" nm_copy_sd_shared "src/basic/string-table.c" nm_copy_sd_shared "src/basic/string-table.h" nm_copy_sd_shared "src/basic/string-util.c" nm_copy_sd_shared "src/basic/string-util.h" nm_copy_sd_shared "src/basic/strv.c" nm_copy_sd_shared "src/basic/strv.h" nm_copy_sd_shared "src/basic/strxcpyx.c" nm_copy_sd_shared "src/basic/strxcpyx.h" nm_copy_sd_shared "src/basic/time-util.c" nm_copy_sd_shared "src/basic/time-util.h" nm_copy_sd_shared "src/basic/tmpfile-util.c" nm_copy_sd_shared "src/basic/tmpfile-util.h" nm_copy_sd_shared "src/basic/umask-util.h" nm_copy_sd_shared "src/basic/user-util.h" nm_copy_sd_shared "src/basic/utf8.c" nm_copy_sd_shared "src/basic/utf8.h" nm_copy_sd_shared "src/fundamental/logarithm.h" nm_copy_sd_shared "src/fundamental/macro-fundamental.h" nm_copy_sd_shared "src/fundamental/memory-util-fundamental.h" nm_copy_sd_shared "src/fundamental/sha256.c" nm_copy_sd_shared "src/fundamental/sha256.h" nm_copy_sd_shared "src/fundamental/string-util-fundamental.c" nm_copy_sd_shared "src/fundamental/string-util-fundamental.h" nm_copy_sd_shared "src/shared/dns-domain.c" nm_copy_sd_shared "src/shared/dns-domain.h" nm_copy_sd_shared "src/shared/log-link.h" nm_copy_sd_shared "src/shared/web-util.c" nm_copy_sd_shared "src/shared/web-util.h" nm_copy_sd_stdaux "src/basic/unaligned.h" nm_copy_sd_stdaux "src/fundamental/unaligned-fundamental.h" --- .../src/libsystemd/sd-device/sd-device.c | 8 +- .../src/libsystemd/sd-event/sd-event.c | 6 +- .../src/libsystemd/sd-id128/id128-util.c | 4 +- src/libnm-systemd-core/src/systemd/sd-dhcp-duid.h | 1 - src/libnm-systemd-core/src/systemd/sd-ndisc.h | 91 +------ src/libnm-systemd-shared/src/basic/env-util.c | 32 ++- src/libnm-systemd-shared/src/basic/env-util.h | 10 +- src/libnm-systemd-shared/src/basic/extract-word.c | 35 +-- src/libnm-systemd-shared/src/basic/extract-word.h | 5 +- src/libnm-systemd-shared/src/basic/fd-util.c | 83 +++++- src/libnm-systemd-shared/src/basic/fd-util.h | 6 + src/libnm-systemd-shared/src/basic/format-util.h | 8 + src/libnm-systemd-shared/src/basic/fs-util.c | 16 +- src/libnm-systemd-shared/src/basic/fs-util.h | 10 +- src/libnm-systemd-shared/src/basic/glyph-util.c | 13 + src/libnm-systemd-shared/src/basic/glyph-util.h | 6 + src/libnm-systemd-shared/src/basic/hashmap.c | 53 +++- src/libnm-systemd-shared/src/basic/hashmap.h | 10 +- src/libnm-systemd-shared/src/basic/in-addr-util.c | 16 +- src/libnm-systemd-shared/src/basic/in-addr-util.h | 2 + src/libnm-systemd-shared/src/basic/locale-util.c | 7 +- src/libnm-systemd-shared/src/basic/log.h | 4 +- src/libnm-systemd-shared/src/basic/missing_fcntl.h | 21 +- .../src/basic/missing_syscall.h | 19 +- .../src/basic/namespace-util.h | 2 + src/libnm-systemd-shared/src/basic/process-util.c | 23 +- src/libnm-systemd-shared/src/basic/process-util.h | 27 +- src/libnm-systemd-shared/src/basic/signal-util.c | 28 +-- src/libnm-systemd-shared/src/basic/signal-util.h | 9 +- src/libnm-systemd-shared/src/basic/stat-util.c | 199 ++++++++------- src/libnm-systemd-shared/src/basic/stat-util.h | 29 +-- src/libnm-systemd-shared/src/basic/string-util.c | 3 + src/libnm-systemd-shared/src/basic/strv.c | 2 +- src/libnm-systemd-shared/src/basic/time-util.c | 6 +- .../src/fundamental/macro-fundamental.h | 26 +- src/libnm-systemd-shared/src/fundamental/sha256.c | 278 --------------------- src/libnm-systemd-shared/src/fundamental/sha256.h | 39 --- 37 files changed, 508 insertions(+), 629 deletions(-) delete mode 100644 src/libnm-systemd-shared/src/fundamental/sha256.c delete mode 100644 src/libnm-systemd-shared/src/fundamental/sha256.h diff --git a/src/libnm-systemd-core/src/libsystemd/sd-device/sd-device.c b/src/libnm-systemd-core/src/libsystemd/sd-device/sd-device.c index bfc2a8a9ca..78ff928864 100644 --- a/src/libnm-systemd-core/src/libsystemd/sd-device/sd-device.c +++ b/src/libnm-systemd-core/src/libsystemd/sd-device/sd-device.c @@ -214,7 +214,7 @@ int device_set_syspath(sd_device *device, const char *_syspath, bool verify) { /* Only operate on sysfs, i.e. refuse going down into /sys/fs/cgroup/ or similar places where * things are not arranged as kobjects in kernel, and hence don't necessarily have * kobject/attribute structure. */ - r = getenv_bool_secure("SYSTEMD_DEVICE_VERIFY_SYSFS"); + r = secure_getenv_bool("SYSTEMD_DEVICE_VERIFY_SYSFS"); if (r < 0 && r != -ENXIO) log_debug_errno(r, "Failed to parse $SYSTEMD_DEVICE_VERIFY_SYSFS value: %m"); if (r != 0) { @@ -728,7 +728,7 @@ int device_read_uevent_file(sd_device *device) { _cleanup_free_ char *uevent = NULL; const char *syspath, *key = NULL, *value = NULL, *major = NULL, *minor = NULL; char *path; - size_t uevent_len; + size_t uevent_len = 0; int r; enum { @@ -1679,8 +1679,8 @@ int device_get_device_id(sd_device *device, const char **ret) { int device_read_db_internal_filename(sd_device *device, const char *filename) { _cleanup_free_ char *db = NULL; - const char *value; - size_t db_len; + const char *value = NULL; + size_t db_len = 0; char key = '\0'; /* Unnecessary initialization to appease gcc-12.0.0-0.4.fc36 */ int r; diff --git a/src/libnm-systemd-core/src/libsystemd/sd-event/sd-event.c b/src/libnm-systemd-core/src/libsystemd/sd-event/sd-event.c index 338609b186..12aa980593 100644 --- a/src/libnm-systemd-core/src/libsystemd/sd-event/sd-event.c +++ b/src/libnm-systemd-core/src/libsystemd/sd-event/sd-event.c @@ -1574,7 +1574,7 @@ static int child_exit_callback(sd_event_source *s, const siginfo_t *si, void *us static bool shall_use_pidfd(void) { /* Mostly relevant for debugging, i.e. this is used in test-event.c to test the event loop once with and once without pidfd */ - return getenv_bool_secure("SYSTEMD_PIDFD") != 0; + return secure_getenv_bool("SYSTEMD_PIDFD") != 0; } _public_ int sd_event_add_child( @@ -4915,13 +4915,13 @@ _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_origin_changed(e), -ECHILD); if (!e->exit_requested) return -ENODATA; - *code = e->exit_code; + if (code) + *code = e->exit_code; return 0; } diff --git a/src/libnm-systemd-core/src/libsystemd/sd-id128/id128-util.c b/src/libnm-systemd-core/src/libsystemd/sd-id128/id128-util.c index 7e5cb95d30..da20b503d4 100644 --- a/src/libnm-systemd-core/src/libsystemd/sd-id128/id128-util.c +++ b/src/libnm-systemd-core/src/libsystemd/sd-id128/id128-util.c @@ -139,7 +139,7 @@ int id128_read_at(int dir_fd, const char *path, Id128Flag f, sd_id128_t *ret) { assert(dir_fd >= 0 || dir_fd == AT_FDCWD); assert(path); - fd = xopenat(dir_fd, path, O_RDONLY|O_CLOEXEC|O_NOCTTY, /* xopen_flags = */ 0, /* mode = */ 0); + fd = xopenat(dir_fd, path, O_RDONLY|O_CLOEXEC|O_NOCTTY); if (fd < 0) return fd; @@ -185,7 +185,7 @@ int id128_write_at(int dir_fd, const char *path, Id128Flag f, sd_id128_t id) { assert(dir_fd >= 0 || dir_fd == AT_FDCWD); assert(path); - fd = xopenat(dir_fd, path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY|O_TRUNC, /* xopen_flags = */ 0, 0444); + fd = xopenat_full(dir_fd, path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY|O_TRUNC, /* xopen_flags = */ 0, 0444); if (fd < 0) return fd; diff --git a/src/libnm-systemd-core/src/systemd/sd-dhcp-duid.h b/src/libnm-systemd-core/src/systemd/sd-dhcp-duid.h index b1d2772a3e..555b40e9d8 100644 --- a/src/libnm-systemd-core/src/systemd/sd-dhcp-duid.h +++ b/src/libnm-systemd-core/src/systemd/sd-dhcp-duid.h @@ -3,7 +3,6 @@ #define foosddhcpduidhfoo /*** - Copyright © 2013 Intel Corporation. All rights reserved. systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or diff --git a/src/libnm-systemd-core/src/systemd/sd-ndisc.h b/src/libnm-systemd-core/src/systemd/sd-ndisc.h index a5ccd5f644..5f4f6caf8d 100644 --- a/src/libnm-systemd-core/src/systemd/sd-ndisc.h +++ b/src/libnm-systemd-core/src/systemd/sd-ndisc.h @@ -26,35 +26,14 @@ #include #include "sd-event.h" +#include "sd-ndisc-protocol.h" +#include "sd-ndisc-router.h" #include "_sd-common.h" _SD_BEGIN_DECLARATIONS; -/* Neighbor Discovery Options, RFC 4861, Section 4.6 and - * https://www.iana.org/assignments/icmpv6-parameters/icmpv6-parameters.xhtml#icmpv6-parameters-5 */ -enum { - SD_NDISC_OPTION_SOURCE_LL_ADDRESS = 1, - SD_NDISC_OPTION_TARGET_LL_ADDRESS = 2, - SD_NDISC_OPTION_PREFIX_INFORMATION = 3, - SD_NDISC_OPTION_MTU = 5, - SD_NDISC_OPTION_ROUTE_INFORMATION = 24, - SD_NDISC_OPTION_RDNSS = 25, - SD_NDISC_OPTION_FLAGS_EXTENSION = 26, - SD_NDISC_OPTION_DNSSL = 31, - SD_NDISC_OPTION_CAPTIVE_PORTAL = 37, - SD_NDISC_OPTION_PREF64 = 38 -}; - -/* Route preference, RFC 4191, Section 2.1 */ -enum { - SD_NDISC_PREFERENCE_LOW = 3U, - SD_NDISC_PREFERENCE_MEDIUM = 0U, - SD_NDISC_PREFERENCE_HIGH = 1U -}; - typedef struct sd_ndisc sd_ndisc; -typedef struct sd_ndisc_router sd_ndisc_router; __extension__ typedef enum sd_ndisc_event_t { SD_NDISC_EVENT_TIMEOUT, @@ -64,14 +43,16 @@ __extension__ typedef enum sd_ndisc_event_t { _SD_ENUM_FORCE_S64(NDISC_EVENT) } sd_ndisc_event_t; -typedef void (*sd_ndisc_callback_t)(sd_ndisc *nd, sd_ndisc_event_t event, sd_ndisc_router *rt, void *userdata); +typedef void (*sd_ndisc_callback_t)(sd_ndisc *nd, sd_ndisc_event_t event, void *message, void *userdata); int sd_ndisc_new(sd_ndisc **ret); sd_ndisc *sd_ndisc_ref(sd_ndisc *nd); sd_ndisc *sd_ndisc_unref(sd_ndisc *nd); +_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_ndisc, sd_ndisc_unref); int sd_ndisc_start(sd_ndisc *nd); int sd_ndisc_stop(sd_ndisc *nd); +int sd_ndisc_is_running(sd_ndisc *nd); int sd_ndisc_attach_event(sd_ndisc *nd, sd_event *event, int64_t priority); int sd_ndisc_detach_event(sd_ndisc *nd); @@ -81,69 +62,9 @@ int sd_ndisc_set_callback(sd_ndisc *nd, sd_ndisc_callback_t cb, void *userdata); int sd_ndisc_set_ifindex(sd_ndisc *nd, int interface_index); int sd_ndisc_set_ifname(sd_ndisc *nd, const char *interface_name); int sd_ndisc_get_ifname(sd_ndisc *nd, const char **ret); +int sd_ndisc_set_link_local_address(sd_ndisc *nd, const struct in6_addr *addr); int sd_ndisc_set_mac(sd_ndisc *nd, const struct ether_addr *mac_addr); -sd_ndisc_router *sd_ndisc_router_ref(sd_ndisc_router *rt); -sd_ndisc_router *sd_ndisc_router_unref(sd_ndisc_router *rt); - -int sd_ndisc_router_get_address(sd_ndisc_router *rt, struct in6_addr *ret); -int sd_ndisc_router_get_timestamp(sd_ndisc_router *rt, clockid_t clock, uint64_t *ret); -int sd_ndisc_router_get_raw(sd_ndisc_router *rt, const void **ret, size_t *ret_size); - -int sd_ndisc_router_get_hop_limit(sd_ndisc_router *rt, uint8_t *ret); -int sd_ndisc_router_get_icmp6_ratelimit(sd_ndisc_router *rt, uint64_t *ret); -int sd_ndisc_router_get_flags(sd_ndisc_router *rt, uint64_t *ret); -int sd_ndisc_router_get_preference(sd_ndisc_router *rt, unsigned *ret); -int sd_ndisc_router_get_lifetime(sd_ndisc_router *rt, uint64_t *ret); -int sd_ndisc_router_get_lifetime_timestamp(sd_ndisc_router *rt, clockid_t clock, uint64_t *ret); -int sd_ndisc_router_get_retransmission_time(sd_ndisc_router *rt, uint64_t *ret); -int sd_ndisc_router_get_mtu(sd_ndisc_router *rt, uint32_t *ret); - -/* Generic option access */ -int sd_ndisc_router_option_rewind(sd_ndisc_router *rt); -int sd_ndisc_router_option_next(sd_ndisc_router *rt); -int sd_ndisc_router_option_get_type(sd_ndisc_router *rt, uint8_t *ret); -int sd_ndisc_router_option_is_type(sd_ndisc_router *rt, uint8_t type); -int sd_ndisc_router_option_get_raw(sd_ndisc_router *rt, const void **ret, size_t *ret_size); - -/* Specific option access: SD_NDISC_OPTION_PREFIX_INFORMATION */ -int sd_ndisc_router_prefix_get_valid_lifetime(sd_ndisc_router *rt, uint64_t *ret); -int sd_ndisc_router_prefix_get_valid_lifetime_timestamp(sd_ndisc_router *rt, clockid_t clock, uint64_t *ret); -int sd_ndisc_router_prefix_get_preferred_lifetime(sd_ndisc_router *rt, uint64_t *ret); -int sd_ndisc_router_prefix_get_preferred_lifetime_timestamp(sd_ndisc_router *rt, clockid_t clock, uint64_t *ret); -int sd_ndisc_router_prefix_get_flags(sd_ndisc_router *rt, uint8_t *ret); -int sd_ndisc_router_prefix_get_address(sd_ndisc_router *rt, struct in6_addr *ret); -int sd_ndisc_router_prefix_get_prefixlen(sd_ndisc_router *rt, unsigned *ret); - -/* Specific option access: SD_NDISC_OPTION_ROUTE_INFORMATION */ -int sd_ndisc_router_route_get_lifetime(sd_ndisc_router *rt, uint64_t *ret); -int sd_ndisc_router_route_get_lifetime_timestamp(sd_ndisc_router *rt, clockid_t clock, uint64_t *ret); -int sd_ndisc_router_route_get_address(sd_ndisc_router *rt, struct in6_addr *ret); -int sd_ndisc_router_route_get_prefixlen(sd_ndisc_router *rt, unsigned *ret); -int sd_ndisc_router_route_get_preference(sd_ndisc_router *rt, unsigned *ret); - -/* Specific option access: SD_NDISC_OPTION_RDNSS */ -int sd_ndisc_router_rdnss_get_addresses(sd_ndisc_router *rt, const struct in6_addr **ret); -int sd_ndisc_router_rdnss_get_lifetime(sd_ndisc_router *rt, uint64_t *ret); -int sd_ndisc_router_rdnss_get_lifetime_timestamp(sd_ndisc_router *rt, clockid_t clock, uint64_t *ret); - -/* Specific option access: SD_NDISC_OPTION_DNSSL */ -int sd_ndisc_router_dnssl_get_domains(sd_ndisc_router *rt, char ***ret); -int sd_ndisc_router_dnssl_get_lifetime(sd_ndisc_router *rt, uint64_t *ret); -int sd_ndisc_router_dnssl_get_lifetime_timestamp(sd_ndisc_router *rt, clockid_t clock, uint64_t *ret); - -/* Specific option access: SD_NDISC_OPTION_CAPTIVE_PORTAL */ -int sd_ndisc_router_captive_portal_get_uri(sd_ndisc_router *rt, const char **ret, size_t *ret_size); - -/* Specific option access: SD_NDISC_OPTION_PREF64 */ -int sd_ndisc_router_prefix64_get_prefix(sd_ndisc_router *rt, struct in6_addr *ret); -int sd_ndisc_router_prefix64_get_prefixlen(sd_ndisc_router *rt, unsigned *ret); -int sd_ndisc_router_prefix64_get_lifetime(sd_ndisc_router *rt, uint64_t *ret); -int sd_ndisc_router_prefix64_get_lifetime_timestamp(sd_ndisc_router *rt, clockid_t clock, uint64_t *ret); - -_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_ndisc, sd_ndisc_unref); -_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_ndisc_router, sd_ndisc_router_unref); - _SD_END_DECLARATIONS; #endif diff --git a/src/libnm-systemd-shared/src/basic/env-util.c b/src/libnm-systemd-shared/src/basic/env-util.c index 6061edb904..7608f90a4a 100644 --- a/src/libnm-systemd-shared/src/basic/env-util.c +++ b/src/libnm-systemd-shared/src/basic/env-util.c @@ -18,6 +18,7 @@ #include "stdio-util.h" #include "string-util.h" #include "strv.h" +#include "syslog-util.h" #include "utf8.h" /* We follow bash for the character set. Different shells have different rules. */ @@ -309,19 +310,17 @@ char **strv_env_delete(char **x, size_t n_lists, ...) { return TAKE_PTR(t); } -char **strv_env_unset(char **l, const char *p) { - char **f, **t; +char** strv_env_unset(char **l, const char *p) { + assert(p); if (!l) return NULL; - assert(p); - /* Drops every occurrence of the env var setting p in the * string list. Edits in-place. */ + char **f, **t; for (f = t = l; *f; f++) { - if (env_match(*f, p)) { free(*f); continue; @@ -334,14 +333,13 @@ char **strv_env_unset(char **l, const char *p) { return l; } -char **strv_env_unset_many(char **l, ...) { - char **f, **t; - +char** strv_env_unset_many_internal(char **l, ...) { if (!l) return NULL; /* Like strv_env_unset() but applies many at once. Edits in-place. */ + char **f, **t; for (f = t = l; *f; f++) { bool found = false; const char *p; @@ -349,12 +347,11 @@ char **strv_env_unset_many(char **l, ...) { va_start(ap, l); - while ((p = va_arg(ap, const char*))) { + while ((p = va_arg(ap, const char*))) if (env_match(*f, p)) { found = true; break; } - } va_end(ap); @@ -966,7 +963,7 @@ int getenv_bool(const char *p) { return parse_boolean(e); } -int getenv_bool_secure(const char *p) { +int secure_getenv_bool(const char *p) { const char *e; e = secure_getenv(p); @@ -976,7 +973,7 @@ int getenv_bool_secure(const char *p) { return parse_boolean(e); } -int getenv_uint64_secure(const char *p, uint64_t *ret) { +int secure_getenv_uint64(const char *p, uint64_t *ret) { const char *e; assert(p); @@ -1030,6 +1027,17 @@ int setenv_systemd_exec_pid(bool update_only) { return 1; } +int setenv_systemd_log_level(void) { + _cleanup_free_ char *val = NULL; + int r; + + r = log_level_to_string_alloc(log_get_max_level(), &val); + if (r < 0) + return r; + + return RET_NERRNO(setenv("SYSTEMD_LOG_LEVEL", val, /* overwrite= */ true)); +} + int getenv_path_list(const char *name, char ***ret_paths) { _cleanup_strv_free_ char **l = NULL; const char *e; diff --git a/src/libnm-systemd-shared/src/basic/env-util.h b/src/libnm-systemd-shared/src/basic/env-util.h index ad127de39f..6610ca8ca1 100644 --- a/src/libnm-systemd-shared/src/basic/env-util.h +++ b/src/libnm-systemd-shared/src/basic/env-util.h @@ -43,8 +43,9 @@ char** _strv_env_merge(char **first, ...); #define strv_env_merge(first, ...) _strv_env_merge(first, __VA_ARGS__, POINTER_MAX) char **strv_env_delete(char **x, size_t n_lists, ...); /* New copy */ -char **strv_env_unset(char **l, const char *p); /* In place ... */ -char **strv_env_unset_many(char **l, ...) _sentinel_; +char** strv_env_unset(char **l, const char *p); /* In place ... */ +char** strv_env_unset_many_internal(char **l, ...) _sentinel_; +#define strv_env_unset_many(l, ...) strv_env_unset_many_internal(l, __VA_ARGS__, NULL) int strv_env_replace_consume(char ***l, char *p); /* In place ... */ int strv_env_replace_strdup(char ***l, const char *assignment); int strv_env_replace_strdup_passthrough(char ***l, const char *assignment); @@ -61,9 +62,9 @@ static inline char* strv_env_get(char * const *x, const char *n) { char *strv_env_pairs_get(char **l, const char *name) _pure_; int getenv_bool(const char *p); -int getenv_bool_secure(const char *p); +int secure_getenv_bool(const char *p); -int getenv_uint64_secure(const char *p, uint64_t *ret); +int secure_getenv_uint64(const char *p, uint64_t *ret); /* Like setenv, but calls unsetenv if value == NULL. */ int set_unset_env(const char *name, const char *value, bool overwrite); @@ -72,6 +73,7 @@ int set_unset_env(const char *name, const char *value, bool overwrite); int putenv_dup(const char *assignment, bool override); int setenv_systemd_exec_pid(bool update_only); +int setenv_systemd_log_level(void); /* Parses and does sanity checks on an environment variable containing * PATH-like colon-separated absolute paths */ diff --git a/src/libnm-systemd-shared/src/basic/extract-word.c b/src/libnm-systemd-shared/src/basic/extract-word.c index 160f771b22..012cee6e75 100644 --- a/src/libnm-systemd-shared/src/basic/extract-word.c +++ b/src/libnm-systemd-shared/src/basic/extract-word.c @@ -244,52 +244,43 @@ int extract_first_word_and_warn( * Let's make sure that ExtractFlags fits into an unsigned int. */ assert_cc(sizeof(enum ExtractFlags) <= sizeof(unsigned)); -int extract_many_words(const char **p, const char *separators, unsigned flags, ...) { +int extract_many_words_internal(const char **p, const char *separators, unsigned flags, ...) { va_list ap; - char **l; - int n = 0, i, c, r; + unsigned n = 0; + int r; - /* Parses a number of words from a string, stripping any - * quotes if necessary. */ + /* Parses a number of words from a string, stripping any quotes if necessary. */ assert(p); /* Count how many words are expected */ va_start(ap, flags); - for (;;) { - if (!va_arg(ap, char **)) - break; + while (va_arg(ap, char**)) n++; - } va_end(ap); - if (n <= 0) + if (n == 0) return 0; /* Read all words into a temporary array */ - l = newa0(char*, n); - for (c = 0; c < n; c++) { + char **l = newa0(char*, n); + unsigned c; + for (c = 0; c < n; c++) { r = extract_first_word(p, &l[c], separators, flags); if (r < 0) { free_many_charp(l, c); return r; } - if (r == 0) break; } - /* If we managed to parse all words, return them in the passed - * in parameters */ + /* If we managed to parse all words, return them in the passed in parameters */ va_start(ap, flags); - for (i = 0; i < n; i++) { - char **v; - - v = va_arg(ap, char **); - assert(v); - - *v = l[i]; + FOREACH_ARRAY(i, l, n) { + char **v = ASSERT_PTR(va_arg(ap, char**)); + *v = *i; } va_end(ap); diff --git a/src/libnm-systemd-shared/src/basic/extract-word.h b/src/libnm-systemd-shared/src/basic/extract-word.h index c82ad761ef..da4f6ae674 100644 --- a/src/libnm-systemd-shared/src/basic/extract-word.h +++ b/src/libnm-systemd-shared/src/basic/extract-word.h @@ -19,4 +19,7 @@ typedef enum ExtractFlags { int extract_first_word(const char **p, char **ret, const char *separators, ExtractFlags flags); int extract_first_word_and_warn(const char **p, char **ret, const char *separators, ExtractFlags flags, const char *unit, const char *filename, unsigned line, const char *rvalue); -int extract_many_words(const char **p, const char *separators, unsigned flags, ...) _sentinel_; + +int extract_many_words_internal(const char **p, const char *separators, unsigned flags, ...) _sentinel_; +#define extract_many_words(p, separators, flags, ...) \ + extract_many_words_internal(p, separators, flags, ##__VA_ARGS__, NULL) diff --git a/src/libnm-systemd-shared/src/basic/fd-util.c b/src/libnm-systemd-shared/src/basic/fd-util.c index 38866ebb78..c16a2ab658 100644 --- a/src/libnm-systemd-shared/src/basic/fd-util.c +++ b/src/libnm-systemd-shared/src/basic/fd-util.c @@ -308,7 +308,7 @@ static int close_all_fds_special_case(const int except[], size_t n_except) { case 0: /* Close everything. Yay! */ - if (close_range(3, -1, 0) >= 0) + if (close_range(3, INT_MAX, 0) >= 0) return 1; if (ERRNO_IS_NOT_SUPPORTED(errno) || ERRNO_IS_PRIVILEGE(errno)) { @@ -419,7 +419,7 @@ int close_all_fds(const int except[], size_t n_except) { if (sorted[n_sorted-1] >= INT_MAX) /* Dont let the addition below overflow */ return 0; - if (close_range(sorted[n_sorted-1] + 1, -1, 0) >= 0) + if (close_range(sorted[n_sorted-1] + 1, INT_MAX, 0) >= 0) return 0; if (!ERRNO_IS_NOT_SUPPORTED(errno) && !ERRNO_IS_PRIVILEGE(errno)) @@ -464,6 +464,53 @@ int close_all_fds(const int except[], size_t n_except) { return r; } +int pack_fds(int fds[], size_t n_fds) { + if (n_fds <= 0) + return 0; + + /* Shifts around the fds in the provided array such that they + * all end up packed next to each-other, in order, starting + * from SD_LISTEN_FDS_START. This must be called after close_all_fds(); + * it is likely to freeze up otherwise. You should probably use safe_fork_full + * with FORK_CLOSE_ALL_FDS|FORK_PACK_FDS set, to ensure that this is done correctly. + * The fds array is modified in place with the new FD numbers. */ + + assert(fds); + + for (int start = 0;;) { + int restart_from = -1; + + for (int i = start; i < (int) n_fds; i++) { + int nfd; + + /* Already at right index? */ + if (fds[i] == i + 3) + continue; + + nfd = fcntl(fds[i], F_DUPFD, i + 3); + if (nfd < 0) + return -errno; + + safe_close(fds[i]); + fds[i] = nfd; + + /* Hmm, the fd we wanted isn't free? Then + * let's remember that and try again from here */ + if (nfd != i + 3 && restart_from < 0) + restart_from = i; + } + + if (restart_from < 0) + break; + + start = restart_from; + } + + assert(fds[0] == 3); + + return 0; +} + int same_fd(int a, int b) { struct stat sta, stb; pid_t pid; @@ -866,6 +913,38 @@ int fd_is_opath(int fd) { return FLAGS_SET(r, O_PATH); } +int fd_verify_safe_flags(int fd) { + int flags, unexpected_flags; + + /* Check if an extrinsic fd is safe to work on (by a privileged service). This ensures that clients + * can't trick a privileged service into giving access to a file the client doesn't already have + * access to (especially via something like O_PATH). + * + * O_NOFOLLOW: For some reason the kernel will return this flag from fcntl; it doesn't go away + * immediately after open(). It should have no effect whatsoever to an already-opened FD, + * and since we refuse O_PATH it should be safe. + * + * RAW_O_LARGEFILE: glibc secretly sets this and neglects to hide it from us if we call fcntl. + * See comment in missing_fcntl.h for more details about this. + * + * O_DIRECTORY: this is set for directories, which are totally fine + */ + + assert(fd >= 0); + + flags = fcntl(fd, F_GETFL); + if (flags < 0) + return -errno; + + unexpected_flags = flags & ~(O_ACCMODE|O_NOFOLLOW|RAW_O_LARGEFILE|O_DIRECTORY); + if (unexpected_flags != 0) + return log_debug_errno(SYNTHETIC_ERRNO(EREMOTEIO), + "Unexpected flags set for extrinsic fd: 0%o", + (unsigned) unexpected_flags); + + return 0; +} + int read_nr_open(void) { _cleanup_free_ char *nr_open = NULL; int r; diff --git a/src/libnm-systemd-shared/src/basic/fd-util.h b/src/libnm-systemd-shared/src/basic/fd-util.h index 183266513a..f549831090 100644 --- a/src/libnm-systemd-shared/src/basic/fd-util.h +++ b/src/libnm-systemd-shared/src/basic/fd-util.h @@ -8,6 +8,7 @@ #include #include "macro.h" +#include "missing_fcntl.h" #include "stdio-util.h" /* maximum length of fdname */ @@ -77,6 +78,8 @@ int get_max_fd(void); int close_all_fds(const int except[], size_t n_except); int close_all_fds_without_malloc(const int except[], size_t n_except); +int pack_fds(int fds[], size_t n); + int same_fd(int a, int b); void cmsg_close_all(struct msghdr *mh); @@ -109,7 +112,10 @@ static inline int make_null_stdio(void) { int fd_reopen(int fd, int flags); int fd_reopen_condition(int fd, int flags, int mask, int *ret_new_fd); + int fd_is_opath(int fd); +int fd_verify_safe_flags(int fd); + int read_nr_open(void); int fd_get_diskseq(int fd, uint64_t *ret); diff --git a/src/libnm-systemd-shared/src/basic/format-util.h b/src/libnm-systemd-shared/src/basic/format-util.h index 8719df3e29..ba7cff6a8b 100644 --- a/src/libnm-systemd-shared/src/basic/format-util.h +++ b/src/libnm-systemd-shared/src/basic/format-util.h @@ -18,6 +18,14 @@ assert_cc(sizeof(uid_t) == sizeof(uint32_t)); assert_cc(sizeof(gid_t) == sizeof(uint32_t)); #define GID_FMT "%" PRIu32 +/* Note: the lifetime of the compound literal is the immediately surrounding block, + * see C11 §6.5.2.5, and + * https://stackoverflow.com/questions/34880638/compound-literal-lifetime-and-if-blocks */ +#define FORMAT_UID(uid) \ + snprintf_ok((char[DECIMAL_STR_MAX(uid_t)]){}, DECIMAL_STR_MAX(uid_t), UID_FMT, uid) +#define FORMAT_GID(gid) \ + snprintf_ok((char[DECIMAL_STR_MAX(gid_t)]){}, DECIMAL_STR_MAX(gid_t), GID_FMT, gid) + #if SIZEOF_TIME_T == 8 # define PRI_TIME PRIi64 #elif SIZEOF_TIME_T == 4 diff --git a/src/libnm-systemd-shared/src/basic/fs-util.c b/src/libnm-systemd-shared/src/basic/fs-util.c index ee38e0266a..5bc7d2f95b 100644 --- a/src/libnm-systemd-shared/src/basic/fs-util.c +++ b/src/libnm-systemd-shared/src/basic/fs-util.c @@ -116,7 +116,11 @@ int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char int readlinkat_malloc(int fd, const char *p, char **ret) { size_t l = PATH_MAX; - assert(p); + assert(fd >= 0 || fd == AT_FDCWD); + + if (fd < 0 && isempty(p)) + return -EISDIR; /* In this case, the fd points to the current working directory, and is + * definitely not a symlink. Let's return earlier. */ for (;;) { _cleanup_free_ char *c = NULL; @@ -126,7 +130,7 @@ int readlinkat_malloc(int fd, const char *p, char **ret) { if (!c) return -ENOMEM; - n = readlinkat(fd, p, c, l); + n = readlinkat(fd, strempty(p), c, l); if (n < 0) return -errno; @@ -1050,7 +1054,7 @@ int open_mkdir_at(int dirfd, const char *path, int flags, mode_t mode) { path = fname; } - fd = xopenat(dirfd, path, flags|O_CREAT|O_DIRECTORY|O_NOFOLLOW, /* xopen_flags = */ 0, mode); + fd = xopenat_full(dirfd, path, flags|O_CREAT|O_DIRECTORY|O_NOFOLLOW, /* xopen_flags = */ 0, mode); if (IN_SET(fd, -ELOOP, -ENOTDIR)) return -EEXIST; if (fd < 0) @@ -1106,7 +1110,7 @@ int openat_report_new(int dirfd, const char *pathname, int flags, mode_t mode, b } } -int xopenat(int dir_fd, const char *path, int open_flags, XOpenFlags xopen_flags, mode_t mode) { +int xopenat_full(int dir_fd, const char *path, int open_flags, XOpenFlags xopen_flags, mode_t mode) { _cleanup_close_ int fd = -EBADF; bool made = false; int r; @@ -1187,7 +1191,7 @@ int xopenat(int dir_fd, const char *path, int open_flags, XOpenFlags xopen_flags return TAKE_FD(fd); } -int xopenat_lock( +int xopenat_lock_full( int dir_fd, const char *path, int open_flags, @@ -1210,7 +1214,7 @@ int xopenat_lock( for (;;) { struct stat st; - fd = xopenat(dir_fd, path, open_flags, xopen_flags, mode); + fd = xopenat_full(dir_fd, path, open_flags, xopen_flags, mode); if (fd < 0) return fd; diff --git a/src/libnm-systemd-shared/src/basic/fs-util.h b/src/libnm-systemd-shared/src/basic/fs-util.h index 1023ab73ca..6a1e2e76d1 100644 --- a/src/libnm-systemd-shared/src/basic/fs-util.h +++ b/src/libnm-systemd-shared/src/basic/fs-util.h @@ -137,6 +137,12 @@ typedef enum XOpenFlags { XO_SUBVOLUME = 1 << 1, } XOpenFlags; -int xopenat(int dir_fd, const char *path, int open_flags, XOpenFlags xopen_flags, mode_t mode); +int xopenat_full(int dir_fd, const char *path, int open_flags, XOpenFlags xopen_flags, mode_t mode); +static inline int xopenat(int dir_fd, const char *path, int open_flags) { + return xopenat_full(dir_fd, path, open_flags, 0, 0); +} -int xopenat_lock(int dir_fd, const char *path, int open_flags, XOpenFlags xopen_flags, mode_t mode, LockType locktype, int operation); +int xopenat_lock_full(int dir_fd, const char *path, int open_flags, XOpenFlags xopen_flags, mode_t mode, LockType locktype, int operation); +static inline int xopenat_lock(int dir_fd, const char *path, int open_flags, LockType locktype, int operation) { + return xopenat_lock_full(dir_fd, path, open_flags, 0, 0, locktype, operation); +} diff --git a/src/libnm-systemd-shared/src/basic/glyph-util.c b/src/libnm-systemd-shared/src/basic/glyph-util.c index 803bdd90e2..d37be3234a 100644 --- a/src/libnm-systemd-shared/src/basic/glyph-util.c +++ b/src/libnm-systemd-shared/src/basic/glyph-util.c @@ -41,6 +41,8 @@ const char *special_glyph_full(SpecialGlyph code, bool force_utf) { [SPECIAL_GLYPH_TREE_SPACE] = " ", [SPECIAL_GLYPH_TREE_TOP] = ",-", [SPECIAL_GLYPH_VERTICAL_DOTTED] = ":", + [SPECIAL_GLYPH_HORIZONTAL_DOTTED] = "-", + [SPECIAL_GLYPH_HORIZONTAL_FAT] = "=", [SPECIAL_GLYPH_TRIANGULAR_BULLET] = ">", [SPECIAL_GLYPH_BLACK_CIRCLE] = "*", [SPECIAL_GLYPH_WHITE_CIRCLE] = "*", @@ -74,6 +76,10 @@ const char *special_glyph_full(SpecialGlyph code, bool force_utf) { [SPECIAL_GLYPH_SPARKLES] = "*", [SPECIAL_GLYPH_LOW_BATTERY] = "!", [SPECIAL_GLYPH_WARNING_SIGN] = "!", + [SPECIAL_GLYPH_RED_CIRCLE] = "o", + [SPECIAL_GLYPH_YELLOW_CIRCLE] = "o", + [SPECIAL_GLYPH_BLUE_CIRCLE] = "o", + [SPECIAL_GLYPH_GREEN_CIRCLE] = "o", }, /* UTF-8 */ @@ -87,6 +93,8 @@ const char *special_glyph_full(SpecialGlyph code, bool force_utf) { /* Single glyphs in both cases */ [SPECIAL_GLYPH_VERTICAL_DOTTED] = u8"┆", + [SPECIAL_GLYPH_HORIZONTAL_DOTTED] = u8"┄", + [SPECIAL_GLYPH_HORIZONTAL_FAT] = u8"━", [SPECIAL_GLYPH_TRIANGULAR_BULLET] = u8"‣", [SPECIAL_GLYPH_BLACK_CIRCLE] = u8"●", [SPECIAL_GLYPH_WHITE_CIRCLE] = u8"○", @@ -136,6 +144,11 @@ const char *special_glyph_full(SpecialGlyph code, bool force_utf) { [SPECIAL_GLYPH_WARNING_SIGN] = u8"⚠️", [SPECIAL_GLYPH_COMPUTER_DISK] = u8"💽", [SPECIAL_GLYPH_WORLD] = u8"🌍", + + [SPECIAL_GLYPH_RED_CIRCLE] = u8"🔴", + [SPECIAL_GLYPH_YELLOW_CIRCLE] = u8"🟡", + [SPECIAL_GLYPH_BLUE_CIRCLE] = u8"🔵", + [SPECIAL_GLYPH_GREEN_CIRCLE] = u8"🟢", }, }; diff --git a/src/libnm-systemd-shared/src/basic/glyph-util.h b/src/libnm-systemd-shared/src/basic/glyph-util.h index a7709976e1..db8dbbff26 100644 --- a/src/libnm-systemd-shared/src/basic/glyph-util.h +++ b/src/libnm-systemd-shared/src/basic/glyph-util.h @@ -13,6 +13,8 @@ typedef enum SpecialGlyph { SPECIAL_GLYPH_TREE_SPACE, SPECIAL_GLYPH_TREE_TOP, SPECIAL_GLYPH_VERTICAL_DOTTED, + SPECIAL_GLYPH_HORIZONTAL_DOTTED, + SPECIAL_GLYPH_HORIZONTAL_FAT, SPECIAL_GLYPH_TRIANGULAR_BULLET, SPECIAL_GLYPH_BLACK_CIRCLE, SPECIAL_GLYPH_WHITE_CIRCLE, @@ -49,6 +51,10 @@ typedef enum SpecialGlyph { SPECIAL_GLYPH_WARNING_SIGN, SPECIAL_GLYPH_COMPUTER_DISK, SPECIAL_GLYPH_WORLD, + SPECIAL_GLYPH_RED_CIRCLE, + SPECIAL_GLYPH_YELLOW_CIRCLE, + SPECIAL_GLYPH_BLUE_CIRCLE, + SPECIAL_GLYPH_GREEN_CIRCLE, _SPECIAL_GLYPH_MAX, _SPECIAL_GLYPH_INVALID = -EINVAL, } SpecialGlyph; diff --git a/src/libnm-systemd-shared/src/basic/hashmap.c b/src/libnm-systemd-shared/src/basic/hashmap.c index 894760ca60..a9fd762029 100644 --- a/src/libnm-systemd-shared/src/basic/hashmap.c +++ b/src/libnm-systemd-shared/src/basic/hashmap.c @@ -2120,24 +2120,27 @@ static int hashmap_entry_compare( return compare((*a)->key, (*b)->key); } -int _hashmap_dump_sorted(HashmapBase *h, void ***ret, size_t *ret_n) { - _cleanup_free_ struct hashmap_base_entry **entries = NULL; +static int _hashmap_dump_entries_sorted( + HashmapBase *h, + void ***ret, + size_t *ret_n) { + _cleanup_free_ void **entries = NULL; Iterator iter; unsigned idx; size_t n = 0; assert(ret); + assert(ret_n); if (_hashmap_size(h) == 0) { *ret = NULL; - if (ret_n) - *ret_n = 0; + *ret_n = 0; return 0; } /* We append one more element than needed so that the resulting array can be used as a strv. We * don't count this entry in the returned size. */ - entries = new(struct hashmap_base_entry*, _hashmap_size(h) + 1); + entries = new(void*, _hashmap_size(h) + 1); if (!entries) return -ENOMEM; @@ -2147,13 +2150,47 @@ int _hashmap_dump_sorted(HashmapBase *h, void ***ret, size_t *ret_n) { assert(n == _hashmap_size(h)); entries[n] = NULL; - typesafe_qsort_r(entries, n, hashmap_entry_compare, h->hash_ops->compare); + typesafe_qsort_r((struct hashmap_base_entry**) entries, n, + hashmap_entry_compare, h->hash_ops->compare); + + *ret = TAKE_PTR(entries); + *ret_n = n; + return 0; +} + +int _hashmap_dump_keys_sorted(HashmapBase *h, void ***ret, size_t *ret_n) { + _cleanup_free_ void **entries = NULL; + size_t n; + int r; + + r = _hashmap_dump_entries_sorted(h, &entries, &n); + if (r < 0) + return r; + + /* Reuse the array. */ + FOREACH_ARRAY(e, entries, n) + *e = (void*) (*(struct hashmap_base_entry**) e)->key; + + *ret = TAKE_PTR(entries); + if (ret_n) + *ret_n = n; + return 0; +} + +int _hashmap_dump_sorted(HashmapBase *h, void ***ret, size_t *ret_n) { + _cleanup_free_ void **entries = NULL; + size_t n; + int r; + + r = _hashmap_dump_entries_sorted(h, &entries, &n); + if (r < 0) + return r; /* Reuse the array. */ FOREACH_ARRAY(e, entries, n) - *e = entry_value(h, *e); + *e = entry_value(h, *(struct hashmap_base_entry**) e); - *ret = (void**) TAKE_PTR(entries); + *ret = TAKE_PTR(entries); if (ret_n) *ret_n = n; return 0; diff --git a/src/libnm-systemd-shared/src/basic/hashmap.h b/src/libnm-systemd-shared/src/basic/hashmap.h index 233f1d7a1e..49d9d118cc 100644 --- a/src/libnm-systemd-shared/src/basic/hashmap.h +++ b/src/libnm-systemd-shared/src/basic/hashmap.h @@ -39,8 +39,8 @@ typedef struct IteratedCache IteratedCache; /* Caches the iterated order of on * by hashmap users, so the definition has to be here. Do not use its fields * directly. */ typedef struct { - unsigned idx; /* index of an entry to be iterated next */ const void *next_key; /* expected value of that entry's key pointer */ + unsigned idx; /* index of an entry to be iterated next */ #if ENABLE_DEBUG_HASHMAP unsigned put_count; /* hashmap's put_count recorded at start of iteration */ unsigned rem_count; /* hashmap's rem_count in previous iteration */ @@ -409,6 +409,14 @@ static inline int set_dump_sorted(Set *h, void ***ret, size_t *ret_n) { return _hashmap_dump_sorted(HASHMAP_BASE(h), ret, ret_n); } +int _hashmap_dump_keys_sorted(HashmapBase *h, void ***ret, size_t *ret_n); +static inline int hashmap_dump_keys_sorted(Hashmap *h, void ***ret, size_t *ret_n) { + return _hashmap_dump_keys_sorted(HASHMAP_BASE(h), ret, ret_n); +} +static inline int ordered_hashmap_dump_keys_sorted(OrderedHashmap *h, void ***ret, size_t *ret_n) { + return _hashmap_dump_keys_sorted(HASHMAP_BASE(h), ret, ret_n); +} + /* * Hashmaps are iterated in unpredictable order. * OrderedHashmaps are an exception to this. They are iterated in the order diff --git a/src/libnm-systemd-shared/src/basic/in-addr-util.c b/src/libnm-systemd-shared/src/basic/in-addr-util.c index 8bd9c75d59..82c8ff9a2d 100644 --- a/src/libnm-systemd-shared/src/basic/in-addr-util.c +++ b/src/libnm-systemd-shared/src/basic/in-addr-util.c @@ -91,14 +91,26 @@ bool in6_addr_is_link_local_all_nodes(const struct in6_addr *a) { be32toh(a->s6_addr32[3]) == UINT32_C(0x00000001); } +bool in4_addr_is_multicast(const struct in_addr *a) { + assert(a); + + return IN_MULTICAST(be32toh(a->s_addr)); +} + +bool in6_addr_is_multicast(const struct in6_addr *a) { + assert(a); + + return IN6_IS_ADDR_MULTICAST(a); +} + int in_addr_is_multicast(int family, const union in_addr_union *u) { assert(u); if (family == AF_INET) - return IN_MULTICAST(be32toh(u->in.s_addr)); + return in4_addr_is_multicast(&u->in); if (family == AF_INET6) - return IN6_IS_ADDR_MULTICAST(&u->in6); + return in6_addr_is_multicast(&u->in6); return -EAFNOSUPPORT; } diff --git a/src/libnm-systemd-shared/src/basic/in-addr-util.h b/src/libnm-systemd-shared/src/basic/in-addr-util.h index 9fae3cae45..5c820c6ec6 100644 --- a/src/libnm-systemd-shared/src/basic/in-addr-util.h +++ b/src/libnm-systemd-shared/src/basic/in-addr-util.h @@ -40,6 +40,8 @@ static inline bool in_addr_data_is_set(const struct in_addr_data *a) { return in_addr_data_is_null(a); } +bool in4_addr_is_multicast(const struct in_addr *a); +bool in6_addr_is_multicast(const struct in6_addr *a); int in_addr_is_multicast(int family, const union in_addr_union *u); bool in4_addr_is_link_local(const struct in_addr *a); diff --git a/src/libnm-systemd-shared/src/basic/locale-util.c b/src/libnm-systemd-shared/src/basic/locale-util.c index 9e70c3f01f..23565273dd 100644 --- a/src/libnm-systemd-shared/src/basic/locale-util.c +++ b/src/libnm-systemd-shared/src/basic/locale-util.c @@ -260,7 +260,10 @@ bool locale_is_valid(const char *name) { if (!filename_is_valid(name)) return false; - if (!string_is_safe(name)) + /* Locales look like: ll_CC.ENC@variant, where ll and CC are alphabetic, ENC is alphanumeric with + * dashes, and variant seems to be alphabetic. + * See: https://www.gnu.org/software/gettext/manual/html_node/Locale-Names.html */ + if (!in_charset(name, ALPHANUMERICAL "_.-@")) return false; return true; @@ -292,7 +295,7 @@ bool is_locale_utf8(void) { if (cached_answer >= 0) goto out; - r = getenv_bool_secure("SYSTEMD_UTF8"); + r = secure_getenv_bool("SYSTEMD_UTF8"); if (r >= 0) { cached_answer = r; goto out; diff --git a/src/libnm-systemd-shared/src/basic/log.h b/src/libnm-systemd-shared/src/basic/log.h index 140e501eb1..23f54b88fb 100644 --- a/src/libnm-systemd-shared/src/basic/log.h +++ b/src/libnm-systemd-shared/src/basic/log.h @@ -383,7 +383,7 @@ typedef struct LogRateLimit { RateLimit ratelimit; } LogRateLimit; -#define log_ratelimit_internal(_level, _error, _ratelimit, _format, _file, _line, _func, ...) \ +#define log_ratelimit_internal(_level, _error, _ratelimit, _file, _line, _func, _format, ...) \ ({ \ int _log_ratelimit_error = (_error); \ int _log_ratelimit_level = (_level); \ @@ -407,7 +407,7 @@ typedef struct LogRateLimit { ({ \ int _level = (level), _e = (error); \ _e = (log_get_max_level() >= LOG_PRI(_level)) \ - ? log_ratelimit_internal(_level, _e, _ratelimit, format, PROJECT_FILE, __LINE__, __func__, ##__VA_ARGS__) \ + ? log_ratelimit_internal(_level, _e, _ratelimit, PROJECT_FILE, __LINE__, __func__, format, ##__VA_ARGS__) \ : -ERRNO_VALUE(_e); \ _e < 0 ? _e : -ESTRPIPE; \ }) diff --git a/src/libnm-systemd-shared/src/basic/missing_fcntl.h b/src/libnm-systemd-shared/src/basic/missing_fcntl.h index 24b2dc3119..3c85befda9 100644 --- a/src/libnm-systemd-shared/src/basic/missing_fcntl.h +++ b/src/libnm-systemd-shared/src/basic/missing_fcntl.h @@ -69,9 +69,26 @@ /* So O_LARGEFILE is generally implied by glibc, and defined to zero hence, because we only build in LFS * mode. However, when invoking fcntl(F_GETFL) the flag is ORed into the result anyway — glibc does not mask - * it away. Which sucks. Let's define the actual value here, so that we can mask it ourselves. */ + * it away. Which sucks. Let's define the actual value here, so that we can mask it ourselves. + * + * The precise definition is arch specific, so we use the values defined in the kernel (note that some + * are hexa and others are octal; duplicated as-is from the kernel definitions): + * - alpha, arm, arm64, m68k, mips, parisc, powerpc, sparc: each has a specific value; + * - others: they use the "generic" value (defined in include/uapi/asm-generic/fcntl.h) */ #if O_LARGEFILE != 0 #define RAW_O_LARGEFILE O_LARGEFILE #else -#define RAW_O_LARGEFILE 0100000 +#if defined(__alpha__) || defined(__arm__) || defined(__aarch64__) || defined(__m68k__) +#define RAW_O_LARGEFILE 0400000 +#elif defined(__mips__) +#define RAW_O_LARGEFILE 0x2000 +#elif defined(__parisc__) || defined(__hppa__) +#define RAW_O_LARGEFILE 000004000 +#elif defined(__powerpc__) +#define RAW_O_LARGEFILE 0200000 +#elif defined(__sparc__) +#define RAW_O_LARGEFILE 0x40000 +#else +#define RAW_O_LARGEFILE 00100000 +#endif #endif diff --git a/src/libnm-systemd-shared/src/basic/missing_syscall.h b/src/libnm-systemd-shared/src/basic/missing_syscall.h index d795efd8f2..86280771c4 100644 --- a/src/libnm-systemd-shared/src/basic/missing_syscall.h +++ b/src/libnm-systemd-shared/src/basic/missing_syscall.h @@ -412,23 +412,14 @@ static inline int missing_execveat(int dirfd, const char *pathname, /* ======================================================================= */ #if !HAVE_CLOSE_RANGE -static inline int missing_close_range(int first_fd, int end_fd, unsigned flags) { +static inline int missing_close_range(unsigned first_fd, unsigned end_fd, unsigned flags) { # ifdef __NR_close_range /* Kernel-side the syscall expects fds as unsigned integers (just like close() actually), while - * userspace exclusively uses signed integers for fds. We don't know just yet how glibc is going to - * wrap this syscall, but let's assume it's going to be similar to what they do for close(), - * i.e. make the same unsigned → signed type change from the raw kernel syscall compared to the - * userspace wrapper. There's only one caveat for this: unlike for close() there's the special - * UINT_MAX fd value for the 'end_fd' argument. Let's safely map that to -1 here. And let's refuse - * any other negative values. */ - if ((first_fd < 0) || (end_fd < 0 && end_fd != -1)) { - errno = -EBADF; - return -1; - } - + * userspace exclusively uses signed integers for fds. glibc chose to expose it 1:1 however, hence we + * do so here too, even if we end up passing signed fds to it most of the time. */ return syscall(__NR_close_range, - (unsigned) first_fd, - end_fd == -1 ? UINT_MAX : (unsigned) end_fd, /* Of course, the compiler should figure out that this is the identity mapping IRL */ + first_fd, + end_fd, flags); # else errno = ENOSYS; diff --git a/src/libnm-systemd-shared/src/basic/namespace-util.h b/src/libnm-systemd-shared/src/basic/namespace-util.h index d1d015612f..34cbec3f6e 100644 --- a/src/libnm-systemd-shared/src/basic/namespace-util.h +++ b/src/libnm-systemd-shared/src/basic/namespace-util.h @@ -53,3 +53,5 @@ static inline bool userns_shift_range_valid(uid_t shift, uid_t range) { int userns_acquire(const char *uid_map, const char *gid_map); int netns_acquire(void); int in_same_namespace(pid_t pid1, pid_t pid2, NamespaceType type); + +int parse_userns_uid_range(const char *s, uid_t *ret_uid_shift, uid_t *ret_uid_range); diff --git a/src/libnm-systemd-shared/src/basic/process-util.c b/src/libnm-systemd-shared/src/basic/process-util.c index a94ff38409..69635e65f8 100644 --- a/src/libnm-systemd-shared/src/basic/process-util.c +++ b/src/libnm-systemd-shared/src/basic/process-util.c @@ -510,7 +510,7 @@ static int get_process_link_contents(pid_t pid, const char *proc_file, char **re p = procfs_file_alloca(pid, proc_file); r = readlink_malloc(p, ret); - return r == -ENOENT ? -ESRCH : r; + return (r == -ENOENT && proc_mounted() > 0) ? -ESRCH : r; } int get_process_exe(pid_t pid, char **ret) { @@ -1303,7 +1303,7 @@ int opinionated_personality(unsigned long *ret) { if (current < 0) return current; - if (((unsigned long) current & 0xffff) == PER_LINUX32) + if (((unsigned long) current & OPINIONATED_PERSONALITY_MASK) == PER_LINUX32) *ret = PER_LINUX32; else *ret = PER_LINUX; @@ -1468,7 +1468,7 @@ static int fork_flags_to_signal(ForkFlags flags) { int safe_fork_full( const char *name, const int stdio_fds[3], - const int except_fds[], + int except_fds[], size_t n_except_fds, ForkFlags flags, pid_t *ret_pid) { @@ -1697,6 +1697,19 @@ int safe_fork_full( } } + if (flags & FORK_PACK_FDS) { + /* FORK_CLOSE_ALL_FDS ensures that except_fds are the only FDs >= 3 that are + * open, this is including the log. This is required by pack_fds, which will + * get stuck in an infinite loop of any FDs other than except_fds are open. */ + assert(FLAGS_SET(flags, FORK_CLOSE_ALL_FDS)); + + r = pack_fds(except_fds, n_except_fds); + if (r < 0) { + log_full_errno(prio, r, "Failed to pack file descriptors: %m"); + _exit(EXIT_FAILURE); + } + } + if (flags & FORK_CLOEXEC_OFF) { r = fd_cloexec_many(except_fds, n_except_fds, false); if (r < 0) { @@ -1736,7 +1749,7 @@ int safe_fork_full( int pidref_safe_fork_full( const char *name, const int stdio_fds[3], - const int except_fds[], + int except_fds[], size_t n_except_fds, ForkFlags flags, PidRef *ret_pid) { @@ -1760,7 +1773,7 @@ int pidref_safe_fork_full( int namespace_fork( const char *outer_name, const char *inner_name, - const int except_fds[], + int except_fds[], size_t n_except_fds, ForkFlags flags, int pidns_fd, diff --git a/src/libnm-systemd-shared/src/basic/process-util.h b/src/libnm-systemd-shared/src/basic/process-util.h index 0fc31f7086..8308402847 100644 --- a/src/libnm-systemd-shared/src/basic/process-util.h +++ b/src/libnm-systemd-shared/src/basic/process-util.h @@ -101,12 +101,17 @@ bool is_main_thread(void); bool oom_score_adjust_is_valid(int oa); #ifndef PERSONALITY_INVALID -/* personality(7) documents that 0xffffffffUL is used for querying the +/* personality(2) documents that 0xFFFFFFFFUL is used for querying the * current personality, hence let's use that here as error * indicator. */ -#define PERSONALITY_INVALID 0xffffffffLU +#define PERSONALITY_INVALID 0xFFFFFFFFUL #endif +/* The personality() syscall returns a 32-bit value where the top three bytes are reserved for flags that + * emulate historical or architectural quirks, and only the least significant byte reflects the actual + * personality we're interested in. */ +#define OPINIONATED_PERSONALITY_MASK 0xFFUL + unsigned long personality_from_string(const char *p); const char *personality_to_string(unsigned long); @@ -180,12 +185,13 @@ typedef enum ForkFlags { FORK_KEEP_NOTIFY_SOCKET = 1 << 17, /* Unless this specified, $NOTIFY_SOCKET will be unset. */ FORK_DETACH = 1 << 18, /* Double fork if needed to ensure PID1/subreaper is parent */ FORK_NEW_NETNS = 1 << 19, /* Run child in its own network namespace 💣 DO NOT USE IN THREADED PROGRAMS! 💣 */ + FORK_PACK_FDS = 1 << 20, /* Rearrange the passed FDs to be FD 3,4,5,etc. Updates the array in place (combine with FORK_CLOSE_ALL_FDS!) */ } ForkFlags; int safe_fork_full( const char *name, const int stdio_fds[3], - const int except_fds[], + int except_fds[], size_t n_except_fds, ForkFlags flags, pid_t *ret_pid); @@ -197,7 +203,7 @@ static inline int safe_fork(const char *name, ForkFlags flags, pid_t *ret_pid) { int pidref_safe_fork_full( const char *name, const int stdio_fds[3], - const int except_fds[], + int except_fds[], size_t n_except_fds, ForkFlags flags, PidRef *ret_pid); @@ -206,7 +212,18 @@ static inline int pidref_safe_fork(const char *name, ForkFlags flags, PidRef *re return pidref_safe_fork_full(name, NULL, NULL, 0, flags, ret_pid); } -int namespace_fork(const char *outer_name, const char *inner_name, const int except_fds[], size_t n_except_fds, ForkFlags flags, int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd, pid_t *ret_pid); +int namespace_fork( + const char *outer_name, + const char *inner_name, + int except_fds[], + size_t n_except_fds, + ForkFlags flags, + int pidns_fd, + int mntns_fd, + int netns_fd, + int userns_fd, + int root_fd, + pid_t *ret_pid); int set_oom_score_adjust(int value); int get_oom_score_adjust(int *ret); diff --git a/src/libnm-systemd-shared/src/basic/signal-util.c b/src/libnm-systemd-shared/src/basic/signal-util.c index f8f4e509ad..661ad00b11 100644 --- a/src/libnm-systemd-shared/src/basic/signal-util.c +++ b/src/libnm-systemd-shared/src/basic/signal-util.c @@ -18,7 +18,7 @@ int reset_all_signal_handlers(void) { .sa_handler = SIG_DFL, .sa_flags = SA_RESTART, }; - int r = 0; + int ret = 0, r; for (int sig = 1; sig < _NSIG; sig++) { @@ -26,14 +26,14 @@ int reset_all_signal_handlers(void) { if (IN_SET(sig, SIGKILL, SIGSTOP)) continue; - /* On Linux the first two RT signals are reserved by - * glibc, and sigaction() will return EINVAL for them. */ - if (sigaction(sig, &sa, NULL) < 0) - if (errno != EINVAL && r >= 0) - r = -errno; + /* On Linux the first two RT signals are reserved by glibc, and sigaction() will return + * EINVAL for them. */ + r = RET_NERRNO(sigaction(sig, &sa, NULL)); + if (r != -EINVAL) + RET_GATHER(ret, r); } - return r; + return ret; } int reset_signal_mask(void) { @@ -57,10 +57,7 @@ int sigaction_many_internal(const struct sigaction *sa, ...) { if (sig == 0) continue; - if (sigaction(sig, sa, NULL) < 0) { - if (r >= 0) - r = -errno; - } + RET_GATHER(r, RET_NERRNO(sigaction(sig, sa, NULL))); } va_end(ap); @@ -87,7 +84,7 @@ static int sigset_add_many_ap(sigset_t *ss, va_list ap) { return r; } -int sigset_add_many(sigset_t *ss, ...) { +int sigset_add_many_internal(sigset_t *ss, ...) { va_list ap; int r; @@ -98,7 +95,7 @@ int sigset_add_many(sigset_t *ss, ...) { return r; } -int sigprocmask_many(int how, sigset_t *old, ...) { +int sigprocmask_many_internal(int how, sigset_t *old, ...) { va_list ap; sigset_t ss; int r; @@ -113,10 +110,7 @@ int sigprocmask_many(int how, sigset_t *old, ...) { if (r < 0) return r; - if (sigprocmask(how, &ss, old) < 0) - return -errno; - - return 0; + return RET_NERRNO(sigprocmask(how, &ss, old)); } static const char *const static_signal_table[] = { diff --git a/src/libnm-systemd-shared/src/basic/signal-util.h b/src/libnm-systemd-shared/src/basic/signal-util.h index ad2ba841c6..8826fbeb7b 100644 --- a/src/libnm-systemd-shared/src/basic/signal-util.h +++ b/src/libnm-systemd-shared/src/basic/signal-util.h @@ -31,8 +31,11 @@ int sigaction_many_internal(const struct sigaction *sa, ...); #define sigaction_many(sa, ...) \ sigaction_many_internal(sa, __VA_ARGS__, -1) -int sigset_add_many(sigset_t *ss, ...); -int sigprocmask_many(int how, sigset_t *old, ...); +int sigset_add_many_internal(sigset_t *ss, ...); +#define sigset_add_many(...) sigset_add_many_internal(__VA_ARGS__, -1) + +int sigprocmask_many_internal(int how, sigset_t *old, ...); +#define sigprocmask_many(...) sigprocmask_many_internal(__VA_ARGS__, -1) const char *signal_to_string(int i) _const_; int signal_from_string(const char *s) _pure_; @@ -46,7 +49,7 @@ static inline void block_signals_reset(sigset_t *ss) { #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); \ + assert_se(sigprocmask_many(SIG_BLOCK, &_t, __VA_ARGS__) >= 0); \ _t; \ }) diff --git a/src/libnm-systemd-shared/src/basic/stat-util.c b/src/libnm-systemd-shared/src/basic/stat-util.c index 51715668fe..ec6273c7d0 100644 --- a/src/libnm-systemd-shared/src/basic/stat-util.c +++ b/src/libnm-systemd-shared/src/basic/stat-util.c @@ -25,43 +25,130 @@ #include "stat-util.h" #include "string-util.h" -int is_symlink(const char *path) { - struct stat info; +static int verify_stat_at( + int fd, + const char *path, + bool follow, + int (*verify_func)(const struct stat *st), + bool verify) { - assert(path); + struct stat st; + int r; + + assert(fd >= 0 || fd == AT_FDCWD); + assert(!isempty(path) || !follow); + assert(verify_func); - if (lstat(path, &info) < 0) + if (fstatat(fd, strempty(path), &st, + (isempty(path) ? AT_EMPTY_PATH : 0) | (follow ? 0 : AT_SYMLINK_NOFOLLOW)) < 0) return -errno; - return !!S_ISLNK(info.st_mode); + r = verify_func(&st); + return verify ? r : r >= 0; } -int is_dir_full(int atfd, const char* path, bool follow) { - struct stat st; - int r; +int stat_verify_regular(const struct stat *st) { + assert(st); - assert(atfd >= 0 || atfd == AT_FDCWD); - assert(atfd >= 0 || path); + /* Checks whether the specified stat() structure refers to a regular file. If not returns an + * appropriate error code. */ - if (path) - r = fstatat(atfd, path, &st, follow ? 0 : AT_SYMLINK_NOFOLLOW); - else - r = fstat(atfd, &st); - if (r < 0) - return -errno; + if (S_ISDIR(st->st_mode)) + return -EISDIR; + + if (S_ISLNK(st->st_mode)) + return -ELOOP; + + if (!S_ISREG(st->st_mode)) + return -EBADFD; - return !!S_ISDIR(st.st_mode); + return 0; } -int is_device_node(const char *path) { - struct stat info; +int verify_regular_at(int fd, const char *path, bool follow) { + return verify_stat_at(fd, path, follow, stat_verify_regular, true); +} - assert(path); +int fd_verify_regular(int fd) { + assert(fd >= 0); + return verify_regular_at(fd, NULL, false); +} - if (lstat(path, &info) < 0) - return -errno; +int stat_verify_directory(const struct stat *st) { + assert(st); + + if (S_ISLNK(st->st_mode)) + return -ELOOP; + + if (!S_ISDIR(st->st_mode)) + return -ENOTDIR; + + return 0; +} + +int fd_verify_directory(int fd) { + assert(fd >= 0); + return verify_stat_at(fd, NULL, false, stat_verify_directory, true); +} + +int is_dir_at(int fd, const char *path, bool follow) { + return verify_stat_at(fd, path, follow, stat_verify_directory, false); +} + +int is_dir(const char *path, bool follow) { + assert(!isempty(path)); + return is_dir_at(AT_FDCWD, path, follow); +} + +int stat_verify_symlink(const struct stat *st) { + assert(st); + + if (S_ISDIR(st->st_mode)) + return -EISDIR; - return !!(S_ISBLK(info.st_mode) || S_ISCHR(info.st_mode)); + if (!S_ISLNK(st->st_mode)) + return -ENOLINK; + + return 0; +} + +int is_symlink(const char *path) { + assert(!isempty(path)); + return verify_stat_at(AT_FDCWD, path, false, stat_verify_symlink, false); +} + +int stat_verify_linked(const struct stat *st) { + assert(st); + + if (st->st_nlink <= 0) + return -EIDRM; /* recognizable error. */ + + return 0; +} + +int fd_verify_linked(int fd) { + assert(fd >= 0); + return verify_stat_at(fd, NULL, false, stat_verify_linked, true); +} + +int stat_verify_device_node(const struct stat *st) { + assert(st); + + if (S_ISLNK(st->st_mode)) + return -ELOOP; + + if (S_ISDIR(st->st_mode)) + return -EISDIR; + + if (!S_ISBLK(st->st_mode) && !S_ISCHR(st->st_mode)) + return -ENOTTY; + + return 0; +} + +int is_device_node(const char *path) { + assert(!isempty(path)); + return verify_stat_at(AT_FDCWD, path, false, stat_verify_device_node, false); } int dir_is_empty_at(int dir_fd, const char *path, bool ignore_hidden_or_backup) { @@ -260,70 +347,6 @@ int path_is_network_fs(const char *path) { return is_network_fs(&s); } -int stat_verify_regular(const struct stat *st) { - assert(st); - - /* Checks whether the specified stat() structure refers to a regular file. If not returns an appropriate error - * code. */ - - if (S_ISDIR(st->st_mode)) - return -EISDIR; - - if (S_ISLNK(st->st_mode)) - return -ELOOP; - - if (!S_ISREG(st->st_mode)) - return -EBADFD; - - return 0; -} - -int fd_verify_regular(int fd) { - struct stat st; - - assert(fd >= 0); - - if (fstat(fd, &st) < 0) - return -errno; - - return stat_verify_regular(&st); -} - -int verify_regular_at(int dir_fd, const char *path, bool follow) { - struct stat st; - - assert(dir_fd >= 0 || dir_fd == AT_FDCWD); - assert(path); - - if (fstatat(dir_fd, path, &st, (isempty(path) ? AT_EMPTY_PATH : 0) | (follow ? 0 : AT_SYMLINK_NOFOLLOW)) < 0) - return -errno; - - return stat_verify_regular(&st); -} - -int stat_verify_directory(const struct stat *st) { - assert(st); - - if (S_ISLNK(st->st_mode)) - return -ELOOP; - - if (!S_ISDIR(st->st_mode)) - return -ENOTDIR; - - return 0; -} - -int fd_verify_directory(int fd) { - struct stat st; - - assert(fd >= 0); - - if (fstat(fd, &st) < 0) - return -errno; - - return stat_verify_directory(&st); -} - int proc_mounted(void) { int r; @@ -468,7 +491,7 @@ int xstatfsat(int dir_fd, const char *path, struct statfs *ret) { assert(dir_fd >= 0 || dir_fd == AT_FDCWD); assert(ret); - fd = xopenat(dir_fd, path, O_PATH|O_CLOEXEC|O_NOCTTY, /* xopen_flags = */ 0, /* mode = */ 0); + fd = xopenat(dir_fd, path, O_PATH|O_CLOEXEC|O_NOCTTY); if (fd < 0) return fd; diff --git a/src/libnm-systemd-shared/src/basic/stat-util.h b/src/libnm-systemd-shared/src/basic/stat-util.h index dc11a85f62..47445d852a 100644 --- a/src/libnm-systemd-shared/src/basic/stat-util.h +++ b/src/libnm-systemd-shared/src/basic/stat-util.h @@ -14,14 +14,22 @@ #include "siphash24.h" #include "time-util.h" +int stat_verify_regular(const struct stat *st); +int verify_regular_at(int fd, const char *path, bool follow); +int fd_verify_regular(int fd); + +int stat_verify_directory(const struct stat *st); +int fd_verify_directory(int fd); +int is_dir_at(int fd, const char *path, bool follow); +int is_dir(const char *path, bool follow); + +int stat_verify_symlink(const struct stat *st); int is_symlink(const char *path); -int is_dir_full(int atfd, const char *fname, bool follow); -static inline int is_dir(const char *path, bool follow) { - return is_dir_full(AT_FDCWD, path, follow); -} -static inline int is_dir_fd(int fd) { - return is_dir_full(fd, NULL, false); -} + +int stat_verify_linked(const struct stat *st); +int fd_verify_linked(int fd); + +int stat_verify_device_node(const struct stat *st); int is_device_node(const char *path); int dir_is_empty_at(int dir_fd, const char *path, bool ignore_hidden_or_backup); @@ -72,13 +80,6 @@ int path_is_network_fs(const char *path); */ #define F_TYPE_EQUAL(a, b) (a == (typeof(a)) b) -int stat_verify_regular(const struct stat *st); -int fd_verify_regular(int fd); -int verify_regular_at(int dir_fd, const char *path, bool follow); - -int stat_verify_directory(const struct stat *st); -int fd_verify_directory(int fd); - int proc_mounted(void); bool stat_inode_same(const struct stat *a, const struct stat *b); diff --git a/src/libnm-systemd-shared/src/basic/string-util.c b/src/libnm-systemd-shared/src/basic/string-util.c index 2aac588118..c1e7e6e622 100644 --- a/src/libnm-systemd-shared/src/basic/string-util.c +++ b/src/libnm-systemd-shared/src/basic/string-util.c @@ -620,6 +620,9 @@ char *cellescape(char *buf, size_t len, const char *s) { char* strshorten(char *s, size_t l) { assert(s); + if (l >= SIZE_MAX-1) /* Would not change anything */ + return s; + if (strnlen(s, l+1) > l) s[l] = 0; diff --git a/src/libnm-systemd-shared/src/basic/strv.c b/src/libnm-systemd-shared/src/basic/strv.c index 72cbbfe2f4..208108d6c0 100644 --- a/src/libnm-systemd-shared/src/basic/strv.c +++ b/src/libnm-systemd-shared/src/basic/strv.c @@ -358,7 +358,7 @@ int strv_split_colon_pairs(char ***t, const char *s) { const char *p = tuple; r = extract_many_words(&p, ":", EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_SEPARATORS, - &first, &second, NULL); + &first, &second); if (r < 0) return r; if (r == 0) diff --git a/src/libnm-systemd-shared/src/basic/time-util.c b/src/libnm-systemd-shared/src/basic/time-util.c index 02123dc591..3601be25fb 100644 --- a/src/libnm-systemd-shared/src/basic/time-util.c +++ b/src/libnm-systemd-shared/src/basic/time-util.c @@ -1429,7 +1429,7 @@ static int get_timezones_from_zone1970_tab(char ***ret) { /* Line format is: * 'country codes' 'coordinates' 'timezone' 'comments' */ - r = extract_many_words(&p, NULL, 0, &cc, &co, &tz, NULL); + r = extract_many_words(&p, NULL, 0, &cc, &co, &tz); if (r < 0) continue; @@ -1474,7 +1474,7 @@ static int get_timezones_from_tzdata_zi(char ***ret) { * Link line format is: * 'Link' 'target' 'alias' * See 'man zic' for more detail. */ - r = extract_many_words(&p, NULL, 0, &type, &f1, &f2, NULL); + r = extract_many_words(&p, NULL, 0, &type, &f1, &f2); if (r < 0) continue; @@ -1573,7 +1573,7 @@ int verify_timezone(const char *name, int log_level) { r = fd_verify_regular(fd); if (r < 0) - return log_full_errno(log_level, r, "Timezone file '%s' is not a regular file: %m", t); + return log_full_errno(log_level, r, "Timezone file '%s' is not a regular file: %m", t); r = loop_read_exact(fd, buf, 4, false); if (r < 0) diff --git a/src/libnm-systemd-shared/src/fundamental/macro-fundamental.h b/src/libnm-systemd-shared/src/fundamental/macro-fundamental.h index 041649a03b..5ccbda5186 100644 --- a/src/libnm-systemd-shared/src/fundamental/macro-fundamental.h +++ b/src/libnm-systemd-shared/src/fundamental/macro-fundamental.h @@ -249,6 +249,30 @@ CONST_ISPOWEROF2(_x); \ })) +#define ADD_SAFE(ret, a, b) (!__builtin_add_overflow(a, b, ret)) +#define INC_SAFE(a, b) __INC_SAFE(UNIQ, a, b) +#define __INC_SAFE(q, a, b) \ + ({ \ + const typeof(a) UNIQ_T(A, q) = (a); \ + ADD_SAFE(UNIQ_T(A, q), *UNIQ_T(A, q), b); \ + }) + +#define SUB_SAFE(ret, a, b) (!__builtin_sub_overflow(a, b, ret)) +#define DEC_SAFE(a, b) __DEC_SAFE(UNIQ, a, b) +#define __DEC_SAFE(q, a, b) \ + ({ \ + const typeof(a) UNIQ_T(A, q) = (a); \ + SUB_SAFE(UNIQ_T(A, q), *UNIQ_T(A, q), b); \ + }) + +#define MUL_SAFE(ret, a, b) (!__builtin_mul_overflow(a, b, ret)) +#define MUL_ASSIGN_SAFE(a, b) __MUL_ASSIGN_SAFE(UNIQ, a, b) +#define __MUL_ASSIGN_SAFE(q, a, b) \ + ({ \ + const typeof(a) UNIQ_T(A, q) = (a); \ + MUL_SAFE(UNIQ_T(A, q), *UNIQ_T(A, q), b); \ + }) + #define LESS_BY(a, b) __LESS_BY(UNIQ, (a), UNIQ, (b)) #define __LESS_BY(aq, a, bq, b) \ ({ \ @@ -298,7 +322,7 @@ const typeof(y) UNIQ_T(A, q) = (y); \ const typeof(x) UNIQ_T(B, q) = DIV_ROUND_UP((x), UNIQ_T(A, q)); \ typeof(x) UNIQ_T(C, q); \ - __builtin_mul_overflow(UNIQ_T(B, q), UNIQ_T(A, q), &UNIQ_T(C, q)) ? (typeof(x)) -1 : UNIQ_T(C, q); \ + MUL_SAFE(&UNIQ_T(C, q), UNIQ_T(B, q), UNIQ_T(A, q)) ? UNIQ_T(C, q) : (typeof(x)) -1; \ }) #define ROUND_UP(x, y) __ROUND_UP(UNIQ, (x), (y)) diff --git a/src/libnm-systemd-shared/src/fundamental/sha256.c b/src/libnm-systemd-shared/src/fundamental/sha256.c deleted file mode 100644 index 4447ad8a66..0000000000 --- a/src/libnm-systemd-shared/src/fundamental/sha256.c +++ /dev/null @@ -1,278 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ - -/* Stolen from glibc and converted to our style. In glibc it comes with the following copyright blurb: */ - -/* Functions to compute SHA256 message digest of files or memory blocks. - according to the definition of SHA256 in FIPS 180-2. - Copyright (C) 2007-2022 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#include -#if SD_BOOT -# include "efi-string.h" -#else -# include -#endif - -#include "macro-fundamental.h" -#include "sha256.h" -#include "unaligned-fundamental.h" - -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -# define SWAP(n) \ - __builtin_bswap32(n) -# define SWAP64(n) \ - __builtin_bswap64(n) -#else -# define SWAP(n) (n) -# define SWAP64(n) (n) -#endif - -/* This array contains the bytes used to pad the buffer to the next - 64-byte boundary. (FIPS 180-2:5.1.1) */ -static const uint8_t fillbuf[64] = { - 0x80, 0 /* , 0, 0, ... */ -}; - -/* Constants for SHA256 from FIPS 180-2:4.2.2. */ -static const uint32_t K[64] = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, - 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, - 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, - 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, - 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, - 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 -}; - -static void sha256_process_block(const void *, size_t, struct sha256_ctx *); - -/* Initialize structure containing state of computation. - (FIPS 180-2:5.3.2) */ -void sha256_init_ctx(struct sha256_ctx *ctx) { - assert(ctx); - - ctx->H[0] = 0x6a09e667; - ctx->H[1] = 0xbb67ae85; - ctx->H[2] = 0x3c6ef372; - ctx->H[3] = 0xa54ff53a; - ctx->H[4] = 0x510e527f; - ctx->H[5] = 0x9b05688c; - ctx->H[6] = 0x1f83d9ab; - ctx->H[7] = 0x5be0cd19; - - ctx->total64 = 0; - ctx->buflen = 0; -} - -/* Process the remaining bytes in the internal buffer and the usual - prolog according to the standard and write the result to RESBUF. */ -uint8_t *sha256_finish_ctx(struct sha256_ctx *ctx, uint8_t resbuf[static SHA256_DIGEST_SIZE]) { - /* Take yet unprocessed bytes into account. */ - uint32_t bytes = ctx->buflen; - size_t pad; - - assert(ctx); - assert(resbuf); - - /* Now count remaining bytes. */ - ctx->total64 += bytes; - - pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes; - memcpy(&ctx->buffer[bytes], fillbuf, pad); - - /* Put the 64-bit file length in *bits* at the end of the buffer. */ - ctx->buffer32[(bytes + pad + 4) / 4] = SWAP(ctx->total[TOTAL64_low] << 3); - ctx->buffer32[(bytes + pad) / 4] = SWAP((ctx->total[TOTAL64_high] << 3) - | (ctx->total[TOTAL64_low] >> 29)); - - /* Process last bytes. */ - sha256_process_block(ctx->buffer, bytes + pad + 8, ctx); - - /* Put result from CTX in first 32 bytes following RESBUF. */ - for (size_t i = 0; i < 8; ++i) - unaligned_write_ne32(resbuf + i * sizeof(uint32_t), SWAP(ctx->H[i])); - return resbuf; -} - -void sha256_process_bytes(const void *buffer, size_t len, struct sha256_ctx *ctx) { - assert(buffer); - assert(ctx); - - /* When we already have some bits in our internal buffer concatenate - both inputs first. */ - - if (ctx->buflen != 0) { - size_t left_over = ctx->buflen; - size_t add = 128 - left_over > len ? len : 128 - left_over; - - memcpy(&ctx->buffer[left_over], buffer, add); - ctx->buflen += add; - - if (ctx->buflen > 64) { - sha256_process_block(ctx->buffer, ctx->buflen & ~63, ctx); - - ctx->buflen &= 63; - /* The regions in the following copy operation cannot overlap. */ - memcpy(ctx->buffer, &ctx->buffer[(left_over + add) & ~63], - ctx->buflen); - } - - buffer = (const char *) buffer + add; - len -= add; - } - - /* Process available complete blocks. */ - if (len >= 64) { - if (IS_ALIGNED32(buffer)) { - sha256_process_block(buffer, len & ~63, ctx); - buffer = (const char *) buffer + (len & ~63); - len &= 63; - } else - while (len > 64) { - memcpy(ctx->buffer, buffer, 64); - sha256_process_block(ctx->buffer, 64, ctx); - buffer = (const char *) buffer + 64; - len -= 64; - } - } - - /* Move remaining bytes into internal buffer. */ - if (len > 0) { - size_t left_over = ctx->buflen; - - memcpy(&ctx->buffer[left_over], buffer, len); - left_over += len; - if (left_over >= 64) { - sha256_process_block(ctx->buffer, 64, ctx); - left_over -= 64; - memcpy(ctx->buffer, &ctx->buffer[64], left_over); - } - ctx->buflen = left_over; - } -} - -/* Process LEN bytes of BUFFER, accumulating context into CTX. - It is assumed that LEN % 64 == 0. */ -static void sha256_process_block(const void *buffer, size_t len, struct sha256_ctx *ctx) { - const uint32_t *words = ASSERT_PTR(buffer); - size_t nwords = len / sizeof(uint32_t); - - assert(ctx); - - uint32_t a = ctx->H[0]; - uint32_t b = ctx->H[1]; - uint32_t c = ctx->H[2]; - uint32_t d = ctx->H[3]; - uint32_t e = ctx->H[4]; - uint32_t f = ctx->H[5]; - uint32_t g = ctx->H[6]; - uint32_t h = ctx->H[7]; - - /* First increment the byte count. FIPS 180-2 specifies the possible - length of the file up to 2^64 bits. Here we only compute the - number of bytes. */ - ctx->total64 += len; - - /* Process all bytes in the buffer with 64 bytes in each round of - the loop. */ - while (nwords > 0) { - uint32_t W[64]; - uint32_t a_save = a; - uint32_t b_save = b; - uint32_t c_save = c; - uint32_t d_save = d; - uint32_t e_save = e; - uint32_t f_save = f; - uint32_t g_save = g; - uint32_t h_save = h; - - /* Operators defined in FIPS 180-2:4.1.2. */ -#define Ch(x, y, z) ((x & y) ^ (~x & z)) -#define Maj(x, y, z) ((x & y) ^ (x & z) ^ (y & z)) -#define S0(x) (CYCLIC (x, 2) ^ CYCLIC (x, 13) ^ CYCLIC (x, 22)) -#define S1(x) (CYCLIC (x, 6) ^ CYCLIC (x, 11) ^ CYCLIC (x, 25)) -#define R0(x) (CYCLIC (x, 7) ^ CYCLIC (x, 18) ^ (x >> 3)) -#define R1(x) (CYCLIC (x, 17) ^ CYCLIC (x, 19) ^ (x >> 10)) - - /* It is unfortunate that C does not provide an operator for - cyclic rotation. Hope the C compiler is smart enough. */ -#define CYCLIC(w, s) ((w >> s) | (w << (32 - s))) - - /* Compute the message schedule according to FIPS 180-2:6.2.2 step 2. */ - for (size_t t = 0; t < 16; ++t) { - W[t] = SWAP (*words); - ++words; - } - for (size_t t = 16; t < 64; ++t) - W[t] = R1 (W[t - 2]) + W[t - 7] + R0 (W[t - 15]) + W[t - 16]; - - /* The actual computation according to FIPS 180-2:6.2.2 step 3. */ - for (size_t t = 0; t < 64; ++t) { - uint32_t T1 = h + S1 (e) + Ch (e, f, g) + K[t] + W[t]; - uint32_t T2 = S0 (a) + Maj (a, b, c); - h = g; - g = f; - f = e; - e = d + T1; - d = c; - c = b; - b = a; - a = T1 + T2; - } - - /* Add the starting values of the context according to FIPS 180-2:6.2.2 - step 4. */ - a += a_save; - b += b_save; - c += c_save; - d += d_save; - e += e_save; - f += f_save; - g += g_save; - h += h_save; - - /* Prepare for the next round. */ - nwords -= 16; - } - - /* Put checksum in context given as argument. */ - ctx->H[0] = a; - ctx->H[1] = b; - ctx->H[2] = c; - ctx->H[3] = d; - ctx->H[4] = e; - ctx->H[5] = f; - ctx->H[6] = g; - ctx->H[7] = h; -} - -uint8_t* sha256_direct(const void *buffer, size_t sz, uint8_t result[static SHA256_DIGEST_SIZE]) { - struct sha256_ctx ctx; - sha256_init_ctx(&ctx); - sha256_process_bytes(buffer, sz, &ctx); - return sha256_finish_ctx(&ctx, result); -} diff --git a/src/libnm-systemd-shared/src/fundamental/sha256.h b/src/libnm-systemd-shared/src/fundamental/sha256.h deleted file mode 100644 index dbb08e35e5..0000000000 --- a/src/libnm-systemd-shared/src/fundamental/sha256.h +++ /dev/null @@ -1,39 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -#pragma once - -#include -#include - -#define SHA256_DIGEST_SIZE 32 - -struct sha256_ctx { - uint32_t H[8]; - - union { - uint64_t total64; -#define TOTAL64_low (1 - (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) -#define TOTAL64_high (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) - uint32_t total[2]; - }; - - uint32_t buflen; - - union { - uint8_t buffer[128]; /* NB: always correctly aligned for UINT32. */ - uint32_t buffer32[32]; - uint64_t buffer64[16]; - }; -}; - -void sha256_init_ctx(struct sha256_ctx *ctx); -uint8_t *sha256_finish_ctx(struct sha256_ctx *ctx, uint8_t resbuf[static SHA256_DIGEST_SIZE]); -void sha256_process_bytes(const void *buffer, size_t len, struct sha256_ctx *ctx); - -static inline void sha256_process_bytes_and_size(const void *buffer, size_t len, struct sha256_ctx *ctx) { - sha256_process_bytes(&len, sizeof(len), ctx); - sha256_process_bytes(buffer, len, ctx); -} - -uint8_t* sha256_direct(const void *buffer, size_t sz, uint8_t result[static SHA256_DIGEST_SIZE]); - -#define SHA256_DIRECT(buffer, sz) sha256_direct(buffer, sz, (uint8_t[SHA256_DIGEST_SIZE]) {}) -- cgit v1.2.3