diff --git a/shared/systemd/sd-adapt-shared/nm-sd-adapt-shared.h b/shared/systemd/sd-adapt-shared/nm-sd-adapt-shared.h index 5a28cdfc0..c11315a53 100644 --- a/shared/systemd/sd-adapt-shared/nm-sd-adapt-shared.h +++ b/shared/systemd/sd-adapt-shared/nm-sd-adapt-shared.h @@ -88,6 +88,8 @@ G_STMT_START { \ #define ENABLE_GSHADOW FALSE +#define HAVE_SECCOMP 0 + /*****************************************************************************/ /* systemd cannot be compiled with "-Wdeclaration-after-statement". In particular diff --git a/shared/systemd/src/basic/env-file.c b/shared/systemd/src/basic/env-file.c index 30ee135ad..1e93f18e3 100644 --- a/shared/systemd/src/basic/env-file.c +++ b/shared/systemd/src/basic/env-file.c @@ -211,17 +211,21 @@ static int parse_env_file_internal( case DOUBLE_QUOTE_VALUE_ESCAPE: state = DOUBLE_QUOTE_VALUE; - if (c == '"') { + if (strchr(SHELL_NEED_ESCAPE, c)) { + /* If this is a char that needs escaping, just unescape it. */ if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) return -ENOMEM; - value[n_value++] = '"'; - } else if (!strchr(NEWLINE, c)) { + value[n_value++] = c; + } else if (c != '\n') { + /* If other char than what needs escaping, keep the "\" in place, like the + * real shell does. */ if (!GREEDY_REALLOC(value, value_alloc, n_value+3)) return -ENOMEM; value[n_value++] = '\\'; value[n_value++] = c; } + /* Escaped newlines (aka "continuation lines") are eaten up entirely */ break; case COMMENT: diff --git a/shared/systemd/src/basic/env-util.c b/shared/systemd/src/basic/env-util.c index d16890d97..11f4b29ba 100644 --- a/shared/systemd/src/basic/env-util.c +++ b/shared/systemd/src/basic/env-util.c @@ -690,7 +690,7 @@ char **replace_env_argv(char **argv, char **env) { if (e) { int r; - r = strv_split_extract(&m, e, WHITESPACE, EXTRACT_RELAX|EXTRACT_UNQUOTE); + r = strv_split_full(&m, e, WHITESPACE, EXTRACT_RELAX|EXTRACT_UNQUOTE); if (r < 0) { ret[k] = NULL; strv_free(ret); @@ -744,7 +744,6 @@ int getenv_bool(const char *p) { return parse_boolean(e); } -#if 0 /* NM_IGNORED */ int getenv_bool_secure(const char *p) { const char *e; @@ -754,4 +753,3 @@ int getenv_bool_secure(const char *p) { return parse_boolean(e); } -#endif /* NM_IGNORED */ diff --git a/shared/systemd/src/basic/escape.c b/shared/systemd/src/basic/escape.c index 1ea0b6a64..1261fd488 100644 --- a/shared/systemd/src/basic/escape.c +++ b/shared/systemd/src/basic/escape.c @@ -77,7 +77,7 @@ int cescape_char(char c, char *buf) { return buf - buf_old; } -char *cescape_length(const char *s, size_t n) { +char* cescape_length(const char *s, size_t n) { const char *f; char *r, *t; @@ -98,7 +98,7 @@ char *cescape_length(const char *s, size_t n) { return r; } -char *cescape(const char *s) { +char* cescape(const char *s) { assert(s); return cescape_length(s, strlen(s)); @@ -363,7 +363,7 @@ int cunescape_length_with_prefix(const char *s, size_t length, const char *prefi return t - r; } -char *xescape_full(const char *s, const char *bad, size_t console_width, bool eight_bits) { +char* xescape_full(const char *s, const char *bad, size_t console_width, bool eight_bits) { char *ans, *t, *prev, *prev2; const char *f; @@ -430,7 +430,7 @@ char *xescape_full(const char *s, const char *bad, size_t console_width, bool ei return ans; } -char *escape_non_printable_full(const char *str, size_t console_width, bool eight_bit) { +char* escape_non_printable_full(const char *str, size_t console_width, bool eight_bit) { if (eight_bit) return xescape_full(str, "", console_width, true); else @@ -438,7 +438,7 @@ char *escape_non_printable_full(const char *str, size_t console_width, bool eigh } #endif /* NM_IGNORED */ -char *octescape(const char *s, size_t len) { +char* octescape(const char *s, size_t len) { char *r, *t; const char *f; @@ -466,7 +466,7 @@ char *octescape(const char *s, size_t len) { } -static char *strcpy_backslash_escaped(char *t, const char *s, const char *bad, bool escape_tab_nl) { +static char* strcpy_backslash_escaped(char *t, const char *s, const char *bad, bool escape_tab_nl) { assert(bad); for (; *s; s++) { @@ -485,7 +485,7 @@ static char *strcpy_backslash_escaped(char *t, const char *s, const char *bad, b return t; } -char *shell_escape(const char *s, const char *bad) { +char* shell_escape(const char *s, const char *bad) { char *r, *t; r = new(char, strlen(s)*2+1); diff --git a/shared/systemd/src/basic/escape.h b/shared/systemd/src/basic/escape.h index 0b00b116e..fa267813b 100644 --- a/shared/systemd/src/basic/escape.h +++ b/shared/systemd/src/basic/escape.h @@ -43,8 +43,8 @@ typedef enum EscapeStyle { * syntax (a string enclosed in $'') instead of plain quotes. */ } EscapeStyle; -char *cescape(const char *s); -char *cescape_length(const char *s, size_t n); +char* cescape(const char *s); +char* cescape_length(const char *s, size_t n); int cescape_char(char c, char *buf); int cunescape_length_with_prefix(const char *s, size_t length, const char *prefix, UnescapeFlags flags, char **ret); @@ -56,12 +56,12 @@ static inline int cunescape(const char *s, UnescapeFlags flags, char **ret) { } int cunescape_one(const char *p, size_t length, char32_t *ret, bool *eight_bit, bool accept_nul); -char *xescape_full(const char *s, const char *bad, size_t console_width, bool eight_bits); -static inline char *xescape(const char *s, const char *bad) { +char* xescape_full(const char *s, const char *bad, size_t console_width, bool eight_bits); +static inline char* xescape(const char *s, const char *bad) { return xescape_full(s, bad, SIZE_MAX, false); } -char *octescape(const char *s, size_t len); -char *escape_non_printable_full(const char *str, size_t console_width, bool eight_bit); +char* octescape(const char *s, size_t len); +char* escape_non_printable_full(const char *str, size_t console_width, bool eight_bit); -char *shell_escape(const char *s, const char *bad); +char* shell_escape(const char *s, const char *bad); char* shell_maybe_quote(const char *s, EscapeStyle style); diff --git a/shared/systemd/src/basic/extract-word.c b/shared/systemd/src/basic/extract-word.c index 72ad0490a..e32b4c7f7 100644 --- a/shared/systemd/src/basic/extract-word.c +++ b/shared/systemd/src/basic/extract-word.c @@ -16,6 +16,7 @@ #include "log.h" #include "macro.h" #include "string-util.h" +#include "strv.h" #include "utf8.h" int extract_first_word(const char **p, char **ret, const char *separators, ExtractFlags flags) { diff --git a/shared/systemd/src/basic/fd-util.c b/shared/systemd/src/basic/fd-util.c index a401663e2..525d38280 100644 --- a/shared/systemd/src/basic/fd-util.c +++ b/shared/systemd/src/basic/fd-util.c @@ -379,6 +379,7 @@ bool fdname_is_valid(const char *s) { return p - s < 256; } +#if 0 /* NM_IGNORED */ int fd_get_path(int fd, char **ret) { char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)]; int r; @@ -389,18 +390,15 @@ int fd_get_path(int fd, char **ret) { /* ENOENT can mean two things: that the fd does not exist or that /proc is not mounted. Let's make * things debuggable and distinguish the two. */ - if (access("/proc/self/fd/", F_OK) < 0) - /* /proc is not available or not set up properly, we're most likely in some chroot - * environment. */ - return errno == ENOENT ? -EOPNOTSUPP : -errno; - + if (proc_mounted() == 0) + return -ENOSYS; /* /proc is not available or not set up properly, we're most likely in some chroot + * environment. */ return -EBADF; /* The directory exists, hence it's the fd that doesn't. */ } return r; } -#if 0 /* NM_IGNORED */ int move_fd(int from, int to, int cloexec) { int r; @@ -736,8 +734,7 @@ int fd_duplicate_data_fd(int fd) { if (f != 0) return -errno; - safe_close(copy_fd); - copy_fd = TAKE_FD(tmp_fd); + CLOSE_AND_REPLACE(copy_fd, tmp_fd); remains = mfree(remains); remains_size = 0; @@ -872,8 +869,7 @@ int rearrange_stdio(int original_input_fd, int original_output_fd, int original_ goto finish; } - safe_close(null_fd); - null_fd = copy; + CLOSE_AND_REPLACE(null_fd, copy); } } @@ -983,7 +979,7 @@ int read_nr_open(void) { return v; } - /* If we fail, fallback to the hard-coded kernel limit of 1024 * 1024. */ + /* If we fail, fall back to the hard-coded kernel limit of 1024 * 1024. */ return 1024 * 1024; } #endif /* NM_IGNORED */ diff --git a/shared/systemd/src/basic/fd-util.h b/shared/systemd/src/basic/fd-util.h index e490753ca..93ce95cd0 100644 --- a/shared/systemd/src/basic/fd-util.h +++ b/shared/systemd/src/basic/fd-util.h @@ -93,6 +93,16 @@ static inline int make_null_stdio(void) { _fd_; \ }) +/* Like free_and_replace(), but for file descriptors */ +#define CLOSE_AND_REPLACE(a, b) \ + ({ \ + int *_fdp_ = &(a); \ + safe_close(*_fdp_); \ + *_fdp_ = TAKE_FD(b); \ + 0; \ + }) + + int fd_reopen(int fd, int flags); int read_nr_open(void); diff --git a/shared/systemd/src/basic/fs-util.c b/shared/systemd/src/basic/fs-util.c index a1f6380f3..1ababf8eb 100644 --- a/shared/systemd/src/basic/fs-util.c +++ b/shared/systemd/src/basic/fs-util.c @@ -123,7 +123,7 @@ int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char if (!IN_SET(errno, EINVAL, ENOSYS, ENOTTY, EPERM)) /* FAT returns EPERM on link()… */ return -errno; - /* OK, neither RENAME_NOREPLACE nor linkat()+unlinkat() worked. Let's then fallback to the racy TOCTOU + /* OK, neither RENAME_NOREPLACE nor linkat()+unlinkat() worked. Let's then fall back to the racy TOCTOU * vulnerable accessat(F_OK) check followed by classic, replacing renameat(), we have nothing better. */ if (faccessat(newdirfd, newpath, F_OK, AT_SYMLINK_NOFOLLOW) >= 0) @@ -234,6 +234,7 @@ int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) { int fchmod_and_chown(int fd, mode_t mode, uid_t uid, gid_t gid) { bool do_chown, do_chmod; struct stat st; + int r; /* Change ownership and access mode of the specified fd. Tries to do so safely, ensuring that at no * point in time the access mode is above the old access mode under the old ownership or the new @@ -264,65 +265,23 @@ int fchmod_and_chown(int fd, mode_t mode, uid_t uid, gid_t gid) { if (do_chown && do_chmod) { mode_t minimal = st.st_mode & mode; /* the subset of the old and the new mask */ - if (((minimal ^ st.st_mode) & 07777) != 0) - if (fchmod_opath(fd, minimal & 07777) < 0) - return -errno; + if (((minimal ^ st.st_mode) & 07777) != 0) { + r = fchmod_opath(fd, minimal & 07777); + if (r < 0) + return r; + } } if (do_chown) if (fchownat(fd, "", uid, gid, AT_EMPTY_PATH) < 0) return -errno; - if (do_chmod) - if (fchmod_opath(fd, mode & 07777) < 0) - return -errno; - - return do_chown || do_chmod; -} - -int chmod_and_chown_unsafe(const char *path, mode_t mode, uid_t uid, gid_t gid) { - bool do_chown, do_chmod; - struct stat st; - - assert(path); - - /* Change ownership and access mode of the specified path, see description of fchmod_and_chown(). - * Should only be used on trusted paths. */ - - if (lstat(path, &st) < 0) - return -errno; - - do_chown = - (uid != UID_INVALID && st.st_uid != uid) || - (gid != GID_INVALID && st.st_gid != gid); - - do_chmod = - !S_ISLNK(st.st_mode) && /* chmod is not defined on symlinks */ - ((mode != MODE_INVALID && ((st.st_mode ^ mode) & 07777) != 0) || - do_chown); /* If we change ownership, make sure we reset the mode afterwards, since chown() - * modifies the access mode too */ - - if (mode == MODE_INVALID) - mode = st.st_mode; /* If we only shall do a chown(), save original mode, since chown() might break it. */ - else if ((mode & S_IFMT) != 0 && ((mode ^ st.st_mode) & S_IFMT) != 0) - return -EINVAL; /* insist on the right file type if it was specified */ - - if (do_chown && do_chmod) { - mode_t minimal = st.st_mode & mode; /* the subset of the old and the new mask */ - - if (((minimal ^ st.st_mode) & 07777) != 0) - if (chmod(path, minimal & 07777) < 0) - return -errno; + if (do_chmod) { + r = fchmod_opath(fd, mode & 07777); + if (r < 0) + return r; } - if (do_chown) - if (lchown(path, uid, gid) < 0) - return -errno; - - if (do_chmod) - if (chmod(path, mode & 07777) < 0) - return -errno; - return do_chown || do_chmod; } @@ -771,7 +730,7 @@ static int log_unsafe_transition(int a, int b, const char *path, unsigned flags) return log_warning_errno(SYNTHETIC_ERRNO(ENOLINK), "Detected unsafe path transition %s %s %s during canonicalization of %s.", - n1, special_glyph(SPECIAL_GLYPH_ARROW), n2, path); + strna(n1), special_glyph(SPECIAL_GLYPH_ARROW), strna(n2), path); } static int log_autofs_mount_point(int fd, const char *path, unsigned flags) { @@ -784,7 +743,7 @@ static int log_autofs_mount_point(int fd, const char *path, unsigned flags) { return log_warning_errno(SYNTHETIC_ERRNO(EREMOTE), "Detected autofs mount point %s during canonicalization of %s.", - n1, path); + strna(n1), path); } int chase_symlinks(const char *path, const char *original_root, unsigned flags, char **ret_path, int *ret_fd) { @@ -1304,16 +1263,25 @@ int chase_symlinks_and_stat( 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; + if (access(p, mode) < 0) { + if (errno != ENOENT) + return -errno; - return r; + /* ENOENT can mean two things: that the fd does not exist or that /proc is not mounted. Let's + * make things debuggable and distinguish the two. */ + + if (proc_mounted() == 0) + return -ENOSYS; /* /proc is not available or not set up properly, we're most likely in some chroot + * environment. */ + + return -EBADF; /* The directory exists, hence it's the fd that doesn't. */ + } + + return 0; } void unlink_tempfilep(char (*p)[]) { @@ -1434,6 +1402,7 @@ int unlinkat_deallocate(int fd, const char *name, UnlinkDeallocateFlags flags) { return 0; } +#if 0 /* NM_IGNORED */ int fsync_directory_of_file(int fd) { _cleanup_free_ char *path = NULL; _cleanup_close_ int dfd = -1; @@ -1447,9 +1416,9 @@ int fsync_directory_of_file(int fd) { if (r < 0) { log_debug_errno(r, "Failed to query /proc/self/fd/%d%s: %m", fd, - r == -EOPNOTSUPP ? ", ignoring" : ""); + r == -ENOSYS ? ", ignoring" : ""); - if (r == -EOPNOTSUPP) + if (r == -ENOSYS) /* 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. */ @@ -1470,6 +1439,7 @@ int fsync_directory_of_file(int fd) { return 0; } +#endif /* NM_IGNORED */ int fsync_full(int fd) { int r, q; diff --git a/shared/systemd/src/basic/fs-util.h b/shared/systemd/src/basic/fs-util.h index b184570f9..eb6e1eee4 100644 --- a/shared/systemd/src/basic/fs-util.h +++ b/shared/systemd/src/basic/fs-util.h @@ -34,7 +34,6 @@ int readlink_and_make_absolute(const char *p, char **r); int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid); int fchmod_and_chown(int fd, mode_t mode, uid_t uid, gid_t gid); -int chmod_and_chown_unsafe(const char *path, mode_t mode, uid_t uid, gid_t gid); int fchmod_umask(int fd, mode_t mode); int fchmod_opath(int fd, mode_t m); diff --git a/shared/systemd/src/basic/hashmap.c b/shared/systemd/src/basic/hashmap.c index db62ec790..b57814e69 100644 --- a/shared/systemd/src/basic/hashmap.c +++ b/shared/systemd/src/basic/hashmap.c @@ -3,6 +3,7 @@ #include "nm-sd-adapt-shared.h" #include +#include #include #include @@ -21,7 +22,6 @@ #include "strv.h" #if ENABLE_DEBUG_HASHMAP -#include #include "list.h" #endif @@ -191,7 +191,6 @@ assert_cc(DIRECT_BUCKETS(struct set_entry) < (1 << 3)); * a handful of directly stored entries in a hashmap. When a hashmap * outgrows direct storage, it gets its own key for indirect storage. */ static uint8_t shared_hash_key[HASH_KEY_SIZE]; -static bool shared_hash_key_initialized; /* Fields that all hashmap/set types must have */ struct HashmapBase { @@ -325,12 +324,12 @@ static void n_entries_dec(HashmapBase *h) { h->n_direct_entries--; } -static void *storage_ptr(HashmapBase *h) { +static void* storage_ptr(HashmapBase *h) { return h->has_indirect ? h->indirect.storage : h->direct.storage; } -static uint8_t *hash_key(HashmapBase *h) { +static uint8_t* hash_key(HashmapBase *h) { return h->has_indirect ? h->indirect.hash_key : shared_hash_key; } @@ -373,16 +372,16 @@ static void get_hash_key(uint8_t hash_key[HASH_KEY_SIZE], bool reuse_is_ok) { memcpy(hash_key, current, sizeof(current)); } -static struct hashmap_base_entry *bucket_at(HashmapBase *h, unsigned idx) { +static struct hashmap_base_entry* bucket_at(HashmapBase *h, unsigned idx) { return (struct hashmap_base_entry*) ((uint8_t*) storage_ptr(h) + idx * hashmap_type_info[h->type].entry_size); } -static struct plain_hashmap_entry *plain_bucket_at(Hashmap *h, unsigned idx) { +static struct plain_hashmap_entry* plain_bucket_at(Hashmap *h, unsigned idx) { return (struct plain_hashmap_entry*) bucket_at(HASHMAP_BASE(h), idx); } -static struct ordered_hashmap_entry *ordered_bucket_at(OrderedHashmap *h, unsigned idx) { +static struct ordered_hashmap_entry* ordered_bucket_at(OrderedHashmap *h, unsigned idx) { return (struct ordered_hashmap_entry*) bucket_at(HASHMAP_BASE(h), idx); } @@ -390,13 +389,13 @@ static struct set_entry *set_bucket_at(Set *h, unsigned idx) { return (struct set_entry*) bucket_at(HASHMAP_BASE(h), idx); } -static struct ordered_hashmap_entry *bucket_at_swap(struct swap_entries *swap, unsigned idx) { +static struct ordered_hashmap_entry* bucket_at_swap(struct swap_entries *swap, unsigned idx) { return &swap->e[idx - _IDX_SWAP_BEGIN]; } /* Returns a pointer to the bucket at index idx. * Understands real indexes and swap indexes, hence "_virtual". */ -static struct hashmap_base_entry *bucket_at_virtual(HashmapBase *h, struct swap_entries *swap, +static struct hashmap_base_entry* bucket_at_virtual(HashmapBase *h, struct swap_entries *swap, unsigned idx) { if (idx < _IDX_SWAP_BEGIN) return bucket_at(h, idx); @@ -407,7 +406,7 @@ static struct hashmap_base_entry *bucket_at_virtual(HashmapBase *h, struct swap_ assert_not_reached("Invalid index"); } -static dib_raw_t *dib_raw_ptr(HashmapBase *h) { +static dib_raw_t* dib_raw_ptr(HashmapBase *h) { return (dib_raw_t*) ((uint8_t*) storage_ptr(h) + hashmap_type_info[h->type].entry_size * n_buckets(h)); } @@ -505,7 +504,7 @@ static unsigned prev_idx(HashmapBase *h, unsigned idx) { return (n_buckets(h) + idx - 1U) % n_buckets(h); } -static void *entry_value(HashmapBase *h, struct hashmap_base_entry *e) { +static void* entry_value(HashmapBase *h, struct hashmap_base_entry *e) { switch (h->type) { case HASHMAP_TYPE_PLAIN: @@ -732,16 +731,12 @@ bool _hashmap_iterate(HashmapBase *h, Iterator *i, void **value, const void **ke return true; } -bool set_iterate(const Set *s, Iterator *i, void **value) { - return _hashmap_iterate(HASHMAP_BASE((Set*) s), i, value, NULL); -} - #define HASHMAP_FOREACH_IDX(idx, h, i) \ for ((i) = ITERATOR_FIRST, (idx) = hashmap_iterate_entry((h), &(i)); \ (idx != IDX_NIL); \ (idx) = hashmap_iterate_entry((h), &(i))) -IteratedCache *_hashmap_iterated_cache_new(HashmapBase *h) { +IteratedCache* _hashmap_iterated_cache_new(HashmapBase *h) { IteratedCache *cache; assert(h); @@ -770,7 +765,11 @@ static void reset_direct_storage(HashmapBase *h) { memset(p, DIB_RAW_INIT, sizeof(dib_raw_t) * hi->n_direct_buckets); } -static struct HashmapBase *hashmap_base_new(const struct hash_ops *hash_ops, enum HashmapType type HASHMAP_DEBUG_PARAMS) { +static void shared_hash_key_initialize(void) { + random_bytes(shared_hash_key, sizeof(shared_hash_key)); +} + +static struct HashmapBase* hashmap_base_new(const struct hash_ops *hash_ops, enum HashmapType type HASHMAP_DEBUG_PARAMS) { HashmapBase *h; const struct hashmap_type_info *hi = &hashmap_type_info[type]; bool up; @@ -792,10 +791,8 @@ static struct HashmapBase *hashmap_base_new(const struct hash_ops *hash_ops, enu reset_direct_storage(h); - if (!shared_hash_key_initialized) { - random_bytes(shared_hash_key, sizeof(shared_hash_key)); - shared_hash_key_initialized= true; - } + static pthread_once_t once = PTHREAD_ONCE_INIT; + assert_se(pthread_once(&once, shared_hash_key_initialize) == 0); #if ENABLE_DEBUG_HASHMAP h->debug.func = func; @@ -850,6 +847,16 @@ int _set_ensure_allocated(Set **s, const struct hash_ops *hash_ops HASHMAP_DEBU return hashmap_base_ensure_allocated((HashmapBase**)s, hash_ops, HASHMAP_TYPE_SET HASHMAP_DEBUG_PASS_ARGS); } +int _ordered_hashmap_ensure_put(OrderedHashmap **h, const struct hash_ops *hash_ops, const void *key, void *value HASHMAP_DEBUG_PARAMS) { + int r; + + r = _ordered_hashmap_ensure_allocated(h, hash_ops HASHMAP_DEBUG_PASS_ARGS); + if (r < 0) + return r; + + return ordered_hashmap_put(*h, key, value); +} + static void hashmap_free_no_clear(HashmapBase *h) { assert(!h->has_indirect); assert(h->n_direct_entries == 0); @@ -868,7 +875,7 @@ static void hashmap_free_no_clear(HashmapBase *h) { free(h); } -HashmapBase *_hashmap_free(HashmapBase *h, free_func_t default_free_key, free_func_t default_free_value) { +HashmapBase* _hashmap_free(HashmapBase *h, free_func_t default_free_key, free_func_t default_free_value) { if (h) { _hashmap_clear(h, default_free_key, default_free_value); hashmap_free_no_clear(h); @@ -1325,7 +1332,7 @@ int hashmap_update(Hashmap *h, const void *key, void *value) { return 0; } -void *_hashmap_get(HashmapBase *h, const void *key) { +void* _hashmap_get(HashmapBase *h, const void *key) { struct hashmap_base_entry *e; unsigned hash, idx; @@ -1341,7 +1348,7 @@ void *_hashmap_get(HashmapBase *h, const void *key) { return entry_value(h, e); } -void *hashmap_get2(Hashmap *h, const void *key, void **key2) { +void* hashmap_get2(Hashmap *h, const void *key, void **key2) { struct plain_hashmap_entry *e; unsigned hash, idx; @@ -1370,7 +1377,7 @@ bool _hashmap_contains(HashmapBase *h, const void *key) { return bucket_scan(h, hash, key) != IDX_NIL; } -void *_hashmap_remove(HashmapBase *h, const void *key) { +void* _hashmap_remove(HashmapBase *h, const void *key) { struct hashmap_base_entry *e; unsigned hash, idx; void *data; @@ -1390,7 +1397,7 @@ void *_hashmap_remove(HashmapBase *h, const void *key) { return data; } -void *hashmap_remove2(Hashmap *h, const void *key, void **rkey) { +void* hashmap_remove2(Hashmap *h, const void *key, void **rkey) { struct plain_hashmap_entry *e; unsigned hash, idx; void *data; @@ -1508,7 +1515,7 @@ int hashmap_remove_and_replace(Hashmap *h, const void *old_key, const void *new_ return 0; } -void *_hashmap_remove_value(HashmapBase *h, const void *key, void *value) { +void* _hashmap_remove_value(HashmapBase *h, const void *key, void *value) { struct hashmap_base_entry *e; unsigned hash, idx; @@ -1538,7 +1545,7 @@ static unsigned find_first_entry(HashmapBase *h) { return hashmap_iterate_entry(h, &i); } -void *_hashmap_first_key_and_value(HashmapBase *h, bool remove, void **ret_key) { +void* _hashmap_first_key_and_value(HashmapBase *h, bool remove, void **ret_key) { struct hashmap_base_entry *e; void *key, *data; unsigned idx; @@ -1713,7 +1720,7 @@ int _hashmap_move_one(HashmapBase *h, HashmapBase *other, const void *key) { return 0; } -HashmapBase *_hashmap_copy(HashmapBase *h HASHMAP_DEBUG_PARAMS) { +HashmapBase* _hashmap_copy(HashmapBase *h HASHMAP_DEBUG_PARAMS) { HashmapBase *copy; int r; @@ -1741,7 +1748,7 @@ HashmapBase *_hashmap_copy(HashmapBase *h HASHMAP_DEBUG_PARAMS) { return copy; } -char **_hashmap_get_strv(HashmapBase *h) { +char** _hashmap_get_strv(HashmapBase *h) { char **sv; Iterator i; unsigned idx, n; @@ -1758,7 +1765,7 @@ char **_hashmap_get_strv(HashmapBase *h) { return sv; } -void *ordered_hashmap_next(OrderedHashmap *h, const void *key) { +void* ordered_hashmap_next(OrderedHashmap *h, const void *key) { struct ordered_hashmap_entry *e; unsigned hash, idx; @@ -1965,7 +1972,7 @@ int iterated_cache_get(IteratedCache *cache, const void ***res_keys, const void return 0; } -IteratedCache *iterated_cache_free(IteratedCache *cache) { +IteratedCache* iterated_cache_free(IteratedCache *cache) { if (cache) { free(cache->keys.ptr); free(cache->values.ptr); diff --git a/shared/systemd/src/basic/hashmap.h b/shared/systemd/src/basic/hashmap.h index 600944162..890f90a9d 100644 --- a/shared/systemd/src/basic/hashmap.h +++ b/shared/systemd/src/basic/hashmap.h @@ -83,8 +83,8 @@ typedef struct { # define HASHMAP_DEBUG_PASS_ARGS #endif -Hashmap *_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS); -OrderedHashmap *_ordered_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS); +Hashmap* _hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS); +OrderedHashmap* _ordered_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS); #define hashmap_new(ops) _hashmap_new(ops HASHMAP_DEBUG_SRC_ARGS) #define ordered_hashmap_new(ops) _ordered_hashmap_new(ops HASHMAP_DEBUG_SRC_ARGS) @@ -96,39 +96,39 @@ OrderedHashmap *_ordered_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DE 0; \ }) -HashmapBase *_hashmap_free(HashmapBase *h, free_func_t default_free_key, free_func_t default_free_value); -static inline Hashmap *hashmap_free(Hashmap *h) { +HashmapBase* _hashmap_free(HashmapBase *h, free_func_t default_free_key, free_func_t default_free_value); +static inline Hashmap* hashmap_free(Hashmap *h) { return (void*) _hashmap_free(HASHMAP_BASE(h), NULL, NULL); } -static inline OrderedHashmap *ordered_hashmap_free(OrderedHashmap *h) { +static inline OrderedHashmap* ordered_hashmap_free(OrderedHashmap *h) { return (void*) _hashmap_free(HASHMAP_BASE(h), NULL, NULL); } -static inline Hashmap *hashmap_free_free(Hashmap *h) { +static inline Hashmap* hashmap_free_free(Hashmap *h) { return (void*) _hashmap_free(HASHMAP_BASE(h), NULL, free); } -static inline OrderedHashmap *ordered_hashmap_free_free(OrderedHashmap *h) { +static inline OrderedHashmap* ordered_hashmap_free_free(OrderedHashmap *h) { return (void*) _hashmap_free(HASHMAP_BASE(h), NULL, free); } -static inline Hashmap *hashmap_free_free_key(Hashmap *h) { +static inline Hashmap* hashmap_free_free_key(Hashmap *h) { return (void*) _hashmap_free(HASHMAP_BASE(h), free, NULL); } -static inline OrderedHashmap *ordered_hashmap_free_free_key(OrderedHashmap *h) { +static inline OrderedHashmap* ordered_hashmap_free_free_key(OrderedHashmap *h) { return (void*) _hashmap_free(HASHMAP_BASE(h), free, NULL); } -static inline Hashmap *hashmap_free_free_free(Hashmap *h) { +static inline Hashmap* hashmap_free_free_free(Hashmap *h) { return (void*) _hashmap_free(HASHMAP_BASE(h), free, free); } -static inline OrderedHashmap *ordered_hashmap_free_free_free(OrderedHashmap *h) { +static inline OrderedHashmap* ordered_hashmap_free_free_free(OrderedHashmap *h) { return (void*) _hashmap_free(HASHMAP_BASE(h), free, free); } -IteratedCache *iterated_cache_free(IteratedCache *cache); +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 *_hashmap_copy(HashmapBase *h HASHMAP_DEBUG_PARAMS); +HashmapBase* _hashmap_copy(HashmapBase *h HASHMAP_DEBUG_PARAMS); #define hashmap_copy(h) ((Hashmap*) _hashmap_copy(HASHMAP_BASE(h) HASHMAP_DEBUG_SRC_ARGS)) #define ordered_hashmap_copy(h) ((OrderedHashmap*) _hashmap_copy(HASHMAP_BASE(h) HASHMAP_DEBUG_SRC_ARGS)) @@ -137,11 +137,14 @@ int _ordered_hashmap_ensure_allocated(OrderedHashmap **h, const struct hash_ops #define hashmap_ensure_allocated(h, ops) _hashmap_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS) #define ordered_hashmap_ensure_allocated(h, ops) _ordered_hashmap_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS) -IteratedCache *_hashmap_iterated_cache_new(HashmapBase *h); -static inline IteratedCache *hashmap_iterated_cache_new(Hashmap *h) { +int _ordered_hashmap_ensure_put(OrderedHashmap **h, const struct hash_ops *hash_ops, const void *key, void *value HASHMAP_DEBUG_PARAMS); +#define ordered_hashmap_ensure_put(s, ops, key, value) _ordered_hashmap_ensure_put(s, ops, key, value HASHMAP_DEBUG_SRC_ARGS) + +IteratedCache* _hashmap_iterated_cache_new(HashmapBase *h); +static inline IteratedCache* hashmap_iterated_cache_new(Hashmap *h) { return (IteratedCache*) _hashmap_iterated_cache_new(HASHMAP_BASE(h)); } -static inline IteratedCache *ordered_hashmap_iterated_cache_new(OrderedHashmap *h) { +static inline IteratedCache* ordered_hashmap_iterated_cache_new(OrderedHashmap *h) { return (IteratedCache*) _hashmap_iterated_cache_new(HASHMAP_BASE(h)); } @@ -163,7 +166,7 @@ static inline int ordered_hashmap_replace(OrderedHashmap *h, const void *key, vo return hashmap_replace(PLAIN_HASHMAP(h), key, value); } -void *_hashmap_get(HashmapBase *h, const void *key); +void* _hashmap_get(HashmapBase *h, const void *key); static inline void *hashmap_get(Hashmap *h, const void *key) { return _hashmap_get(HASHMAP_BASE(h), key); } @@ -171,7 +174,7 @@ static inline void *ordered_hashmap_get(OrderedHashmap *h, const void *key) { return _hashmap_get(HASHMAP_BASE(h), key); } -void *hashmap_get2(Hashmap *h, const void *key, void **rkey); +void* hashmap_get2(Hashmap *h, const void *key, void **rkey); static inline void *ordered_hashmap_get2(OrderedHashmap *h, const void *key, void **rkey) { return hashmap_get2(PLAIN_HASHMAP(h), key, rkey); } @@ -184,7 +187,7 @@ static inline bool ordered_hashmap_contains(OrderedHashmap *h, const void *key) return _hashmap_contains(HASHMAP_BASE(h), key); } -void *_hashmap_remove(HashmapBase *h, const void *key); +void* _hashmap_remove(HashmapBase *h, const void *key); static inline void *hashmap_remove(Hashmap *h, const void *key) { return _hashmap_remove(HASHMAP_BASE(h), key); } @@ -192,17 +195,17 @@ static inline void *ordered_hashmap_remove(OrderedHashmap *h, const void *key) { return _hashmap_remove(HASHMAP_BASE(h), key); } -void *hashmap_remove2(Hashmap *h, const void *key, void **rkey); +void* hashmap_remove2(Hashmap *h, const void *key, void **rkey); static inline void *ordered_hashmap_remove2(OrderedHashmap *h, const void *key, void **rkey) { return hashmap_remove2(PLAIN_HASHMAP(h), key, rkey); } -void *_hashmap_remove_value(HashmapBase *h, const void *key, void *value); +void* _hashmap_remove_value(HashmapBase *h, const void *key, void *value); static inline void *hashmap_remove_value(Hashmap *h, const void *key, void *value) { return _hashmap_remove_value(HASHMAP_BASE(h), key, value); } -static inline void *ordered_hashmap_remove_value(OrderedHashmap *h, const void *key, void *value) { +static inline void* ordered_hashmap_remove_value(OrderedHashmap *h, const void *key, void *value) { return hashmap_remove_value(PLAIN_HASHMAP(h), key, value); } @@ -388,13 +391,13 @@ static inline void *ordered_hashmap_first_key(OrderedHashmap *h) { }) /* no hashmap_next */ -void *ordered_hashmap_next(OrderedHashmap *h, const void *key); +void* ordered_hashmap_next(OrderedHashmap *h, const void *key); -char **_hashmap_get_strv(HashmapBase *h); -static inline char **hashmap_get_strv(Hashmap *h) { +char** _hashmap_get_strv(HashmapBase *h); +static inline char** hashmap_get_strv(Hashmap *h) { return _hashmap_get_strv(HASHMAP_BASE(h)); } -static inline char **ordered_hashmap_get_strv(OrderedHashmap *h) { +static inline char** ordered_hashmap_get_strv(OrderedHashmap *h) { return _hashmap_get_strv(HASHMAP_BASE(h)); } @@ -404,17 +407,25 @@ static inline char **ordered_hashmap_get_strv(OrderedHashmap *h) { * the entries were inserted. * It is safe to remove the current entry. */ -#define HASHMAP_FOREACH(e, h, i) \ - for ((i) = ITERATOR_FIRST; hashmap_iterate((h), &(i), (void**)&(e), NULL); ) +#define _HASHMAP_FOREACH(e, h, i) \ + for (Iterator i = ITERATOR_FIRST; hashmap_iterate((h), &i, (void**)&(e), NULL); ) +#define HASHMAP_FOREACH(e, h) \ + _HASHMAP_FOREACH(e, h, UNIQ_T(i, UNIQ)) -#define ORDERED_HASHMAP_FOREACH(e, h, i) \ - for ((i) = ITERATOR_FIRST; ordered_hashmap_iterate((h), &(i), (void**)&(e), NULL); ) +#define _ORDERED_HASHMAP_FOREACH(e, h, i) \ + for (Iterator i = ITERATOR_FIRST; ordered_hashmap_iterate((h), &i, (void**)&(e), NULL); ) +#define ORDERED_HASHMAP_FOREACH(e, h) \ + _ORDERED_HASHMAP_FOREACH(e, h, UNIQ_T(i, UNIQ)) -#define HASHMAP_FOREACH_KEY(e, k, h, i) \ - for ((i) = ITERATOR_FIRST; hashmap_iterate((h), &(i), (void**)&(e), (const void**) &(k)); ) +#define _HASHMAP_FOREACH_KEY(e, k, h, i) \ + for (Iterator i = ITERATOR_FIRST; hashmap_iterate((h), &i, (void**)&(e), (const void**) &(k)); ) +#define HASHMAP_FOREACH_KEY(e, k, h) \ + _HASHMAP_FOREACH_KEY(e, k, h, UNIQ_T(i, UNIQ)) -#define ORDERED_HASHMAP_FOREACH_KEY(e, k, h, i) \ - for ((i) = ITERATOR_FIRST; ordered_hashmap_iterate((h), &(i), (void**)&(e), (const void**) &(k)); ) +#define _ORDERED_HASHMAP_FOREACH_KEY(e, k, h, i) \ + for (Iterator i = ITERATOR_FIRST; ordered_hashmap_iterate((h), &i, (void**)&(e), (const void**) &(k)); ) +#define ORDERED_HASHMAP_FOREACH_KEY(e, k, h) \ + _ORDERED_HASHMAP_FOREACH_KEY(e, k, h, UNIQ_T(i, UNIQ)) DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, hashmap_free); DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, hashmap_free_free); diff --git a/shared/systemd/src/basic/in-addr-util.c b/shared/systemd/src/basic/in-addr-util.c index 98ccbdfe2..1ea3e7ff1 100644 --- a/shared/systemd/src/basic/in-addr-util.c +++ b/shared/systemd/src/basic/in-addr-util.c @@ -56,6 +56,16 @@ int in_addr_is_link_local(int family, const union in_addr_union *u) { return -EAFNOSUPPORT; } +bool in6_addr_is_link_local_all_nodes(const struct in6_addr *a) { + assert(a); + + /* ff02::1 */ + return be32toh(a->s6_addr32[0]) == UINT32_C(0xff020000) && + a->s6_addr32[1] == 0 && + a->s6_addr32[2] == 0 && + be32toh(a->s6_addr32[3]) == UINT32_C(0x00000001); +} + int in_addr_is_multicast(int family, const union in_addr_union *u) { assert(u); @@ -68,6 +78,12 @@ int in_addr_is_multicast(int family, const union in_addr_union *u) { return -EAFNOSUPPORT; } +bool in4_addr_is_local_multicast(const struct in_addr *a) { + assert(a); + + return (be32toh(a->s_addr) & UINT32_C(0xffffff00)) == UINT32_C(0xe0000000); +} + bool in4_addr_is_localhost(const struct in_addr *a) { assert(a); @@ -408,46 +424,6 @@ int in_addr_prefix_to_string(int family, const union in_addr_union *u, unsigned } #endif /* NM_IGNORED */ -int in_addr_ifindex_to_string(int family, const union in_addr_union *u, int ifindex, char **ret) { - _cleanup_free_ char *x = NULL; - size_t l; - int r; - - assert(u); - assert(ret); - - /* Much like in_addr_to_string(), but optionally appends the zone interface index to the address, to properly - * handle IPv6 link-local addresses. */ - - if (family != AF_INET6) - goto fallback; - if (ifindex <= 0) - goto fallback; - - r = in_addr_is_link_local(family, u); - if (r < 0) - return r; - if (r == 0) - goto fallback; - - l = INET6_ADDRSTRLEN + 1 + DECIMAL_STR_MAX(ifindex) + 1; - x = new(char, l); - if (!x) - return -ENOMEM; - - errno = 0; - if (!inet_ntop(family, u, x, l)) - return errno_or_else(EINVAL); - - sprintf(strchr(x, 0), "%%%i", ifindex); - - *ret = TAKE_PTR(x); - return 0; - -fallback: - return in_addr_to_string(family, u, ret); -} - int in_addr_port_ifindex_name_to_string(int family, const union in_addr_union *u, uint16_t port, int ifindex, const char *server_name, char **ret) { _cleanup_free_ char *ip_str = NULL, *x = NULL; int r; @@ -802,13 +778,13 @@ static int in_addr_data_compare_func(const struct in_addr_data *x, const struct DEFINE_HASH_OPS(in_addr_data_hash_ops, struct in_addr_data, in_addr_data_hash_func, in_addr_data_compare_func); -static void in6_addr_hash_func(const struct in6_addr *addr, struct siphash *state) { +void in6_addr_hash_func(const struct in6_addr *addr, struct siphash *state) { assert(addr); siphash24_compress(addr, sizeof(*addr), state); } -static int in6_addr_compare_func(const struct in6_addr *a, const struct in6_addr *b) { +int in6_addr_compare_func(const struct in6_addr *a, const struct in6_addr *b) { return memcmp(a, b, sizeof(*a)); } diff --git a/shared/systemd/src/basic/in-addr-util.h b/shared/systemd/src/basic/in-addr-util.h index dc3f575bc..45c93a005 100644 --- a/shared/systemd/src/basic/in-addr-util.h +++ b/shared/systemd/src/basic/in-addr-util.h @@ -12,6 +12,7 @@ union in_addr_union { struct in_addr in; struct in6_addr in6; + uint8_t bytes[CONST_MAX(sizeof(struct in_addr), sizeof(struct in6_addr))]; }; struct in_addr_data { @@ -26,10 +27,12 @@ int in_addr_is_multicast(int family, const union in_addr_union *u); bool in4_addr_is_link_local(const struct in_addr *a); int in_addr_is_link_local(int family, const union in_addr_union *u); +bool in6_addr_is_link_local_all_nodes(const struct in6_addr *a); bool in4_addr_is_localhost(const struct in_addr *a); int in_addr_is_localhost(int family, const union in_addr_union *u); +bool in4_addr_is_local_multicast(const struct in_addr *a); bool in4_addr_is_non_local(const struct in_addr *a); bool in4_addr_equal(const struct in_addr *a, const struct in_addr *b); @@ -40,8 +43,13 @@ int in_addr_prefix_nth(int family, union in_addr_union *u, unsigned prefixlen, u int in_addr_random_prefix(int family, union in_addr_union *u, unsigned prefixlen_fixed_part, unsigned prefixlen); int in_addr_to_string(int family, const union in_addr_union *u, char **ret); int in_addr_prefix_to_string(int family, const union in_addr_union *u, unsigned prefixlen, char **ret); -int in_addr_ifindex_to_string(int family, const union in_addr_union *u, int ifindex, char **ret); int in_addr_port_ifindex_name_to_string(int family, const union in_addr_union *u, uint16_t port, int ifindex, const char *server_name, char **ret); +static inline int in_addr_ifindex_to_string(int family, const union in_addr_union *u, int ifindex, char **ret) { + return in_addr_port_ifindex_name_to_string(family, u, 0, ifindex, NULL, ret); +} +static inline int in_addr_port_to_string(int family, const union in_addr_union *u, uint16_t port, char **ret) { + return in_addr_port_ifindex_name_to_string(family, u, port, 0, NULL, ret); +} int in_addr_from_string(int family, const char *s, union in_addr_union *ret); int in_addr_from_string_auto(const char *s, int *ret_family, union in_addr_union *ret); @@ -74,5 +82,8 @@ static inline size_t FAMILY_ADDRESS_SIZE(int family) { * See also oss-fuzz#11344. */ #define IN_ADDR_NULL ((union in_addr_union) { .in6 = {} }) +void in6_addr_hash_func(const struct in6_addr *addr, struct siphash *state); +int in6_addr_compare_func(const struct in6_addr *a, const struct in6_addr *b); + extern const struct hash_ops in_addr_data_hash_ops; extern const struct hash_ops in6_addr_hash_ops; diff --git a/shared/systemd/src/basic/io-util.c b/shared/systemd/src/basic/io-util.c index f1df3fac9..8b0e354a4 100644 --- a/shared/systemd/src/basic/io-util.c +++ b/shared/systemd/src/basic/io-util.c @@ -158,10 +158,8 @@ int pipe_eof(int fd) { int r; r = fd_wait_for_event(fd, POLLIN, 0); - if (r < 0) + if (r <= 0) return r; - if (r == 0) - return 0; return !!(r & POLLHUP); } diff --git a/shared/systemd/src/basic/log.h b/shared/systemd/src/basic/log.h index 9bc875af6..653a3c561 100644 --- a/shared/systemd/src/basic/log.h +++ b/shared/systemd/src/basic/log.h @@ -248,12 +248,12 @@ void log_assert_failed_return_realm( #define log_full_errno(level, error, ...) \ log_full_errno_realm(LOG_REALM, (level), (error), __VA_ARGS__) -#define log_full(level, ...) log_full_errno((level), 0, __VA_ARGS__) +#define log_full(level, ...) (void) log_full_errno((level), 0, __VA_ARGS__) int log_emergency_level(void); /* Normal logging */ -#define log_debug(...) log_full(LOG_DEBUG, __VA_ARGS__) +#define log_debug(...) log_full_errno(LOG_DEBUG, 0, __VA_ARGS__) #define log_info(...) log_full(LOG_INFO, __VA_ARGS__) #define log_notice(...) log_full(LOG_NOTICE, __VA_ARGS__) #define log_warning(...) log_full(LOG_WARNING, __VA_ARGS__) diff --git a/shared/systemd/src/basic/macro.h b/shared/systemd/src/basic/macro.h index 4c0538911..f872d41f0 100644 --- a/shared/systemd/src/basic/macro.h +++ b/shared/systemd/src/basic/macro.h @@ -547,6 +547,9 @@ static inline int __coverity_check_and_return__(int condition) { (y) = (_t); \ } while (false) +#define STRV_MAKE(...) ((char**) ((const char*[]) { __VA_ARGS__, NULL })) +#define STRV_MAKE_EMPTY ((char*[1]) { NULL }) + /* Iterates through a specified list of pointers. Accepts NULL pointers, but uses (void*) -1 as internal marker for EOL. */ #define FOREACH_POINTER(p, x, ...) \ for (typeof(p) *_l = (typeof(p)[]) { ({ p = x; }), ##__VA_ARGS__, (void*) -1 }; \ diff --git a/shared/systemd/src/basic/missing_socket.h b/shared/systemd/src/basic/missing_socket.h index 647e56f1c..fe4d35bd7 100644 --- a/shared/systemd/src/basic/missing_socket.h +++ b/shared/systemd/src/basic/missing_socket.h @@ -65,6 +65,10 @@ struct sockaddr_vm { #define IP_TRANSPARENT 19 #endif +#ifndef IPV6_FREEBIND +#define IPV6_FREEBIND 78 +#endif + /* linux/sockios.h */ #ifndef SIOCGSKNS #define SIOCGSKNS 0x894C diff --git a/shared/systemd/src/basic/missing_stat.h b/shared/systemd/src/basic/missing_stat.h index 7d89a7bba..5d59a2144 100644 --- a/shared/systemd/src/basic/missing_stat.h +++ b/shared/systemd/src/basic/missing_stat.h @@ -9,45 +9,129 @@ #include #endif -/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */ +/* Thew newest definition we are aware of (fa2fcf4f1df1559a0a4ee0f46915b496cc2ebf60; 5.8) */ +#define STATX_DEFINITION { \ + __u32 stx_mask; \ + __u32 stx_blksize; \ + __u64 stx_attributes; \ + __u32 stx_nlink; \ + __u32 stx_uid; \ + __u32 stx_gid; \ + __u16 stx_mode; \ + __u16 __spare0[1]; \ + __u64 stx_ino; \ + __u64 stx_size; \ + __u64 stx_blocks; \ + __u64 stx_attributes_mask; \ + struct statx_timestamp stx_atime; \ + struct statx_timestamp stx_btime; \ + struct statx_timestamp stx_ctime; \ + struct statx_timestamp stx_mtime; \ + __u32 stx_rdev_major; \ + __u32 stx_rdev_minor; \ + __u32 stx_dev_major; \ + __u32 stx_dev_minor; \ + __u64 stx_mnt_id; \ + __u64 __spare2; \ + __u64 __spare3[12]; \ +} + #if !HAVE_STRUCT_STATX struct statx_timestamp { __s64 tv_sec; __u32 tv_nsec; __s32 __reserved; }; -struct statx { - __u32 stx_mask; - __u32 stx_blksize; - __u64 stx_attributes; - __u32 stx_nlink; - __u32 stx_uid; - __u32 stx_gid; - __u16 stx_mode; - __u16 __spare0[1]; - __u64 stx_ino; - __u64 stx_size; - __u64 stx_blocks; - __u64 stx_attributes_mask; - struct statx_timestamp stx_atime; - struct statx_timestamp stx_btime; - struct statx_timestamp stx_ctime; - struct statx_timestamp stx_mtime; - __u32 stx_rdev_major; - __u32 stx_rdev_minor; - __u32 stx_dev_major; - __u32 stx_dev_minor; - __u64 __spare2[14]; -}; + +struct statx STATX_DEFINITION; #endif + +/* Always define the newest version we are aware of as a distinct type, so that we can use it even if glibc + * defines an older definition */ +struct new_statx STATX_DEFINITION; #endif /* NM_IGNORED */ /* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */ -#ifndef STATX_BTIME -#define STATX_BTIME 0x00000800U +#ifndef AT_STATX_SYNC_AS_STAT +#define AT_STATX_SYNC_AS_STAT 0x0000 +#endif + +/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */ +#ifndef AT_STATX_FORCE_SYNC +#define AT_STATX_FORCE_SYNC 0x2000 #endif /* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */ #ifndef AT_STATX_DONT_SYNC #define AT_STATX_DONT_SYNC 0x4000 #endif + +/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */ +#ifndef STATX_TYPE +#define STATX_TYPE 0x00000001U +#endif + +/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */ +#ifndef STATX_MODE +#define STATX_MODE 0x00000002U +#endif + +/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */ +#ifndef STATX_NLINK +#define STATX_NLINK 0x00000004U +#endif + +/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */ +#ifndef STATX_UID +#define STATX_UID 0x00000008U +#endif + +/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */ +#ifndef STATX_GID +#define STATX_GID 0x00000010U +#endif + +/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */ +#ifndef STATX_ATIME +#define STATX_ATIME 0x00000020U +#endif + +/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */ +#ifndef STATX_MTIME +#define STATX_MTIME 0x00000040U +#endif + +/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */ +#ifndef STATX_CTIME +#define STATX_CTIME 0x00000080U +#endif + +/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */ +#ifndef STATX_INO +#define STATX_INO 0x00000100U +#endif + +/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */ +#ifndef STATX_SIZE +#define STATX_SIZE 0x00000200U +#endif + +/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */ +#ifndef STATX_BLOCKS +#define STATX_BLOCKS 0x00000400U +#endif + +/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */ +#ifndef STATX_BTIME +#define STATX_BTIME 0x00000800U +#endif + +/* fa2fcf4f1df1559a0a4ee0f46915b496cc2ebf60 (5.8) */ +#ifndef STATX_MNT_ID +#define STATX_MNT_ID 0x00001000U +#endif + +/* 80340fe3605c0e78cfe496c3b3878be828cfdbfe (5.8) */ +#ifndef STATX_ATTR_MOUNT_ROOT +#define STATX_ATTR_MOUNT_ROOT 0x00002000 /* Root of a mount */ +#endif diff --git a/shared/systemd/src/basic/missing_syscall.h b/shared/systemd/src/basic/missing_syscall.h index 4c42e6651..4aed6e7ce 100644 --- a/shared/systemd/src/basic/missing_syscall.h +++ b/shared/systemd/src/basic/missing_syscall.h @@ -35,39 +35,49 @@ static inline int missing_pivot_root(const char *new_root, const char *put_old) /* ======================================================================= */ -#if !HAVE_MEMFD_CREATE -/* may be (invalid) negative number due to libseccomp, see PR 13319 */ -# if ! (defined __NR_memfd_create && __NR_memfd_create >= 0) -# if defined __NR_memfd_create -# undef __NR_memfd_create -# endif -# if defined __x86_64__ -# define __NR_memfd_create 319 -# elif defined __arm__ -# define __NR_memfd_create 385 -# elif defined __aarch64__ -# define __NR_memfd_create 279 -# elif defined __s390__ -# define __NR_memfd_create 350 -# elif defined _MIPS_SIM -# if _MIPS_SIM == _MIPS_SIM_ABI32 -# define __NR_memfd_create 4354 -# endif -# if _MIPS_SIM == _MIPS_SIM_NABI32 -# define __NR_memfd_create 6318 -# endif -# if _MIPS_SIM == _MIPS_SIM_ABI64 -# define __NR_memfd_create 5314 -# endif -# elif defined __i386__ -# define __NR_memfd_create 356 -# elif defined __arc__ -# define __NR_memfd_create 279 -# else -# warning "__NR_memfd_create unknown for your architecture" -# endif +#if defined __x86_64__ +# define systemd_NR_memfd_create 319 +#elif defined __arm__ +# define systemd_NR_memfd_create 385 +#elif defined __aarch64__ +# define systemd_NR_memfd_create 279 +#elif defined(__powerpc__) +# define systemd_NR_memfd_create 360 +#elif defined __s390__ +# define systemd_NR_memfd_create 350 +#elif defined _MIPS_SIM +# if _MIPS_SIM == _MIPS_SIM_ABI32 +# define systemd_NR_memfd_create 4354 # endif +# if _MIPS_SIM == _MIPS_SIM_NABI32 +# define systemd_NR_memfd_create 6318 +# endif +# if _MIPS_SIM == _MIPS_SIM_ABI64 +# define systemd_NR_memfd_create 5314 +# endif +#elif defined __i386__ +# define systemd_NR_memfd_create 356 +#elif defined __arc__ +# define systemd_NR_memfd_create 279 +#else +# warning "memfd_create() syscall number unknown for your architecture" +#endif +/* may be (invalid) negative number due to libseccomp, see PR 13319 */ +#if defined __NR_memfd_create && __NR_memfd_create >= 0 +# if defined systemd_NR_memfd_create +assert_cc(__NR_memfd_create == systemd_NR_memfd_create); +# endif +#else +# if defined __NR_memfd_create +# undef __NR_memfd_create +# endif +# if defined systemd_NR_memfd_create +# define __NR_memfd_create systemd_NR_memfd_create +# endif +#endif + +#if !HAVE_MEMFD_CREATE static inline int missing_memfd_create(const char *name, unsigned int flags) { # ifdef __NR_memfd_create return syscall(__NR_memfd_create, name, flags); @@ -82,45 +92,53 @@ static inline int missing_memfd_create(const char *name, unsigned int flags) { /* ======================================================================= */ -#if !HAVE_GETRANDOM -/* may be (invalid) negative number due to libseccomp, see PR 13319 */ -# if ! (defined __NR_getrandom && __NR_getrandom >= 0) -# if defined __NR_getrandom -# undef __NR_getrandom -# endif -# if defined __x86_64__ -# define __NR_getrandom 318 -# elif defined(__i386__) -# define __NR_getrandom 355 -# elif defined(__arm__) -# define __NR_getrandom 384 -# elif defined(__aarch64__) -# define __NR_getrandom 278 -# elif defined(__ia64__) -# define __NR_getrandom 1339 -# elif defined(__m68k__) -# define __NR_getrandom 352 -# elif defined(__s390x__) -# define __NR_getrandom 349 -# elif defined(__powerpc__) -# define __NR_getrandom 359 -# elif defined _MIPS_SIM -# if _MIPS_SIM == _MIPS_SIM_ABI32 -# define __NR_getrandom 4353 -# endif -# if _MIPS_SIM == _MIPS_SIM_NABI32 -# define __NR_getrandom 6317 -# endif -# if _MIPS_SIM == _MIPS_SIM_ABI64 -# define __NR_getrandom 5313 -# endif -# elif defined(__arc__) -# define __NR_getrandom 278 -# else -# warning "__NR_getrandom unknown for your architecture" -# endif +#if defined __x86_64__ +# define systemd_NR_getrandom 318 +#elif defined(__i386__) +# define systemd_NR_getrandom 355 +#elif defined(__arm__) +# define systemd_NR_getrandom 384 +#elif defined(__aarch64__) +# define systemd_NR_getrandom 278 +#elif defined(__ia64__) +# define systemd_NR_getrandom 1339 +#elif defined(__m68k__) +# define systemd_NR_getrandom 352 +#elif defined(__s390x__) +# define systemd_NR_getrandom 349 +#elif defined(__powerpc__) +# define systemd_NR_getrandom 359 +#elif defined _MIPS_SIM +# if _MIPS_SIM == _MIPS_SIM_ABI32 +# define systemd_NR_getrandom 4353 # endif +# if _MIPS_SIM == _MIPS_SIM_NABI32 +# define systemd_NR_getrandom 6317 +# endif +# if _MIPS_SIM == _MIPS_SIM_ABI64 +# define systemd_NR_getrandom 5313 +# endif +#elif defined(__arc__) +# define systemd_NR_getrandom 278 +#else +# warning "getrandom() syscall number unknown for your architecture" +#endif +/* may be (invalid) negative number due to libseccomp, see PR 13319 */ +#if defined __NR_getrandom && __NR_getrandom >= 0 +# if defined systemd_NR_getrandom +assert_cc(__NR_getrandom == systemd_NR_getrandom); +# endif +#else +# if defined __NR_getrandom +# undef __NR_getrandom +# endif +# if defined systemd_NR_getrandom +# define __NR_getrandom systemd_NR_getrandom +# endif +#endif + +#if !HAVE_GETRANDOM static inline int missing_getrandom(void *buffer, size_t count, unsigned flags) { # ifdef __NR_getrandom return syscall(__NR_getrandom, buffer, count, flags); @@ -135,9 +153,14 @@ static inline int missing_getrandom(void *buffer, size_t count, unsigned flags) /* ======================================================================= */ +/* The syscall has been defined since forever, but the glibc wrapper was missing. */ #if !HAVE_GETTID static inline pid_t missing_gettid(void) { +# if defined __NR_gettid && __NR_gettid >= 0 return (pid_t) syscall(__NR_gettid); +# else +# error "__NR_gettid not defined" +# endif } # define gettid missing_gettid @@ -145,27 +168,39 @@ static inline pid_t missing_gettid(void) { /* ======================================================================= */ -#if !HAVE_NAME_TO_HANDLE_AT -/* may be (invalid) negative number due to libseccomp, see PR 13319 */ -# if ! (defined __NR_name_to_handle_at && __NR_name_to_handle_at >= 0) -# if defined __NR_name_to_handle_at -# undef __NR_name_to_handle_at -# endif -# if defined(__x86_64__) -# define __NR_name_to_handle_at 303 -# elif defined(__i386__) -# define __NR_name_to_handle_at 341 -# elif defined(__arm__) -# define __NR_name_to_handle_at 370 -# elif defined(__powerpc__) -# define __NR_name_to_handle_at 345 -# elif defined(__arc__) -# define __NR_name_to_handle_at 264 -# else -# error "__NR_name_to_handle_at is not defined" -# endif -# endif +#if defined(__x86_64__) +# define systemd_NR_name_to_handle_at 303 +#elif defined(__i386__) +# define systemd_NR_name_to_handle_at 341 +#elif defined(__arm__) +# define systemd_NR_name_to_handle_at 370 +#elif defined __aarch64__ +# define systemd_NR_name_to_handle_at 264 +#elif defined(__powerpc__) +# define systemd_NR_name_to_handle_at 345 +#elif defined __s390__ || defined __s390x__ +# define systemd_NR_name_to_handle_at 335 +#elif defined(__arc__) +# define systemd_NR_name_to_handle_at 264 +#else +# warning "name_to_handle_at number is not defined" +#endif +/* may be (invalid) negative number due to libseccomp, see PR 13319 */ +#if defined __NR_name_to_handle_at && __NR_name_to_handle_at >= 0 +# if defined systemd_NR_name_to_handle_at +assert_cc(__NR_name_to_handle_at == systemd_NR_name_to_handle_at); +# endif +#else +# if defined __NR_name_to_handle_at +# undef __NR_name_to_handle_at +# endif +# if defined systemd_NR_name_to_handle_at +# define __NR_name_to_handle_at systemd_NR_name_to_handle_at +# endif +#endif + +#if !HAVE_NAME_TO_HANDLE_AT struct file_handle { unsigned int handle_bytes; int handle_type; @@ -186,23 +221,39 @@ static inline int missing_name_to_handle_at(int fd, const char *name, struct fil /* ======================================================================= */ -#if !HAVE_SETNS -/* may be (invalid) negative number due to libseccomp, see PR 13319 */ -# if ! (defined __NR_setns && __NR_setns >= 0) -# if defined __NR_setns -# undef __NR_setns -# endif -# if defined(__x86_64__) -# define __NR_setns 308 -# elif defined(__i386__) -# define __NR_setns 346 -# elif defined(__arc__) -# define __NR_setns 268 -# else -# error "__NR_setns is not defined" -# endif -# endif +#if defined __aarch64__ +# define systemd_NR_setns 268 +#elif defined __arm__ +# define systemd_NR_setns 375 +#elif defined(__x86_64__) +# define systemd_NR_setns 308 +#elif defined(__i386__) +# define systemd_NR_setns 346 +#elif defined(__powerpc__) +# define systemd_NR_setns 350 +#elif defined __s390__ || defined __s390x__ +# define systemd_NR_setns 339 +#elif defined(__arc__) +# define systemd_NR_setns 268 +#else +# warning "setns() syscall number unknown for your architecture" +#endif +/* may be (invalid) negative number due to libseccomp, see PR 13319 */ +#if defined __NR_setns && __NR_setns >= 0 +# if defined systemd_NR_setns +assert_cc(__NR_setns == systemd_NR_setns); +# endif +#else +# if defined __NR_setns +# undef __NR_setns +# endif +# if defined systemd_NR_setns +# define __NR_setns systemd_NR_setns +# endif +#endif + +#if !HAVE_SETNS static inline int missing_setns(int fd, int nstype) { # ifdef __NR_setns return syscall(__NR_setns, fd, nstype); @@ -227,41 +278,49 @@ static inline pid_t raw_getpid(void) { /* ======================================================================= */ -#if !HAVE_RENAMEAT2 -/* may be (invalid) negative number due to libseccomp, see PR 13319 */ -# if ! (defined __NR_renameat2 && __NR_renameat2 >= 0) -# if defined __NR_renameat2 -# undef __NR_renameat2 -# endif -# if defined __x86_64__ -# define __NR_renameat2 316 -# elif defined __arm__ -# define __NR_renameat2 382 -# elif defined __aarch64__ -# define __NR_renameat2 276 -# elif defined _MIPS_SIM -# if _MIPS_SIM == _MIPS_SIM_ABI32 -# define __NR_renameat2 4351 -# endif -# if _MIPS_SIM == _MIPS_SIM_NABI32 -# define __NR_renameat2 6315 -# endif -# if _MIPS_SIM == _MIPS_SIM_ABI64 -# define __NR_renameat2 5311 -# endif -# elif defined __i386__ -# define __NR_renameat2 353 -# elif defined __powerpc64__ -# define __NR_renameat2 357 -# elif defined __s390__ || defined __s390x__ -# define __NR_renameat2 347 -# elif defined __arc__ -# define __NR_renameat2 276 -# else -# warning "__NR_renameat2 unknown for your architecture" -# endif +#if defined __x86_64__ +# define systemd_NR_renameat2 316 +#elif defined __arm__ +# define systemd_NR_renameat2 382 +#elif defined __aarch64__ +# define systemd_NR_renameat2 276 +#elif defined _MIPS_SIM +# if _MIPS_SIM == _MIPS_SIM_ABI32 +# define systemd_NR_renameat2 4351 # endif +# if _MIPS_SIM == _MIPS_SIM_NABI32 +# define systemd_NR_renameat2 6315 +# endif +# if _MIPS_SIM == _MIPS_SIM_ABI64 +# define systemd_NR_renameat2 5311 +# endif +#elif defined __i386__ +# define systemd_NR_renameat2 353 +#elif defined __powerpc64__ +# define systemd_NR_renameat2 357 +#elif defined __s390__ || defined __s390x__ +# define systemd_NR_renameat2 347 +#elif defined __arc__ +# define systemd_NR_renameat2 276 +#else +# warning "renameat2() syscall number unknown for your architecture" +#endif +/* may be (invalid) negative number due to libseccomp, see PR 13319 */ +#if defined __NR_renameat2 && __NR_renameat2 >= 0 +# if defined systemd_NR_renameat2 +assert_cc(__NR_renameat2 == systemd_NR_renameat2); +# endif +#else +# if defined __NR_renameat2 +# undef __NR_renameat2 +# endif +# if defined systemd_NR_renameat2 +# define __NR_renameat2 systemd_NR_renameat2 +# endif +#endif + +#if !HAVE_RENAMEAT2 static inline int missing_renameat2(int oldfd, const char *oldname, int newfd, const char *newname, unsigned flags) { # ifdef __NR_renameat2 return syscall(__NR_renameat2, oldfd, oldname, newfd, newname, flags); @@ -328,31 +387,39 @@ static inline key_serial_t missing_request_key(const char *type, const char *des /* ======================================================================= */ -#if !HAVE_COPY_FILE_RANGE -/* may be (invalid) negative number due to libseccomp, see PR 13319 */ -# if ! (defined __NR_copy_file_range && __NR_copy_file_range >= 0) -# if defined __NR_copy_file_range -# undef __NR_copy_file_range -# endif -# if defined(__x86_64__) -# define __NR_copy_file_range 326 -# elif defined(__i386__) -# define __NR_copy_file_range 377 -# elif defined __s390__ -# define __NR_copy_file_range 375 -# elif defined __arm__ -# define __NR_copy_file_range 391 -# elif defined __aarch64__ -# define __NR_copy_file_range 285 -# elif defined __powerpc__ -# define __NR_copy_file_range 379 -# elif defined __arc__ -# define __NR_copy_file_range 285 -# else -# warning "__NR_copy_file_range not defined for your architecture" -# endif -# endif +#if defined(__x86_64__) +# define systemd_NR_copy_file_range 326 +#elif defined(__i386__) +# define systemd_NR_copy_file_range 377 +#elif defined __s390__ +# define systemd_NR_copy_file_range 375 +#elif defined __arm__ +# define systemd_NR_copy_file_range 391 +#elif defined __aarch64__ +# define systemd_NR_copy_file_range 285 +#elif defined __powerpc__ +# define systemd_NR_copy_file_range 379 +#elif defined __arc__ +# define systemd_NR_copy_file_range 285 +#else +# warning "copy_file_range() syscall number unknown for your architecture" +#endif +/* may be (invalid) negative number due to libseccomp, see PR 13319 */ +#if defined __NR_copy_file_range && __NR_copy_file_range >= 0 +# if defined systemd_NR_copy_file_range +assert_cc(__NR_copy_file_range == systemd_NR_copy_file_range); +# endif +#else +# if defined __NR_copy_file_range +# undef __NR_copy_file_range +# endif +# if defined systemd_NR_copy_file_range +# define __NR_copy_file_range systemd_NR_copy_file_range +# endif +#endif + +#if !HAVE_COPY_FILE_RANGE static inline ssize_t missing_copy_file_range(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, @@ -370,31 +437,41 @@ static inline ssize_t missing_copy_file_range(int fd_in, loff_t *off_in, /* ======================================================================= */ -#if !HAVE_BPF -/* may be (invalid) negative number due to libseccomp, see PR 13319 */ -# if ! (defined __NR_bpf && __NR_bpf >= 0) -# if defined __NR_bpf -# undef __NR_bpf -# endif -# if defined __i386__ -# define __NR_bpf 357 -# elif defined __x86_64__ -# define __NR_bpf 321 -# elif defined __aarch64__ -# define __NR_bpf 280 -# elif defined __arm__ -# define __NR_bpf 386 -# elif defined __sparc__ -# define __NR_bpf 349 -# elif defined __s390__ -# define __NR_bpf 351 -# elif defined __tilegx__ -# define __NR_bpf 280 -# else -# warning "__NR_bpf not defined for your architecture" -# endif -# endif +#if defined __i386__ +# define systemd_NR_bpf 357 +#elif defined __x86_64__ +# define systemd_NR_bpf 321 +#elif defined __aarch64__ +# define systemd_NR_bpf 280 +#elif defined __arm__ +# define systemd_NR_bpf 386 +#elif defined(__powerpc__) +# define systemd_NR_bpf 361 +#elif defined __sparc__ +# define systemd_NR_bpf 349 +#elif defined __s390__ +# define systemd_NR_bpf 351 +#elif defined __tilegx__ +# define systemd_NR_bpf 280 +#else +# warning "bpf() syscall number unknown for your architecture" +#endif +/* may be (invalid) negative number due to libseccomp, see PR 13319 */ +#if defined __NR_bpf && __NR_bpf >= 0 +# if defined systemd_NR_bpf +assert_cc(__NR_bpf == systemd_NR_bpf); +# endif +#else +# if defined __NR_bpf +# undef __NR_bpf +# endif +# if defined systemd_NR_bpf +# define __NR_bpf systemd_NR_bpf +# endif +#endif + +#if !HAVE_BPF union bpf_attr; static inline int missing_bpf(int cmd, union bpf_attr *attr, size_t size) { @@ -412,69 +489,84 @@ static inline int missing_bpf(int cmd, union bpf_attr *attr, size_t size) { /* ======================================================================= */ #ifndef __IGNORE_pkey_mprotect +# if defined __i386__ +# define systemd_NR_pkey_mprotect 380 +# elif defined __x86_64__ +# define systemd_NR_pkey_mprotect 329 +# elif defined __aarch64__ +# define systemd_NR_pkey_mprotect 288 +# elif defined __arm__ +# define systemd_NR_pkey_mprotect 394 +# elif defined __powerpc__ +# define systemd_NR_pkey_mprotect 386 +# elif defined __s390__ +# define systemd_NR_pkey_mprotect 384 +# elif defined _MIPS_SIM +# if _MIPS_SIM == _MIPS_SIM_ABI32 +# define systemd_NR_pkey_mprotect 4363 +# endif +# if _MIPS_SIM == _MIPS_SIM_NABI32 +# define systemd_NR_pkey_mprotect 6327 +# endif +# if _MIPS_SIM == _MIPS_SIM_ABI64 +# define systemd_NR_pkey_mprotect 5323 +# endif +# else +# warning "pkey_mprotect() syscall number unknown for your architecture" +# endif + /* may be (invalid) negative number due to libseccomp, see PR 13319 */ -# if ! (defined __NR_pkey_mprotect && __NR_pkey_mprotect >= 0) +# if defined __NR_pkey_mprotect && __NR_pkey_mprotect >= 0 +# if defined systemd_NR_pkey_mprotect +assert_cc(__NR_pkey_mprotect == systemd_NR_pkey_mprotect); +# endif +# else # if defined __NR_pkey_mprotect # undef __NR_pkey_mprotect # endif -# if defined __i386__ -# define __NR_pkey_mprotect 380 -# elif defined __x86_64__ -# define __NR_pkey_mprotect 329 -# elif defined __arm__ -# define __NR_pkey_mprotect 394 -# elif defined __aarch64__ -# define __NR_pkey_mprotect 394 -# elif defined __powerpc__ -# define __NR_pkey_mprotect 386 -# elif defined __s390__ -# define __NR_pkey_mprotect 384 -# elif defined _MIPS_SIM -# if _MIPS_SIM == _MIPS_SIM_ABI32 -# define __NR_pkey_mprotect 4363 -# endif -# if _MIPS_SIM == _MIPS_SIM_NABI32 -# define __NR_pkey_mprotect 6327 -# endif -# if _MIPS_SIM == _MIPS_SIM_ABI64 -# define __NR_pkey_mprotect 5323 -# endif -# else -# warning "__NR_pkey_mprotect not defined for your architecture" +# if defined systemd_NR_pkey_mprotect +# define __NR_pkey_mprotect systemd_NR_pkey_mprotect # endif # endif #endif /* ======================================================================= */ -#if !HAVE_STATX -/* may be (invalid) negative number due to libseccomp, see PR 13319 */ -# if ! (defined __NR_statx && __NR_statx >= 0) -# if defined __NR_statx -# undef __NR_statx -# endif -# if defined __aarch64__ || defined __arm__ -# define __NR_statx 397 -# elif defined __alpha__ -# define __NR_statx 522 -# elif defined __i386__ || defined __powerpc64__ -# define __NR_statx 383 -# elif defined __sparc__ -# define __NR_statx 360 -# elif defined __x86_64__ -# define __NR_statx 332 -# else -# warning "__NR_statx not defined for your architecture" -# endif -# endif - -struct statx; +#if defined __aarch64__ +# define systemd_NR_statx 291 +#elif defined __arm__ +# define systemd_NR_statx 397 +#elif defined __alpha__ +# define systemd_NR_statx 522 +#elif defined __i386__ || defined __powerpc64__ +# define systemd_NR_statx 383 +#elif defined __s390__ || defined __s390x__ +# define systemd_NR_statx 379 +#elif defined __sparc__ +# define systemd_NR_statx 360 +#elif defined __x86_64__ +# define systemd_NR_statx 332 +#else +# warning "statx() syscall number unknown for your architecture" #endif -/* This typedef is supposed to be always defined. */ -typedef struct statx struct_statx; +/* may be (invalid) negative number due to libseccomp, see PR 13319 */ +#if defined __NR_statx && __NR_statx >= 0 +# if defined systemd_NR_statx +assert_cc(__NR_statx == systemd_NR_statx); +# endif +#else +# if defined __NR_statx +# undef __NR_statx +# endif +# if defined systemd_NR_statx +# define __NR_statx systemd_NR_statx +# endif +#endif #if !HAVE_STATX +struct statx; + static inline ssize_t missing_statx(int dfd, const char *filename, unsigned flags, unsigned int mask, struct statx *buffer) { # ifdef __NR_statx return syscall(__NR_statx, dfd, filename, flags, mask, buffer); @@ -483,12 +575,18 @@ static inline ssize_t missing_statx(int dfd, const char *filename, unsigned flag return -1; # endif } - -# define statx missing_statx #endif -#if !HAVE_SET_MEMPOLICY +/* This typedef is supposed to be always defined. */ +typedef struct statx struct_statx; +#if !HAVE_STATX +# define statx(dfd, filename, flags, mask, buffer) missing_statx(dfd, filename, flags, mask, buffer) +#endif + +/* ======================================================================= */ + +#if !HAVE_SET_MEMPOLICY enum { MPOL_DEFAULT, MPOL_PREFERRED, @@ -517,7 +615,7 @@ static inline long missing_get_mempolicy(int *mode, unsigned long *nodemask, unsigned long maxnode, void *addr, unsigned long flags) { long i; -# ifdef __NR_get_mempolicy +# if defined __NR_get_mempolicy && __NR_get_mempolicy >= 0 i = syscall(__NR_get_mempolicy, mode, nodemask, maxnode, addr, flags); # else errno = ENOSYS; @@ -526,49 +624,87 @@ static inline long missing_get_mempolicy(int *mode, unsigned long *nodemask, return i; } -#define get_mempolicy missing_get_mempolicy +# define get_mempolicy missing_get_mempolicy #endif #endif /* NM_IGNORED */ -#if !HAVE_PIDFD_OPEN -/* may be (invalid) negative number due to libseccomp, see PR 13319 */ -# if ! (defined __NR_pidfd_open && __NR_pidfd_open >= 0) -# if defined __NR_pidfd_open -# undef __NR_pidfd_open -# endif -# define __NR_pidfd_open 434 -#endif -static inline int pidfd_open(pid_t pid, unsigned flags) { -#ifdef __NR_pidfd_open - return syscall(__NR_pidfd_open, pid, flags); +/* ======================================================================= */ + +/* should be always defined, see kernel 39036cd2727395c3369b1051005da74059a85317 */ +#if defined(__alpha__) +# define systemd_NR_pidfd_send_signal 534 #else - errno = ENOSYS; - return -1; +# define systemd_NR_pidfd_send_signal 424 #endif -} + +/* may be (invalid) negative number due to libseccomp, see PR 13319 */ +#if defined __NR_pidfd_send_signal && __NR_pidfd_send_signal >= 0 +# if defined systemd_NR_pidfd_send_signal +assert_cc(__NR_pidfd_send_signal == systemd_NR_pidfd_send_signal); +# endif +#else +# if defined __NR_pidfd_send_signal +# undef __NR_pidfd_send_signal +# endif +# define __NR_pidfd_send_signal systemd_NR_pidfd_send_signal #endif #if !HAVE_PIDFD_SEND_SIGNAL -/* may be (invalid) negative number due to libseccomp, see PR 13319 */ -# if ! (defined __NR_pidfd_send_signal && __NR_pidfd_send_signal >= 0) -# if defined __NR_pidfd_send_signal -# undef __NR_pidfd_send_signal -# endif -# define __NR_pidfd_send_signal 424 -#endif -static inline int pidfd_send_signal(int fd, int sig, siginfo_t *info, unsigned flags) { -#ifdef __NR_pidfd_open +static inline int missing_pidfd_send_signal(int fd, int sig, siginfo_t *info, unsigned flags) { +# ifdef __NR_pidfd_open return syscall(__NR_pidfd_send_signal, fd, sig, info, flags); -#else +# else errno = ENOSYS; return -1; -#endif +# endif } + +# define pidfd_send_signal missing_pidfd_send_signal #endif -#if !HAVE_RT_SIGQUEUEINFO -static inline int rt_sigqueueinfo(pid_t tgid, int sig, siginfo_t *info) { - return syscall(__NR_rt_sigqueueinfo, tgid, sig, info); -} +/* should be always defined, see kernel 7615d9e1780e26e0178c93c55b73309a5dc093d7 */ +#if defined(__alpha__) +# define systemd_NR_pidfd_open 544 +#else +# define systemd_NR_pidfd_open 434 +#endif + +/* may be (invalid) negative number due to libseccomp, see PR 13319 */ +#if defined __NR_pidfd_open && __NR_pidfd_open >= 0 +# if defined systemd_NR_pidfd_open +assert_cc(__NR_pidfd_open == systemd_NR_pidfd_open); +# endif +#else +# if defined __NR_pidfd_open +# undef __NR_pidfd_open +# endif +# define __NR_pidfd_open systemd_NR_pidfd_open +#endif + +#if !HAVE_PIDFD_OPEN +static inline int missing_pidfd_open(pid_t pid, unsigned flags) { +# ifdef __NR_pidfd_open + return syscall(__NR_pidfd_open, pid, flags); +# else + errno = ENOSYS; + return -1; +# endif +} + +# define pidfd_open missing_pidfd_open +#endif + +/* ======================================================================= */ + +#if !HAVE_RT_SIGQUEUEINFO +static inline int missing_rt_sigqueueinfo(pid_t tgid, int sig, siginfo_t *info) { +# if defined __NR_rt_sigqueueinfo && __NR_rt_sigqueueinfo >= 0 + return syscall(__NR_rt_sigqueueinfo, tgid, sig, info); +# else +# error "__NR_rt_sigqueueinfo not defined" +# endif +} + +# define rt_sigqueueinfo missing_rt_sigqueueinfo #endif diff --git a/shared/systemd/src/basic/parse-util.c b/shared/systemd/src/basic/parse-util.c index 0b343b2a8..6b47317a4 100644 --- a/shared/systemd/src/basic/parse-util.c +++ b/shared/systemd/src/basic/parse-util.c @@ -18,6 +18,9 @@ #include "missing_network.h" #include "parse-util.h" #include "process-util.h" +#if HAVE_SECCOMP +#include "seccomp-util.h" +#endif #include "stat-util.h" #include "string-util.h" #include "strv.h" @@ -317,6 +320,7 @@ int parse_errno(const char *t) { return e; } +#if HAVE_SECCOMP int parse_syscall_and_errno(const char *in, char **name, int *error) { _cleanup_free_ char *n = NULL; char *p; @@ -335,7 +339,7 @@ int parse_syscall_and_errno(const char *in, char **name, int *error) { p = strchr(in, ':'); if (p) { - e = parse_errno(p + 1); + e = seccomp_parse_errno_or_action(p + 1); if (e < 0) return e; @@ -354,6 +358,7 @@ int parse_syscall_and_errno(const char *in, char **name, int *error) { return 0; } +#endif #endif /* NM_IGNORED */ static const char *mangle_base(const char *s, unsigned *base) { diff --git a/shared/systemd/src/basic/parse-util.h b/shared/systemd/src/basic/parse-util.h index 9a516ce5f..2cee65c49 100644 --- a/shared/systemd/src/basic/parse-util.h +++ b/shared/systemd/src/basic/parse-util.h @@ -19,7 +19,9 @@ int parse_mtu(int family, const char *s, uint32_t *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); +#if HAVE_SECCOMP int parse_syscall_and_errno(const char *in, char **name, int *error); +#endif #define SAFE_ATO_REFUSE_PLUS_MINUS (1U << 30) #define SAFE_ATO_REFUSE_LEADING_ZERO (1U << 29) diff --git a/shared/systemd/src/basic/path-util.c b/shared/systemd/src/basic/path-util.c index 8f988fb23..644829b27 100644 --- a/shared/systemd/src/basic/path-util.c +++ b/shared/systemd/src/basic/path-util.c @@ -16,6 +16,7 @@ #include "alloc-util.h" #include "extract-word.h" +#include "fd-util.h" #include "fs-util.h" #include "glob-util.h" #include "log.h" @@ -29,15 +30,7 @@ #include "time-util.h" #include "utf8.h" -bool path_is_absolute(const char *p) { - return p[0] == '/'; -} - #if 0 /* NM_IGNORED */ -bool is_path(const char *p) { - return !!strchr(p, '/'); -} - int path_split_and_make_absolute(const char *p, char ***ret) { char **l; int r; @@ -601,9 +594,9 @@ char* path_join_internal(const char *first, ...) { } #if 0 /* NM_IGNORED */ -int find_binary(const char *name, char **ret) { +int find_executable_full(const char *name, bool use_path_envvar, char **ret) { int last_error, r; - const char *p; + const char *p = NULL; assert(name); @@ -620,11 +613,10 @@ int find_binary(const char *name, char **ret) { return 0; } - /** - * Plain getenv, not secure_getenv, because we want - * to actually allow the user to pick the binary. - */ - p = getenv("PATH"); + if (use_path_envvar) + /* Plain getenv, not secure_getenv, because we want to actually allow the user to pick the + * binary. */ + p = getenv("PATH"); if (!p) p = DEFAULT_PATH; @@ -647,12 +639,24 @@ int find_binary(const char *name, char **ret) { return -ENOMEM; if (access(j, X_OK) >= 0) { - /* Found it! */ + _cleanup_free_ char *with_dash; - if (ret) - *ret = path_simplify(TAKE_PTR(j), false); + with_dash = strjoin(j, "/"); + if (!with_dash) + return -ENOMEM; - return 0; + /* If this passes, it must be a directory, and so should be skipped. */ + if (access(with_dash, X_OK) >= 0) + continue; + + /* We can't just `continue` inverting this case, since we need to update last_error. */ + if (errno == ENOTDIR) { + /* Found it! */ + if (ret) + *ret = path_simplify(TAKE_PTR(j), false); + + return 0; + } } /* PATH entries which we don't have access to are ignored, as per tradition. */ @@ -698,18 +702,17 @@ bool paths_check_timestamp(const char* const* paths, usec_t *timestamp, bool upd return changed; } -static int binary_is_good(const char *binary) { +static int executable_is_good(const char *executable) { _cleanup_free_ char *p = NULL, *d = NULL; int r; - r = find_binary(binary, &p); + r = find_executable(executable, &p); if (r == -ENOENT) return 0; if (r < 0) return r; - /* An fsck that is linked to /bin/true is a non-existent - * fsck */ + /* An fsck that is linked to /bin/true is a non-existent fsck */ r = readlink_malloc(p, &d); if (r == -EINVAL) /* not a symlink */ @@ -732,19 +735,7 @@ int fsck_exists(const char *fstype) { return -EINVAL; checker = strjoina("fsck.", fstype); - return binary_is_good(checker); -} - -int mkfs_exists(const char *fstype) { - const char *mkfs; - - assert(fstype); - - if (streq(fstype, "auto")) - return -EINVAL; - - mkfs = strjoina("mkfs.", fstype); - return binary_is_good(mkfs); + return executable_is_good(checker); } int parse_path_argument_and_warn(const char *path, bool suppress_root, char **arg) { @@ -1152,4 +1143,10 @@ bool prefixed_path_strv_contains(char **l, const char *path) { return false; } + +bool credential_name_valid(const char *s) { + /* We want that credential names are both valid in filenames (since that's our primary way to pass + * them around) and as fdnames (which is how we might want to pass them around eventually) */ + return filename_is_valid(s) && fdname_is_valid(s); +} #endif /* NM_IGNORED */ diff --git a/shared/systemd/src/basic/path-util.h b/shared/systemd/src/basic/path-util.h index aba8ad00f..6c2655191 100644 --- a/shared/systemd/src/basic/path-util.h +++ b/shared/systemd/src/basic/path-util.h @@ -44,9 +44,17 @@ # define DEFAULT_USER_PATH DEFAULT_PATH #endif -bool is_path(const char *p) _pure_; +static inline bool is_path(const char *p) { + assert(p); + return strchr(p, '/'); +} + +static inline bool path_is_absolute(const char *p) { + assert(p); + return p[0] == '/'; +} + 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); @@ -82,12 +90,14 @@ int path_strv_make_absolute_cwd(char **l); char** path_strv_resolve(char **l, const char *root); char** path_strv_resolve_uniq(char **l, const char *root); -int find_binary(const char *name, char **filename); +int find_executable_full(const char *name, bool use_path_envvar, char **ret); +static inline int find_executable(const char *name, char **ret) { + return find_executable_full(name, true, ret); +} bool paths_check_timestamp(const char* const* paths, usec_t *paths_ts_usec, bool update); int fsck_exists(const char *fstype); -int mkfs_exists(const char *fstype); /* Iterates through the path prefixes of the specified path, going up * the tree, to root. Also returns "" (and not "/"!) for the root @@ -176,3 +186,5 @@ static inline const char *empty_to_root(const char *path) { bool path_strv_contains(char **l, const char *path); bool prefixed_path_strv_contains(char **l, const char *path); + +bool credential_name_valid(const char *s); diff --git a/shared/systemd/src/basic/random-util.c b/shared/systemd/src/basic/random-util.c index 463d2430d..9551e762f 100644 --- a/shared/systemd/src/basic/random-util.c +++ b/shared/systemd/src/basic/random-util.c @@ -23,6 +23,7 @@ #endif #include "alloc-util.h" +#include "env-util.h" #include "errno-util.h" #include "fd-util.h" #include "fileio.h" @@ -118,6 +119,15 @@ int rdrand(unsigned long *ret) { #endif have_rdrand = !!(ecx & bit_RDRND); + + if (have_rdrand > 0) { + /* Allow disabling use of RDRAND with SYSTEMD_RDRAND=0 + If it is unset getenv_bool_secure will return a negative value. */ + if (getenv_bool_secure("SYSTEMD_RDRAND") == 0) { + have_rdrand = false; + return -EOPNOTSUPP; + } + } } if (have_rdrand == 0) diff --git a/shared/systemd/src/basic/set.h b/shared/systemd/src/basic/set.h index e4fc1e3c4..7170eea84 100644 --- a/shared/systemd/src/basic/set.h +++ b/shared/systemd/src/basic/set.h @@ -13,14 +13,14 @@ 0; \ }) -Set *_set_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS); +Set* _set_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS); #define set_new(ops) _set_new(ops HASHMAP_DEBUG_SRC_ARGS) -static inline Set *set_free(Set *s) { +static inline Set* set_free(Set *s) { return (Set*) _hashmap_free(HASHMAP_BASE(s), NULL, NULL); } -static inline Set *set_free_free(Set *s) { +static inline Set* set_free_free(Set *s) { return (Set*) _hashmap_free(HASHMAP_BASE(s), free, NULL); } @@ -34,7 +34,7 @@ int _set_ensure_allocated(Set **s, const struct hash_ops *hash_ops HASHMAP_DEBUG int set_put(Set *s, const void *key); /* no set_update */ /* no set_replace */ -static inline void *set_get(const Set *s, void *key) { +static inline void *set_get(const Set *s, const void *key) { return _hashmap_get(HASHMAP_BASE((Set *) s), key); } /* no set_get2 */ @@ -77,7 +77,9 @@ static inline unsigned set_buckets(const Set *s) { return _hashmap_buckets(HASHMAP_BASE((Set *) s)); } -bool set_iterate(const Set *s, Iterator *i, void **value); +static inline bool set_iterate(const Set *s, Iterator *i, void **value) { + return _hashmap_iterate(HASHMAP_BASE((Set*) s), i, value, NULL); +} static inline void set_clear(Set *s) { _hashmap_clear(HASHMAP_BASE(s), NULL, NULL); @@ -133,8 +135,10 @@ int _set_put_strdupv(Set **s, char **l HASHMAP_DEBUG_PARAMS); int set_put_strsplit(Set *s, const char *v, const char *separators, ExtractFlags flags); -#define SET_FOREACH(e, s, i) \ - for ((i) = ITERATOR_FIRST; set_iterate((s), &(i), (void**)&(e)); ) +#define _SET_FOREACH(e, s, i) \ + for (Iterator i = ITERATOR_FIRST; set_iterate((s), &i, (void**)&(e)); ) +#define SET_FOREACH(e, s) \ + _SET_FOREACH(e, s, UNIQ_T(i, UNIQ)) #define SET_FOREACH_MOVE(e, d, s) \ for (; ({ e = set_first(s); assert_se(!e || set_move_one(d, s, e) >= 0); e; }); ) diff --git a/shared/systemd/src/basic/siphash24.h b/shared/systemd/src/basic/siphash24.h index b56c41a65..621301f9d 100644 --- a/shared/systemd/src/basic/siphash24.h +++ b/shared/systemd/src/basic/siphash24.h @@ -6,6 +6,8 @@ #include #include +#include "time-util.h" + #if 0 /* NM_IGNORED */ struct siphash { uint64_t v0; @@ -55,6 +57,10 @@ static inline void siphash24_compress_boolean(bool in, struct siphash *state) { siphash24_compress(&i, sizeof i, state); } +static inline void siphash24_compress_usec_t(usec_t in, struct siphash *state) { + siphash24_compress(&in, sizeof in, state); +} + static inline void siphash24_compress_string(const char *in, struct siphash *state) { if (!in) return; diff --git a/shared/systemd/src/basic/socket-util.c b/shared/systemd/src/basic/socket-util.c index 755cdeb21..01dce3ab5 100644 --- a/shared/systemd/src/basic/socket-util.c +++ b/shared/systemd/src/basic/socket-util.c @@ -30,6 +30,7 @@ #include "macro.h" #include "memory-util.h" #include "missing_socket.h" +#include "missing_network.h" #include "parse-util.h" #include "path-util.h" #include "process-util.h" @@ -73,7 +74,7 @@ int socket_address_verify(const SocketAddress *a, bool strict) { if (a->sockaddr.in.sin_port == 0) return -EINVAL; - if (!IN_SET(a->type, SOCK_STREAM, SOCK_DGRAM)) + if (!IN_SET(a->type, 0, SOCK_STREAM, SOCK_DGRAM)) return -EINVAL; return 0; @@ -85,7 +86,7 @@ int socket_address_verify(const SocketAddress *a, bool strict) { if (a->sockaddr.in6.sin6_port == 0) return -EINVAL; - if (!IN_SET(a->type, SOCK_STREAM, SOCK_DGRAM)) + if (!IN_SET(a->type, 0, SOCK_STREAM, SOCK_DGRAM)) return -EINVAL; return 0; @@ -119,7 +120,7 @@ int socket_address_verify(const SocketAddress *a, bool strict) { } } - if (!IN_SET(a->type, SOCK_STREAM, SOCK_DGRAM, SOCK_SEQPACKET)) + if (!IN_SET(a->type, 0, SOCK_STREAM, SOCK_DGRAM, SOCK_SEQPACKET)) return -EINVAL; return 0; @@ -129,7 +130,7 @@ int socket_address_verify(const SocketAddress *a, bool strict) { if (a->size != sizeof(struct sockaddr_nl)) return -EINVAL; - if (!IN_SET(a->type, SOCK_RAW, SOCK_DGRAM)) + if (!IN_SET(a->type, 0, SOCK_RAW, SOCK_DGRAM)) return -EINVAL; return 0; @@ -138,7 +139,7 @@ int socket_address_verify(const SocketAddress *a, bool strict) { if (a->size != sizeof(struct sockaddr_vm)) return -EINVAL; - if (!IN_SET(a->type, SOCK_STREAM, SOCK_DGRAM)) + if (!IN_SET(a->type, 0, SOCK_STREAM, SOCK_DGRAM)) return -EINVAL; return 0; @@ -404,19 +405,23 @@ int sockaddr_pretty( if (r < 0) return -ENOMEM; } else { - char a[INET6_ADDRSTRLEN]; + char a[INET6_ADDRSTRLEN], ifname[IF_NAMESIZE + 1]; inet_ntop(AF_INET6, &sa->in6.sin6_addr, a, sizeof(a)); + if (sa->in6.sin6_scope_id != 0) + format_ifname_full(sa->in6.sin6_scope_id, ifname, FORMAT_IFNAME_IFINDEX); if (include_port) { r = asprintf(&p, - "[%s]:%u", + "[%s]:%u%s%s", a, - be16toh(sa->in6.sin6_port)); + be16toh(sa->in6.sin6_port), + sa->in6.sin6_scope_id != 0 ? "%" : "", + sa->in6.sin6_scope_id != 0 ? ifname : ""); if (r < 0) return -ENOMEM; } else { - p = strdup(a); + p = sa->in6.sin6_scope_id != 0 ? strjoin(a, "%", ifname) : strdup(a); if (!p) return -ENOMEM; } @@ -622,40 +627,64 @@ bool sockaddr_equal(const union sockaddr_union *a, const union sockaddr_union *b return false; } -int fd_inc_sndbuf(int fd, size_t n) { +int fd_set_sndbuf(int fd, size_t n, bool increase) { int r, value; socklen_t l = sizeof(value); + if (n > INT_MAX) + return -ERANGE; + r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l); - if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2) + if (r >= 0 && l == sizeof(value) && increase ? (size_t) value >= n*2 : (size_t) value == n*2) return 0; - /* If we have the privileges we will ignore the kernel limit. */ + /* First, try to set the buffer size with SO_SNDBUF. */ + r = setsockopt_int(fd, SOL_SOCKET, SO_SNDBUF, n); + if (r < 0) + return r; - if (setsockopt_int(fd, SOL_SOCKET, SO_SNDBUF, n) < 0) { - r = setsockopt_int(fd, SOL_SOCKET, SO_SNDBUFFORCE, n); - if (r < 0) - return r; - } + /* SO_SNDBUF above may set to the kernel limit, instead of the requested size. + * So, we need to check the actual buffer size here. */ + l = sizeof(value); + r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l); + if (r >= 0 && l == sizeof(value) && increase ? (size_t) value >= n*2 : (size_t) value == n*2) + return 1; + + /* If we have the privileges we will ignore the kernel limit. */ + r = setsockopt_int(fd, SOL_SOCKET, SO_SNDBUFFORCE, n); + if (r < 0) + return r; return 1; } -int fd_inc_rcvbuf(int fd, size_t n) { +int fd_set_rcvbuf(int fd, size_t n, bool increase) { int r, value; socklen_t l = sizeof(value); + if (n > INT_MAX) + return -ERANGE; + r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l); - if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2) + if (r >= 0 && l == sizeof(value) && increase ? (size_t) value >= n*2 : (size_t) value == n*2) return 0; - /* If we have the privileges we will ignore the kernel limit. */ + /* First, try to set the buffer size with SO_RCVBUF. */ + r = setsockopt_int(fd, SOL_SOCKET, SO_RCVBUF, n); + if (r < 0) + return r; - if (setsockopt_int(fd, SOL_SOCKET, SO_RCVBUF, n) < 0) { - r = setsockopt_int(fd, SOL_SOCKET, SO_RCVBUFFORCE, n); - if (r < 0) - return r; - } + /* SO_RCVBUF above may set to the kernel limit, instead of the requested size. + * So, we need to check the actual buffer size here. */ + l = sizeof(value); + r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l); + if (r >= 0 && l == sizeof(value) && increase ? (size_t) value >= n*2 : (size_t) value == n*2) + return 1; + + /* If we have the privileges we will ignore the kernel limit. */ + r = setsockopt_int(fd, SOL_SOCKET, SO_RCVBUFFORCE, n); + if (r < 0) + return r; return 1; } @@ -669,17 +698,19 @@ static const char* const ip_tos_table[] = { DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos, int, 0xff); -bool ifname_valid_full(const char *p, bool alternative) { +bool ifname_valid_full(const char *p, IfnameValidFlags flags) { bool numeric = true; /* Checks whether a network interface name is valid. This is inspired by dev_valid_name() in the kernel sources * but slightly stricter, as we only allow non-control, non-space ASCII characters in the interface name. We * also don't permit names that only container numbers, to avoid confusion with numeric interface indexes. */ + assert(!(flags & ~_IFNAME_VALID_ALL)); + if (isempty(p)) return false; - if (alternative) { + if (flags & IFNAME_VALID_ALTERNATIVE) { if (strlen(p) >= ALTIFNAMSIZ) return false; } else { @@ -690,22 +721,27 @@ bool ifname_valid_full(const char *p, bool alternative) { if (dot_or_dot_dot(p)) return false; - while (*p) { - if ((unsigned char) *p >= 127U) + for (const char *t = p; *t; t++) { + if ((unsigned char) *t >= 127U) return false; - if ((unsigned char) *p <= 32U) + if ((unsigned char) *t <= 32U) return false; - if (IN_SET(*p, ':', '/')) + if (IN_SET(*t, ':', '/')) return false; - numeric = numeric && (*p >= '0' && *p <= '9'); - p++; + numeric = numeric && (*t >= '0' && *t <= '9'); } - if (numeric) - return false; + if (numeric) { + if (!(flags & IFNAME_VALID_NUMERIC)) + return false; + + /* Verify that the number is well-formatted and in range. */ + if (parse_ifindex(p) < 0) + return false; + } return true; } @@ -1095,12 +1131,10 @@ int sockaddr_un_set_path(struct sockaddr_un *ret, const char *path) { * reference paths in the abstract namespace that include NUL bytes in the name. */ l = strlen(path); - if (l == 0) + if (l < 2) return -EINVAL; if (!IN_SET(path[0], '/', '@')) return -EINVAL; - if (path[1] == 0) - return -EINVAL; /* Don't allow paths larger than the space in sockaddr_un. Note that we are a tiny bit more restrictive than * the kernel is: we insist on NUL termination (both for abstract namespace and regular file system socket @@ -1183,13 +1217,28 @@ ssize_t recvmsg_safe(int sockfd, struct msghdr *msg, int flags) { return n; } -int socket_pass_pktinfo(int fd, bool b) { +int socket_get_family(int fd, int *ret) { int af; socklen_t sl = sizeof(af); if (getsockopt(fd, SOL_SOCKET, SO_DOMAIN, &af, &sl) < 0) return -errno; + if (sl != sizeof(af)) + return -EINVAL; + + return af; +} + +int socket_set_recvpktinfo(int fd, int af, bool b) { + int r; + + if (af == AF_UNSPEC) { + r = socket_get_family(fd, &af); + if (r < 0) + return r; + } + switch (af) { case AF_INET: @@ -1205,3 +1254,142 @@ int socket_pass_pktinfo(int fd, bool b) { return -EAFNOSUPPORT; } } + +int socket_set_recverr(int fd, int af, bool b) { + int r; + + if (af == AF_UNSPEC) { + r = socket_get_family(fd, &af); + if (r < 0) + return r; + } + + switch (af) { + + case AF_INET: + return setsockopt_int(fd, IPPROTO_IP, IP_RECVERR, b); + + case AF_INET6: + return setsockopt_int(fd, IPPROTO_IPV6, IPV6_RECVERR, b); + + default: + return -EAFNOSUPPORT; + } +} + +int socket_set_recvttl(int fd, int af, bool b) { + int r; + + if (af == AF_UNSPEC) { + r = socket_get_family(fd, &af); + if (r < 0) + return r; + } + + switch (af) { + + case AF_INET: + return setsockopt_int(fd, IPPROTO_IP, IP_RECVTTL, b); + + case AF_INET6: + return setsockopt_int(fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, b); + + default: + return -EAFNOSUPPORT; + } +} + +int socket_set_ttl(int fd, int af, int ttl) { + int r; + + if (af == AF_UNSPEC) { + r = socket_get_family(fd, &af); + if (r < 0) + return r; + } + + switch (af) { + + case AF_INET: + return setsockopt_int(fd, IPPROTO_IP, IP_TTL, ttl); + + case AF_INET6: + return setsockopt_int(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, ttl); + + default: + return -EAFNOSUPPORT; + } +} + +int socket_set_unicast_if(int fd, int af, int ifi) { + be32_t ifindex_be = htobe32(ifi); + int r; + + if (af == AF_UNSPEC) { + r = socket_get_family(fd, &af); + if (r < 0) + return r; + } + + switch (af) { + + case AF_INET: + if (setsockopt(fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex_be, sizeof(ifindex_be)) < 0) + return -errno; + + return 0; + + case AF_INET6: + if (setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_IF, &ifindex_be, sizeof(ifindex_be)) < 0) + return -errno; + + return 0; + + default: + return -EAFNOSUPPORT; + } +} + +int socket_set_freebind(int fd, int af, bool b) { + int r; + + if (af == AF_UNSPEC) { + r = socket_get_family(fd, &af); + if (r < 0) + return r; + } + + switch (af) { + + case AF_INET: + return setsockopt_int(fd, IPPROTO_IP, IP_FREEBIND, b); + + case AF_INET6: + return setsockopt_int(fd, IPPROTO_IPV6, IPV6_FREEBIND, b); + + default: + return -EAFNOSUPPORT; + } +} + +int socket_set_transparent(int fd, int af, bool b) { + int r; + + if (af == AF_UNSPEC) { + r = socket_get_family(fd, &af); + if (r < 0) + return r; + } + + switch (af) { + + case AF_INET: + return setsockopt_int(fd, IPPROTO_IP, IP_TRANSPARENT, b); + + case AF_INET6: + return setsockopt_int(fd, IPPROTO_IPV6, IPV6_TRANSPARENT, b); + + default: + return -EAFNOSUPPORT; + } +} diff --git a/shared/systemd/src/basic/socket-util.h b/shared/systemd/src/basic/socket-util.h index 5e5cf7318..1ece91181 100644 --- a/shared/systemd/src/basic/socket-util.h +++ b/shared/systemd/src/basic/socket-util.h @@ -120,15 +120,26 @@ int netlink_family_from_string(const char *s) _pure_; bool sockaddr_equal(const union sockaddr_union *a, const union sockaddr_union *b); -int fd_inc_sndbuf(int fd, size_t n); -int fd_inc_rcvbuf(int fd, size_t n); +int fd_set_sndbuf(int fd, size_t n, bool increase); +static inline int fd_inc_sndbuf(int fd, size_t n) { + return fd_set_sndbuf(fd, n, true); +} +int fd_set_rcvbuf(int fd, size_t n, bool increase); +static inline int fd_inc_rcvbuf(int fd, size_t n) { + return fd_set_rcvbuf(fd, n, true); +} int ip_tos_to_string_alloc(int i, char **s); int ip_tos_from_string(const char *s); -bool ifname_valid_full(const char *p, bool alternative); +typedef enum { + IFNAME_VALID_ALTERNATIVE = 1 << 0, + IFNAME_VALID_NUMERIC = 1 << 1, + _IFNAME_VALID_ALL = IFNAME_VALID_ALTERNATIVE | IFNAME_VALID_NUMERIC, +} IfnameValidFlags; +bool ifname_valid_full(const char *p, IfnameValidFlags flags); static inline bool ifname_valid(const char *p) { - return ifname_valid_full(p, false); + return ifname_valid_full(p, 0); } bool address_label_valid(const char *p); @@ -207,6 +218,35 @@ struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t leng strnlen(_sa->sun_path, sizeof(_sa->sun_path))+1); \ }) +#define SOCKADDR_LEN(sa) \ + ({ \ + const union sockaddr_union *__sa = &(sa); \ + size_t _len; \ + switch(__sa->sa.sa_family) { \ + case AF_INET: \ + _len = sizeof(struct sockaddr_in); \ + break; \ + case AF_INET6: \ + _len = sizeof(struct sockaddr_in6); \ + break; \ + case AF_UNIX: \ + _len = SOCKADDR_UN_LEN(__sa->un); \ + break; \ + case AF_PACKET: \ + _len = SOCKADDR_LL_LEN(__sa->ll); \ + break; \ + case AF_NETLINK: \ + _len = sizeof(struct sockaddr_nl); \ + break; \ + case AF_VSOCK: \ + _len = sizeof(struct sockaddr_vm); \ + break; \ + default: \ + assert_not_reached("invalid socket family"); \ + } \ + _len; \ + }) + int socket_ioctl_fd(void); int sockaddr_un_set_path(struct sockaddr_un *ret, const char *path); @@ -223,4 +263,11 @@ int socket_bind_to_ifindex(int fd, int ifindex); ssize_t recvmsg_safe(int sockfd, struct msghdr *msg, int flags); -int socket_pass_pktinfo(int fd, bool b); +int socket_get_family(int fd, int *ret); +int socket_set_recvpktinfo(int fd, int af, bool b); +int socket_set_recverr(int fd, int af, bool b); +int socket_set_recvttl(int fd, int af, bool b); +int socket_set_ttl(int fd, int af, int ttl); +int socket_set_unicast_if(int fd, int af, int ifi); +int socket_set_freebind(int fd, int af, bool b); +int socket_set_transparent(int fd, int af, bool b); diff --git a/shared/systemd/src/basic/stat-util.c b/shared/systemd/src/basic/stat-util.c index 5c51e13a4..6d393041a 100644 --- a/shared/systemd/src/basic/stat-util.c +++ b/shared/systemd/src/basic/stat-util.c @@ -17,6 +17,7 @@ #include "macro.h" #include "missing_fs.h" #include "missing_magic.h" +#include "missing_syscall.h" #include "parse-util.h" #include "stat-util.h" #include "string-util.h" @@ -420,4 +421,60 @@ bool stat_inode_unmodified(const struct stat *a, const struct stat *b) { a->st_ino == b->st_ino && (!(S_ISCHR(a->st_mode) || S_ISBLK(a->st_mode)) || a->st_rdev == b->st_rdev); /* if device node, also compare major/minor, because we can */ } + +int statx_fallback(int dfd, const char *path, int flags, unsigned mask, struct statx *sx) { + static bool avoid_statx = false; + struct stat st; + + if (!avoid_statx) { + if (statx(dfd, path, flags, mask, sx) < 0) { + if (!ERRNO_IS_NOT_SUPPORTED(errno) && errno != EPERM) + return -errno; + + /* If statx() is not supported or if we see EPERM (which might indicate seccomp + * filtering or so), let's do a fallback. Not that on EACCES we'll not fall back, + * since that is likely an indication of fs access issues, which we should + * propagate */ + } else + return 0; + + avoid_statx = true; + } + + /* Only do fallback if fstatat() supports the flag too, or if it's one of the sync flags, which are + * OK to ignore */ + if ((flags & ~(AT_EMPTY_PATH|AT_NO_AUTOMOUNT|AT_SYMLINK_NOFOLLOW| + AT_STATX_SYNC_AS_STAT|AT_STATX_FORCE_SYNC|AT_STATX_DONT_SYNC)) != 0) + return -EOPNOTSUPP; + + if (fstatat(dfd, path, &st, flags & (AT_EMPTY_PATH|AT_NO_AUTOMOUNT|AT_SYMLINK_NOFOLLOW)) < 0) + return -errno; + + *sx = (struct statx) { + .stx_mask = STATX_TYPE|STATX_MODE| + STATX_NLINK|STATX_UID|STATX_GID| + STATX_ATIME|STATX_MTIME|STATX_CTIME| + STATX_INO|STATX_SIZE|STATX_BLOCKS, + .stx_blksize = st.st_blksize, + .stx_nlink = st.st_nlink, + .stx_uid = st.st_uid, + .stx_gid = st.st_gid, + .stx_mode = st.st_mode, + .stx_ino = st.st_ino, + .stx_size = st.st_size, + .stx_blocks = st.st_blocks, + .stx_rdev_major = major(st.st_rdev), + .stx_rdev_minor = minor(st.st_rdev), + .stx_dev_major = major(st.st_dev), + .stx_dev_minor = minor(st.st_dev), + .stx_atime.tv_sec = st.st_atim.tv_sec, + .stx_atime.tv_nsec = st.st_atim.tv_nsec, + .stx_mtime.tv_sec = st.st_mtim.tv_sec, + .stx_mtime.tv_nsec = st.st_mtim.tv_nsec, + .stx_ctime.tv_sec = st.st_ctim.tv_sec, + .stx_ctime.tv_nsec = st.st_ctim.tv_nsec, + }; + + return 0; +} #endif /* NM_IGNORED */ diff --git a/shared/systemd/src/basic/stat-util.h b/shared/systemd/src/basic/stat-util.h index 59aedcb7c..26ecd635f 100644 --- a/shared/systemd/src/basic/stat-util.h +++ b/shared/systemd/src/basic/stat-util.h @@ -10,6 +10,7 @@ #include #include "macro.h" +#include "missing_stat.h" int is_symlink(const char *path); int is_dir(const char *path, bool follow); @@ -91,3 +92,24 @@ int device_path_parse_major_minor(const char *path, mode_t *ret_mode, dev_t *ret int proc_mounted(void); bool stat_inode_unmodified(const struct stat *a, const struct stat *b); + +int statx_fallback(int dfd, const char *path, int flags, unsigned mask, struct statx *sx); + +#if HAS_FEATURE_MEMORY_SANITIZER +# warning "Explicitly initializing struct statx, to work around msan limitation. Please remove as soon as msan has been updated to not require this." +# define STRUCT_STATX_DEFINE(var) \ + struct statx var = {} +# define STRUCT_NEW_STATX_DEFINE(var) \ + union { \ + struct statx sx; \ + struct new_statx nsx; \ + } var = {} +#else +# define STRUCT_STATX_DEFINE(var) \ + struct statx var +# define STRUCT_NEW_STATX_DEFINE(var) \ + union { \ + struct statx sx; \ + struct new_statx nsx; \ + } var +#endif diff --git a/shared/systemd/src/basic/string-util.c b/shared/systemd/src/basic/string-util.c index c30e88c59..aea13dcb9 100644 --- a/shared/systemd/src/basic/string-util.c +++ b/shared/systemd/src/basic/string-util.c @@ -10,12 +10,14 @@ #include "alloc-util.h" #include "escape.h" +#include "extract-word.h" #include "fileio.h" #include "gunicode.h" #include "locale-util.h" #include "macro.h" #include "memory-util.h" #include "string-util.h" +#include "strv.h" #include "terminal-util.h" #include "utf8.h" #include "util.h" @@ -112,83 +114,6 @@ char* first_word(const char *s, const char *word) { return (char*) p; } -static size_t strcspn_escaped(const char *s, const char *reject) { - bool escaped = false; - int n; - - for (n = 0; s[n] != '\0'; n++) { - if (escaped) - escaped = false; - else if (s[n] == '\\') - escaped = true; - else if (strchr(reject, s[n])) - break; - } - - return n; -} - -/* Split a string into words. */ -const char* split( - const char **state, - size_t *l, - const char *separator, - SplitFlags flags) { - - const char *current; - - assert(state); - assert(l); - - if (!separator) - separator = WHITESPACE; - - current = *state; - - if (*current == '\0') /* already at the end? */ - return NULL; - - current += strspn(current, separator); /* skip leading separators */ - if (*current == '\0') { /* at the end now? */ - *state = current; - return NULL; - } - - if (FLAGS_SET(flags, SPLIT_QUOTES)) { - - if (strchr(QUOTES, *current)) { - /* We are looking at a quote */ - *l = strcspn_escaped(current + 1, CHAR_TO_STR(*current)); - if (current[*l + 1] != *current || - (current[*l + 2] != 0 && !strchr(separator, current[*l + 2]))) { - /* right quote missing or garbage at the end */ - if (FLAGS_SET(flags, SPLIT_RELAX)) { - *state = current + *l + 1 + (current[*l + 1] != '\0'); - return current + 1; - } - *state = current; - return NULL; - } - *state = current++ + *l + 2; - - } else { - /* We are looking at a something that is not a quote */ - *l = strcspn_escaped(current, separator); - if (current[*l] && !strchr(separator, current[*l]) && !FLAGS_SET(flags, SPLIT_RELAX)) { - /* unfinished escape */ - *state = current; - return NULL; - } - *state = current + *l; - } - } else { - *l = strcspn(current, separator); - *state = current + *l; - } - - return current; -} - char *strnappend(const char *s, const char *suffix, size_t b) { size_t a; char *r; @@ -1216,4 +1141,31 @@ int string_extract_line(const char *s, size_t i, char **ret) { c++; } } + +int string_contains_word_strv(const char *string, const char *separators, char **words, const char **ret_word) { + /* In the default mode with no separators specified, we split on whitespace and + * don't coalesce separators. */ + const ExtractFlags flags = separators ? EXTRACT_DONT_COALESCE_SEPARATORS : 0; + + const char *found = NULL; + + for (const char *p = string;;) { + _cleanup_free_ char *w = NULL; + int r; + + r = extract_first_word(&p, &w, separators, flags); + if (r < 0) + return r; + if (r == 0) + break; + + found = strv_find(words, w); + if (found) + break; + } + + if (ret_word) + *ret_word = found; + return !!found; +} #endif /* NM_IGNORED */ diff --git a/shared/systemd/src/basic/string-util.h b/shared/systemd/src/basic/string-util.h index 09131455b..cefbda357 100644 --- a/shared/systemd/src/basic/string-util.h +++ b/shared/systemd/src/basic/string-util.h @@ -108,24 +108,6 @@ char *endswith_no_case(const char *s, const char *postfix) _pure_; char *first_word(const char *s, const char *word) _pure_; -typedef enum SplitFlags { - SPLIT_QUOTES = 0x01 << 0, - SPLIT_RELAX = 0x01 << 1, -} SplitFlags; - -/* Smelly. Do not use this anymore. Use extract_first_word() instead! */ -const char* split(const char **state, size_t *l, const char *separator, SplitFlags flags); - -/* Similar, don't use this anymore */ -#define FOREACH_WORD(word, length, s, state) \ - _FOREACH_WORD(word, length, s, WHITESPACE, 0, state) - -#define FOREACH_WORD_SEPARATOR(word, length, s, separator, state) \ - _FOREACH_WORD(word, length, s, separator, 0, state) - -#define _FOREACH_WORD(word, length, s, separator, flags, state) \ - for ((state) = (s), (word) = split(&(state), &(length), (separator), (flags)); (word); (word) = split(&(state), &(length), (separator), (flags))) - char *strnappend(const char *s, const char *suffix, size_t length); char *strjoin_real(const char *x, ...) _sentinel_; @@ -135,8 +117,8 @@ char *strjoin_real(const char *x, ...) _sentinel_; ({ \ const char *_appendees_[] = { a, __VA_ARGS__ }; \ char *_d_, *_p_; \ - size_t _len_ = 0; \ - size_t _i_; \ + size_t _len_ = 0; \ + size_t _i_; \ for (_i_ = 0; _i_ < ELEMENTSOF(_appendees_) && _appendees_[_i_]; _i_++) \ _len_ += strlen(_appendees_[_i_]); \ _p_ = _d_ = newa(char, _len_ + 1); \ @@ -152,7 +134,6 @@ 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; @@ -231,11 +212,9 @@ REENABLE_WARNING; /* Like startswith(), but operates on arbitrary memory blocks */ static inline void *memory_startswith(const void *p, size_t sz, const char *token) { - size_t n; - assert(token); - n = strlen(token); + size_t n = strlen(token); if (sz < n) return NULL; @@ -251,20 +230,17 @@ static inline void *memory_startswith(const void *p, size_t sz, const char *toke * It works only for ASCII strings. */ static inline void *memory_startswith_no_case(const void *p, size_t sz, const char *token) { - size_t n, i; - assert(token); - n = strlen(token); + size_t n = strlen(token); if (sz < n) return NULL; assert(p); - for (i = 0; i < n; i++) { + for (size_t i = 0; i < n; i++) if (ascii_tolower(((char *)p)[i]) != ascii_tolower(token[i])) return NULL; - } return (uint8_t*) p + n; } @@ -286,3 +262,8 @@ char* string_erase(char *x); int string_truncate_lines(const char *s, size_t n_lines, char **ret); int string_extract_line(const char *s, size_t i, char **ret); + +int string_contains_word_strv(const char *string, const char *separators, char **words, const char **ret_word); +static inline int string_contains_word(const char *string, const char *separators, const char *word) { + return string_contains_word_strv(string, separators, STRV_MAKE(word), NULL); +} diff --git a/shared/systemd/src/basic/strv.c b/shared/systemd/src/basic/strv.c index b7678a88c..fcb31d1ef 100644 --- a/shared/systemd/src/basic/strv.c +++ b/shared/systemd/src/basic/strv.c @@ -260,44 +260,6 @@ int strv_extend_strv_concat(char ***a, char * const *b, const char *suffix) { } #endif /* NM_IGNORED */ -char **strv_split_full(const char *s, const char *separator, SplitFlags flags) { - const char *word, *state; - size_t l; - size_t n, i; - char **r; - - assert(s); - - if (!separator) - separator = WHITESPACE; - - s += strspn(s, separator); - if (isempty(s)) - return new0(char*, 1); - - n = 0; - _FOREACH_WORD(word, l, s, separator, flags, state) - n++; - - r = new(char*, n+1); - if (!r) - return NULL; - - i = 0; - _FOREACH_WORD(word, l, s, separator, flags, state) { - r[i] = strndup(word, l); - if (!r[i]) { - strv_free(r); - return NULL; - } - - i++; - } - - r[i] = NULL; - return r; -} - char **strv_split_newlines(const char *s) { char **l; size_t n; @@ -321,8 +283,7 @@ char **strv_split_newlines(const char *s) { return l; } -#if 0 /* NM_IGNORED */ -int strv_split_extract(char ***t, const char *s, const char *separators, ExtractFlags flags) { +int strv_split_full(char ***t, const char *s, const char *separators, ExtractFlags flags) { _cleanup_strv_free_ char **l = NULL; size_t n = 0, allocated = 0; int r; @@ -358,6 +319,7 @@ int strv_split_extract(char ***t, const char *s, const char *separators, Extract return (int) n; } +#if 0 /* NM_IGNORED */ int strv_split_colon_pairs(char ***t, const char *s) { _cleanup_strv_free_ char **l = NULL; size_t n = 0, allocated = 0; diff --git a/shared/systemd/src/basic/strv.h b/shared/systemd/src/basic/strv.h index e57dfff69..9468edc6a 100644 --- a/shared/systemd/src/basic/strv.h +++ b/shared/systemd/src/basic/strv.h @@ -72,13 +72,19 @@ static inline bool strv_isempty(char * const *l) { return !l || !*l; } -char **strv_split_full(const char *s, const char *separator, SplitFlags flags); -static inline char **strv_split(const char *s, const char *separator) { - return strv_split_full(s, separator, 0); -} char **strv_split_newlines(const char *s); -int strv_split_extract(char ***t, const char *s, const char *separators, ExtractFlags flags); +int strv_split_full(char ***t, const char *s, const char *separators, ExtractFlags flags); +static inline char **strv_split(const char *s, const char *separators) { + char **ret; + int r; + + r = strv_split_full(&ret, s, separators, 0); + if (r < 0) + return NULL; + + return ret; +} /* Given a string containing white-space separated tuples of words themselves separated by ':', * returns a vector of strings. If the second element in a tuple is missing, the corresponding @@ -123,10 +129,6 @@ bool strv_overlap(char * const *a, char * const *b) _pure_; char **strv_sort(char **l); void strv_print(char * const *l); -#define STRV_MAKE(...) ((char**) ((const char*[]) { __VA_ARGS__, NULL })) - -#define STRV_MAKE_EMPTY ((char*[1]) { NULL }) - #define strv_from_stdarg_alloca(first) \ ({ \ char **_l; \ diff --git a/shared/systemd/src/basic/time-util.c b/shared/systemd/src/basic/time-util.c index 3979dd7cc..0fac79a72 100644 --- a/shared/systemd/src/basic/time-util.c +++ b/shared/systemd/src/basic/time-util.c @@ -25,6 +25,7 @@ #include "path-util.h" #include "process-util.h" #include "stat-util.h" +#include "string-table.h" #include "string-util.h" #include "strv.h" #include "time-util.h" @@ -245,12 +246,28 @@ struct timespec *timespec_store(struct timespec *ts, usec_t u) { if (u == USEC_INFINITY || u / USEC_PER_SEC >= TIME_T_MAX) { ts->tv_sec = (time_t) -1; - ts->tv_nsec = (long) -1; + ts->tv_nsec = -1L; return ts; } ts->tv_sec = (time_t) (u / USEC_PER_SEC); - ts->tv_nsec = (long int) ((u % USEC_PER_SEC) * NSEC_PER_USEC); + ts->tv_nsec = (long) ((u % USEC_PER_SEC) * NSEC_PER_USEC); + + return ts; +} + +struct timespec *timespec_store_nsec(struct timespec *ts, nsec_t n) { + assert(ts); + + if (n == NSEC_INFINITY || + n / NSEC_PER_SEC >= TIME_T_MAX) { + ts->tv_sec = (time_t) -1; + ts->tv_nsec = -1L; + return ts; + } + + ts->tv_sec = (time_t) (n / NSEC_PER_SEC); + ts->tv_nsec = (long) (n % NSEC_PER_SEC); return ts; } @@ -285,12 +302,11 @@ struct timeval *timeval_store(struct timeval *tv, usec_t u) { return tv; } -static char *format_timestamp_internal( +char *format_timestamp_style( char *buf, size_t l, usec_t t, - bool utc, - bool us) { + TimestampStyle style) { /* The weekdays in non-localized (English) form. We use this instead of the localized form, so that our * generated timestamps may be parsed with parse_timestamp(), and always read the same. */ @@ -307,9 +323,27 @@ static char *format_timestamp_internal( struct tm tm; time_t sec; size_t n; + bool utc = false, us = false; assert(buf); + switch (style) { + case TIMESTAMP_PRETTY: + break; + case TIMESTAMP_US: + us = true; + break; + case TIMESTAMP_UTC: + utc = true; + break; + case TIMESTAMP_US_UTC: + us = true; + utc = true; + break; + default: + return NULL; + } + if (l < (size_t) (3 + /* week day */ 1 + 10 + /* space and date */ 1 + 8 + /* space and time */ @@ -383,22 +417,6 @@ static char *format_timestamp_internal( return buf; } -char *format_timestamp(char *buf, size_t l, usec_t t) { - return format_timestamp_internal(buf, l, t, false, false); -} - -char *format_timestamp_utc(char *buf, size_t l, usec_t t) { - return format_timestamp_internal(buf, l, t, true, false); -} - -char *format_timestamp_us(char *buf, size_t l, usec_t t) { - return format_timestamp_internal(buf, l, t, false, true); -} - -char *format_timestamp_us_utc(char *buf, size_t l, usec_t t) { - return format_timestamp_internal(buf, l, t, true, true); -} - char *format_timestamp_relative(char *buf, size_t l, usec_t t) { const char *s; usec_t n, d; @@ -1575,4 +1593,28 @@ int time_change_fd(void) { return -errno; } + +static const char* const timestamp_style_table[_TIMESTAMP_STYLE_MAX] = { + [TIMESTAMP_PRETTY] = "pretty", + [TIMESTAMP_US] = "us", + [TIMESTAMP_UTC] = "utc", + [TIMESTAMP_US_UTC] = "us+utc", +}; + +/* Use the macro for enum → string to allow for aliases */ +_DEFINE_STRING_TABLE_LOOKUP_TO_STRING(timestamp_style, TimestampStyle,); + +/* For the string → enum mapping we use the generic implementation, but also support two aliases */ +TimestampStyle timestamp_style_from_string(const char *s) { + TimestampStyle t; + + t = (TimestampStyle) string_table_lookup(timestamp_style_table, ELEMENTSOF(timestamp_style_table), s); + if (t >= 0) + return t; + if (streq_ptr(s, "µs")) + return TIMESTAMP_US; + if (streq_ptr(s, "µs+uts")) + return TIMESTAMP_US_UTC; + return t; +} #endif /* NM_IGNORED */ diff --git a/shared/systemd/src/basic/time-util.h b/shared/systemd/src/basic/time-util.h index 9bbe98630..cecd5efa6 100644 --- a/shared/systemd/src/basic/time-util.h +++ b/shared/systemd/src/basic/time-util.h @@ -29,6 +29,15 @@ typedef struct triple_timestamp { usec_t boottime; } triple_timestamp; +typedef enum TimestampStyle { + TIMESTAMP_PRETTY, + TIMESTAMP_US, + TIMESTAMP_UTC, + TIMESTAMP_US_UTC, + _TIMESTAMP_STYLE_MAX, + _TIMESTAMP_STYLE_INVALID = -1, +} TimestampStyle; + #define USEC_INFINITY ((usec_t) UINT64_MAX) #define NSEC_INFINITY ((nsec_t) UINT64_MAX) @@ -103,17 +112,19 @@ usec_t triple_timestamp_by_clock(triple_timestamp *ts, clockid_t clock); usec_t timespec_load(const struct timespec *ts) _pure_; nsec_t timespec_load_nsec(const struct timespec *ts) _pure_; struct timespec *timespec_store(struct timespec *ts, usec_t u); +struct timespec *timespec_store_nsec(struct timespec *ts, nsec_t n); usec_t timeval_load(const struct timeval *tv) _pure_; struct timeval *timeval_store(struct timeval *tv, usec_t u); -char *format_timestamp(char *buf, size_t l, usec_t t); -char *format_timestamp_utc(char *buf, size_t l, usec_t t); -char *format_timestamp_us(char *buf, size_t l, usec_t t); -char *format_timestamp_us_utc(char *buf, size_t l, usec_t t); +char *format_timestamp_style(char *buf, size_t l, usec_t t, TimestampStyle style); char *format_timestamp_relative(char *buf, size_t l, usec_t t); char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy); +static inline char *format_timestamp(char *buf, size_t l, usec_t t) { + return format_timestamp_style(buf, l, t, TIMESTAMP_PRETTY); +} + int parse_timestamp(const char *t, usec_t *usec); int parse_sec(const char *t, usec_t *usec); @@ -185,3 +196,6 @@ static inline usec_t usec_sub_signed(usec_t timestamp, int64_t delta) { #endif int time_change_fd(void); + +const char* timestamp_style_to_string(TimestampStyle t) _const_; +TimestampStyle timestamp_style_from_string(const char *s) _pure_; diff --git a/shared/systemd/src/basic/utf8.c b/shared/systemd/src/basic/utf8.c index f2e27b683..8159b1875 100644 --- a/shared/systemd/src/basic/utf8.c +++ b/shared/systemd/src/basic/utf8.c @@ -125,7 +125,7 @@ int utf8_encoded_to_unichar(const char *str, char32_t *ret_unichar) { return 0; } -bool utf8_is_printable_newline(const char* str, size_t length, bool newline) { +bool utf8_is_printable_newline(const char* str, size_t length, bool allow_newline) { const char *p; assert(str); @@ -142,7 +142,7 @@ bool utf8_is_printable_newline(const char* str, size_t length, bool newline) { r = utf8_encoded_to_unichar(p, &val); if (r < 0 || unichar_is_control(val) || - (!newline && val == '\n')) + (!allow_newline && val == '\n')) return false; length -= encoded_len; @@ -152,18 +152,22 @@ bool utf8_is_printable_newline(const char* str, size_t length, bool newline) { return true; } -char *utf8_is_valid(const char *str) { - const char *p; +char *utf8_is_valid_n(const char *str, size_t len_bytes) { + /* Check if the string is composed of valid utf8 characters. If length len_bytes is given, stop after + * len_bytes. Otherwise, stop at NUL. */ assert(str); - p = str; - while (*p) { + for (const char *p = str; len_bytes != (size_t) -1 ? (size_t) (p - str) < len_bytes : *p != '\0'; ) { int len; - len = utf8_encoded_valid_unichar(p, (size_t) -1); - if (len < 0) - return NULL; + if (_unlikely_(*p == '\0') && len_bytes != (size_t) -1) + return NULL; /* embedded NUL */ + + len = utf8_encoded_valid_unichar(p, + len_bytes != (size_t) -1 ? len_bytes - (p - str) : (size_t) -1); + if (_unlikely_(len < 0)) + return NULL; /* invalid character */ p += len; } diff --git a/shared/systemd/src/basic/utf8.h b/shared/systemd/src/basic/utf8.h index 62e99b728..f315ea0f1 100644 --- a/shared/systemd/src/basic/utf8.h +++ b/shared/systemd/src/basic/utf8.h @@ -14,11 +14,14 @@ bool unichar_is_valid(char32_t c); -char *utf8_is_valid(const char *s) _pure_; +char *utf8_is_valid_n(const char *str, size_t len_bytes) _pure_; +static inline char *utf8_is_valid(const char *s) { + return utf8_is_valid_n(s, (size_t) -1); +} char *ascii_is_valid(const char *s) _pure_; char *ascii_is_valid_n(const char *str, size_t len); -bool utf8_is_printable_newline(const char* str, size_t length, bool newline) _pure_; +bool utf8_is_printable_newline(const char* str, size_t length, bool allow_newline) _pure_; #define utf8_is_printable(str, length) utf8_is_printable_newline(str, length, true) char *utf8_escape_invalid(const char *s); diff --git a/src/systemd/src/libsystemd-network/arp-util.c b/src/systemd/src/libsystemd-network/arp-util.c index e48e4bfe6..b2ac2c9c4 100644 --- a/src/systemd/src/libsystemd-network/arp-util.c +++ b/src/systemd/src/libsystemd-network/arp-util.c @@ -78,7 +78,7 @@ int arp_network_bind_raw_socket(int ifindex, be32_t address, const struct ether_ assert(ifindex > 0); - s = socket(PF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0); + s = socket(AF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0); if (s < 0) return -errno; diff --git a/src/systemd/src/libsystemd-network/dhcp-option.c b/src/systemd/src/libsystemd-network/dhcp-option.c index 491938793..3a0f51557 100644 --- a/src/systemd/src/libsystemd-network/dhcp-option.c +++ b/src/systemd/src/libsystemd-network/dhcp-option.c @@ -83,9 +83,8 @@ static int option_append(uint8_t options[], size_t size, size_t *offset, OrderedHashmap *s = (OrderedHashmap *) optval; struct sd_dhcp_option *p; size_t l = 0; - Iterator i; - ORDERED_HASHMAP_FOREACH(p, s, i) + ORDERED_HASHMAP_FOREACH(p, s) l += p->length + 2; if (*offset + l + 2 > size) @@ -96,7 +95,7 @@ static int option_append(uint8_t options[], size_t size, size_t *offset, *offset += 2; - ORDERED_HASHMAP_FOREACH(p, s, i) { + ORDERED_HASHMAP_FOREACH(p, s) { options[*offset] = p->option; options[*offset + 1] = p->length; memcpy(&options[*offset + 2], p->data, p->length); diff --git a/src/systemd/src/libsystemd-network/dhcp6-option.c b/src/systemd/src/libsystemd-network/dhcp6-option.c index a6dad9340..25da477d2 100644 --- a/src/systemd/src/libsystemd-network/dhcp6-option.c +++ b/src/systemd/src/libsystemd-network/dhcp6-option.c @@ -83,7 +83,6 @@ int dhcp6_option_append(uint8_t **buf, size_t *buflen, uint16_t code, int dhcp6_option_append_vendor_option(uint8_t **buf, size_t *buflen, OrderedHashmap *vendor_options) { sd_dhcp6_option *options; - Iterator i; int r; assert(buf); @@ -91,7 +90,7 @@ int dhcp6_option_append_vendor_option(uint8_t **buf, size_t *buflen, OrderedHash assert(buflen); assert(vendor_options); - ORDERED_HASHMAP_FOREACH(options, vendor_options, i) { + ORDERED_HASHMAP_FOREACH(options, vendor_options) { _cleanup_free_ uint8_t *p = NULL; size_t total; diff --git a/src/systemd/src/libsystemd-network/lldp-network.c b/src/systemd/src/libsystemd-network/lldp-network.c index f4764dd14..85d53e710 100644 --- a/src/systemd/src/libsystemd-network/lldp-network.c +++ b/src/systemd/src/libsystemd-network/lldp-network.c @@ -49,7 +49,7 @@ int lldp_network_bind_raw_socket(int ifindex) { assert(ifindex > 0); - fd = socket(PF_PACKET, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, + fd = socket(AF_PACKET, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, htobe16(ETHERTYPE_LLDP)); if (fd < 0) return -errno; diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-client.c b/src/systemd/src/libsystemd-network/sd-dhcp-client.c index 806b83ae4..6849ed9e2 100644 --- a/src/systemd/src/libsystemd-network/sd-dhcp-client.c +++ b/src/systemd/src/libsystemd-network/sd-dhcp-client.c @@ -924,7 +924,6 @@ static int dhcp_client_send_raw( static int client_append_common_discover_request_options(sd_dhcp_client *client, DHCPPacket *packet, size_t *optoffset, size_t optlen) { sd_dhcp_option *j; - Iterator i; int r; assert(client); @@ -975,7 +974,7 @@ static int client_append_common_discover_request_options(sd_dhcp_client *client, return r; } - ORDERED_HASHMAP_FOREACH(j, client->extra_options, i) { + ORDERED_HASHMAP_FOREACH(j, client->extra_options) { r = dhcp_option_append(&packet->dhcp, optlen, optoffset, 0, j->option, j->length, j->data); if (r < 0) diff --git a/src/systemd/src/libsystemd-network/sd-dhcp6-client.c b/src/systemd/src/libsystemd-network/sd-dhcp6-client.c index 3e5042265..86cbf06f4 100644 --- a/src/systemd/src/libsystemd-network/sd-dhcp6-client.c +++ b/src/systemd/src/libsystemd-network/sd-dhcp6-client.c @@ -630,7 +630,6 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) { IN6ADDR_ALL_DHCP6_RELAY_AGENTS_AND_SERVERS_INIT; struct sd_dhcp6_option *j; size_t len, optlen = 512; - Iterator i; uint8_t *opt; int r; usec_t elapsed_usec; @@ -865,7 +864,7 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) { if (r < 0) return r; - ORDERED_HASHMAP_FOREACH(j, client->extra_options, i) { + ORDERED_HASHMAP_FOREACH(j, client->extra_options) { r = dhcp6_option_append(&opt, &optlen, j->option, j->length, j->data); if (r < 0) return r; @@ -1701,7 +1700,7 @@ int sd_dhcp6_client_is_running(sd_dhcp6_client *client) { int sd_dhcp6_client_start(sd_dhcp6_client *client) { enum DHCP6State state = DHCP6_STATE_SOLICITATION; - int r = 0; + int r; assert_return(client, -EINVAL); assert_return(client->event, -EINVAL); diff --git a/src/systemd/src/libsystemd-network/sd-ipv4acd.c b/src/systemd/src/libsystemd-network/sd-ipv4acd.c index 9f69088de..b9e3dce38 100644 --- a/src/systemd/src/libsystemd-network/sd-ipv4acd.c +++ b/src/systemd/src/libsystemd-network/sd-ipv4acd.c @@ -144,10 +144,17 @@ static void ipv4acd_client_notify(sd_ipv4acd *acd, int event) { } int sd_ipv4acd_stop(sd_ipv4acd *acd) { + IPv4ACDState old_state; + assert_return(acd, -EINVAL); + old_state = acd->state; + ipv4acd_reset(acd); + if (old_state == IPV4ACD_STATE_INIT) + return 0; + log_ipv4acd(acd, "STOPPED"); ipv4acd_client_notify(acd, SD_IPV4ACD_EVENT_STOP); @@ -437,6 +444,15 @@ int sd_ipv4acd_set_address(sd_ipv4acd *acd, const struct in_addr *address) { return 0; } +int sd_ipv4acd_get_address(sd_ipv4acd *acd, struct in_addr *address) { + assert_return(acd, -EINVAL); + assert_return(address, -EINVAL); + + address->s_addr = acd->address; + + return 0; +} + int sd_ipv4acd_is_running(sd_ipv4acd *acd) { assert_return(acd, false); @@ -457,8 +473,7 @@ int sd_ipv4acd_start(sd_ipv4acd *acd, bool reset_conflicts) { if (r < 0) return r; - safe_close(acd->fd); - acd->fd = r; + CLOSE_AND_REPLACE(acd->fd, r); acd->defend_window = 0; if (reset_conflicts) diff --git a/src/systemd/src/libsystemd-network/sd-lldp.c b/src/systemd/src/libsystemd-network/sd-lldp.c index eb083f5ea..524b1bab0 100644 --- a/src/systemd/src/libsystemd-network/sd-lldp.c +++ b/src/systemd/src/libsystemd-network/sd-lldp.c @@ -433,7 +433,6 @@ static int lldp_start_timer(sd_lldp *lldp, sd_lldp_neighbor *neighbor) { _public_ int sd_lldp_get_neighbors(sd_lldp *lldp, sd_lldp_neighbor ***ret) { sd_lldp_neighbor **l = NULL, *n; - Iterator i; int k = 0, r; assert_return(lldp, -EINVAL); @@ -454,7 +453,7 @@ _public_ int sd_lldp_get_neighbors(sd_lldp *lldp, sd_lldp_neighbor ***ret) { return r; } - HASHMAP_FOREACH(n, lldp->neighbor_by_id, i) + HASHMAP_FOREACH(n, lldp->neighbor_by_id) l[k++] = sd_lldp_neighbor_ref(n); assert((size_t) k == hashmap_size(lldp->neighbor_by_id)); diff --git a/src/systemd/src/libsystemd/sd-event/sd-event.c b/src/systemd/src/libsystemd/sd-event/sd-event.c index 8b7691d0a..d5993a22b 100644 --- a/src/systemd/src/libsystemd/sd-event/sd-event.c +++ b/src/systemd/src/libsystemd/sd-event/sd-event.c @@ -2874,7 +2874,6 @@ static int process_timer( static int process_child(sd_event *e) { sd_event_source *s; - Iterator i; int r; assert(e); @@ -2899,7 +2898,7 @@ static int process_child(sd_event *e) { the callback still sees the process as a zombie. */ - HASHMAP_FOREACH(s, e->child_sources, i) { + HASHMAP_FOREACH(s, e->child_sources) { assert(s->type == SOURCE_CHILD); if (s->pending) @@ -3104,12 +3103,11 @@ static int event_inotify_data_process(sd_event *e, struct inotify_data *d) { if (d->buffer.ev.mask & IN_Q_OVERFLOW) { struct inode_data *inode_data; - Iterator i; /* The queue overran, let's pass this event to all event sources connected to this inotify * object */ - HASHMAP_FOREACH(inode_data, d->inodes, i) { + HASHMAP_FOREACH(inode_data, d->inodes) { sd_event_source *s; LIST_FOREACH(inotify.by_inode_data, s, inode_data->event_sources) { @@ -3207,12 +3205,11 @@ static int source_dispatch(sd_event_source *s) { if (s->type != SOURCE_POST) { sd_event_source *z; - Iterator i; /* If we execute a non-post source, let's mark all * post sources as pending */ - SET_FOREACH(z, s->event->post_sources, i) { + SET_FOREACH(z, s->event->post_sources) { if (z->enabled == SD_EVENT_OFF) continue;