diff --git a/Makefile.am b/Makefile.am index 6650c59ab..b6602346c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1632,6 +1632,7 @@ shared_systemd_libnm_systemd_shared_la_SOURCES = \ shared/systemd/src/basic/macro.h \ shared/systemd/src/basic/mempool.c \ shared/systemd/src/basic/mempool.h \ + shared/systemd/src/basic/missing_fcntl.h \ shared/systemd/src/basic/missing_type.h \ shared/systemd/src/basic/parse-util.c \ shared/systemd/src/basic/parse-util.h \ diff --git a/shared/systemd/sd-adapt-shared/missing.h b/shared/systemd/sd-adapt-shared/missing.h index 637892c2d..2ee34b6ad 100644 --- a/shared/systemd/sd-adapt-shared/missing.h +++ b/shared/systemd/sd-adapt-shared/missing.h @@ -1,3 +1,6 @@ #pragma once /* dummy header */ + +#include "missing_fcntl.h" +#include "missing_type.h" diff --git a/shared/systemd/src/basic/alloc-util.h b/shared/systemd/src/basic/alloc-util.h index ff7a46793..893a1238f 100644 --- a/shared/systemd/src/basic/alloc-util.h +++ b/shared/systemd/src/basic/alloc-util.h @@ -10,20 +10,28 @@ typedef void (*free_func_t)(void *p); +/* If for some reason more than 4M are allocated on the stack, let's abort immediately. It's better than + * proceeding and smashing the stack limits. Note that by default RLIMIT_STACK is 8M on Linux. */ +#define ALLOCA_MAX (4U*1024U*1024U) + #define new(t, n) ((t*) malloc_multiply(sizeof(t), (n))) #define new0(t, n) ((t*) calloc((n) ?: 1, sizeof(t))) -#define newa(t, n) \ - ({ \ - assert(!size_multiply_overflow(sizeof(t), n)); \ - (t*) alloca(sizeof(t)*(n)); \ +#define newa(t, n) \ + ({ \ + size_t _n_ = n; \ + assert(!size_multiply_overflow(sizeof(t), _n_)); \ + assert(sizeof(t)*_n_ <= ALLOCA_MAX); \ + (t*) alloca(sizeof(t)*_n_); \ }) -#define newa0(t, n) \ - ({ \ - assert(!size_multiply_overflow(sizeof(t), n)); \ - (t*) alloca0(sizeof(t)*(n)); \ +#define newa0(t, n) \ + ({ \ + size_t _n_ = n; \ + assert(!size_multiply_overflow(sizeof(t), _n_)); \ + assert(sizeof(t)*_n_ <= ALLOCA_MAX); \ + (t*) alloca0(sizeof(t)*_n_); \ }) #define newdup(t, p, n) ((t*) memdup_multiply(p, sizeof(t), (n))) @@ -51,16 +59,20 @@ void* memdup_suffix0(const void *p, size_t l) _alloc_(2); #define memdupa(p, l) \ ({ \ void *_q_; \ - _q_ = alloca(l); \ - memcpy(_q_, p, l); \ + size_t _l_ = l; \ + assert(_l_ <= ALLOCA_MAX); \ + _q_ = alloca(_l_); \ + memcpy(_q_, p, _l_); \ }) #define memdupa_suffix0(p, l) \ ({ \ void *_q_; \ - _q_ = alloca(l + 1); \ - ((uint8_t*) _q_)[l] = 0; \ - memcpy(_q_, p, l); \ + size_t _l_ = l; \ + assert(_l_ <= ALLOCA_MAX); \ + _q_ = alloca(_l_ + 1); \ + ((uint8_t*) _q_)[_l_] = 0; \ + memcpy(_q_, p, _l_); \ }) static inline void freep(void *p) { @@ -116,6 +128,7 @@ void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size); ({ \ char *_new_; \ size_t _len_ = n; \ + assert(_len_ <= ALLOCA_MAX); \ _new_ = alloca(_len_); \ (void *) memset(_new_, 0, _len_); \ }) @@ -125,16 +138,18 @@ void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size); ({ \ void *_ptr_; \ size_t _mask_ = (align) - 1; \ - _ptr_ = alloca((size) + _mask_); \ + size_t _size_ = size; \ + assert(_size_ <= ALLOCA_MAX); \ + _ptr_ = alloca(_size_ + _mask_); \ (void*)(((uintptr_t)_ptr_ + _mask_) & ~_mask_); \ }) #define alloca0_align(size, align) \ ({ \ void *_new_; \ - size_t _size_ = (size); \ - _new_ = alloca_align(_size_, (align)); \ - (void*)memset(_new_, 0, _size_); \ + size_t _xsize_ = (size); \ + _new_ = alloca_align(_xsize_, (align)); \ + (void*)memset(_new_, 0, _xsize_); \ }) /* Takes inspiration from Rusts's Option::take() method: reads and returns a pointer, but at the same time resets it to diff --git a/shared/systemd/src/basic/env-file.c b/shared/systemd/src/basic/env-file.c index beafd8c20..4babe7530 100644 --- a/shared/systemd/src/basic/env-file.c +++ b/shared/systemd/src/basic/env-file.c @@ -37,7 +37,6 @@ static int parse_env_file_internal( VALUE, VALUE_ESCAPE, SINGLE_QUOTE_VALUE, - SINGLE_QUOTE_VALUE_ESCAPE, DOUBLE_QUOTE_VALUE, DOUBLE_QUOTE_VALUE_ESCAPE, COMMENT, @@ -115,7 +114,7 @@ static int parse_env_file_internal( } else if (c == '\'') state = SINGLE_QUOTE_VALUE; - else if (c == '\"') + else if (c == '"') state = DOUBLE_QUOTE_VALUE; else if (c == '\\') state = VALUE_ESCAPE; @@ -188,8 +187,6 @@ static int parse_env_file_internal( case SINGLE_QUOTE_VALUE: if (c == '\'') state = PRE_VALUE; - else if (c == '\\') - state = SINGLE_QUOTE_VALUE_ESCAPE; else { if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) return -ENOMEM; @@ -199,19 +196,8 @@ static int parse_env_file_internal( break; - case SINGLE_QUOTE_VALUE_ESCAPE: - state = SINGLE_QUOTE_VALUE; - - if (!strchr(NEWLINE, c)) { - if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) - return -ENOMEM; - - value[n_value++] = c; - } - break; - case DOUBLE_QUOTE_VALUE: - if (c == '\"') + if (c == '"') state = PRE_VALUE; else if (c == '\\') state = DOUBLE_QUOTE_VALUE_ESCAPE; @@ -227,12 +213,17 @@ static int parse_env_file_internal( case DOUBLE_QUOTE_VALUE_ESCAPE: state = DOUBLE_QUOTE_VALUE; - if (!strchr(NEWLINE, c)) { + if (c == '"') { if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) return -ENOMEM; - + value[n_value++] = '"'; + } else if (!strchr(NEWLINE, c)) { + if (!GREEDY_REALLOC(value, value_alloc, n_value+3)) + return -ENOMEM; + value[n_value++] = '\\'; value[n_value++] = c; } + break; case COMMENT: @@ -255,7 +246,6 @@ static int parse_env_file_internal( VALUE, VALUE_ESCAPE, SINGLE_QUOTE_VALUE, - SINGLE_QUOTE_VALUE_ESCAPE, DOUBLE_QUOTE_VALUE, DOUBLE_QUOTE_VALUE_ESCAPE)) { @@ -530,7 +520,7 @@ static void write_env_var(FILE *f, const char *v) { fwrite_unlocked(v, 1, p-v, f); if (string_has_cc(p, NULL) || chars_intersect(p, WHITESPACE SHELL_NEED_QUOTES)) { - fputc_unlocked('\"', f); + fputc_unlocked('"', f); for (; *p; p++) { if (strchr(SHELL_NEED_ESCAPE, *p)) @@ -539,7 +529,7 @@ static void write_env_var(FILE *f, const char *v) { fputc_unlocked(*p, f); } - fputc_unlocked('\"', f); + fputc_unlocked('"', f); } else fputs_unlocked(p, f); diff --git a/shared/systemd/src/basic/env-util.c b/shared/systemd/src/basic/env-util.c index fd9eedc53..dc10362d0 100644 --- a/shared/systemd/src/basic/env-util.c +++ b/shared/systemd/src/basic/env-util.c @@ -342,7 +342,6 @@ char **strv_env_unset(char **l, const char *p) { } char **strv_env_unset_many(char **l, ...) { - char **f, **t; if (!l) @@ -411,7 +410,6 @@ int strv_env_replace(char ***l, char *p) { } char **strv_env_set(char **x, const char *p) { - _cleanup_strv_free_ char **ret = NULL; size_t n, m; char **k; diff --git a/shared/systemd/src/basic/env-util.h b/shared/systemd/src/basic/env-util.h index 4d21ea6be..d54f99658 100644 --- a/shared/systemd/src/basic/env-util.h +++ b/shared/systemd/src/basic/env-util.h @@ -13,9 +13,9 @@ bool env_value_is_valid(const char *e); bool env_assignment_is_valid(const char *e); enum { - REPLACE_ENV_USE_ENVIRONMENT = 1u, - REPLACE_ENV_ALLOW_BRACELESS = 2u, - REPLACE_ENV_ALLOW_EXTENDED = 4u, + REPLACE_ENV_USE_ENVIRONMENT = 1 << 0, + REPLACE_ENV_ALLOW_BRACELESS = 1 << 1, + REPLACE_ENV_ALLOW_EXTENDED = 1 << 2, }; char *replace_env_n(const char *format, size_t n, char **env, unsigned flags); diff --git a/shared/systemd/src/basic/extract-word.h b/shared/systemd/src/basic/extract-word.h index 8c63b7c30..705ebbe95 100644 --- a/shared/systemd/src/basic/extract-word.h +++ b/shared/systemd/src/basic/extract-word.h @@ -4,12 +4,12 @@ #include "macro.h" typedef enum ExtractFlags { - EXTRACT_RELAX = 1, - EXTRACT_CUNESCAPE = 2, - EXTRACT_CUNESCAPE_RELAX = 4, - EXTRACT_QUOTES = 8, - EXTRACT_DONT_COALESCE_SEPARATORS = 16, - EXTRACT_RETAIN_ESCAPE = 32, + EXTRACT_RELAX = 1 << 0, + EXTRACT_CUNESCAPE = 1 << 1, + EXTRACT_CUNESCAPE_RELAX = 1 << 2, + EXTRACT_QUOTES = 1 << 3, + EXTRACT_DONT_COALESCE_SEPARATORS = 1 << 4, + EXTRACT_RETAIN_ESCAPE = 1 << 5, } ExtractFlags; 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 e160a2826..0cc0c6b5e 100644 --- a/shared/systemd/src/basic/fd-util.c +++ b/shared/systemd/src/basic/fd-util.c @@ -192,6 +192,27 @@ _pure_ static bool fd_in_set(int fd, const int fdset[], size_t n_fdset) { return false; } +static int get_max_fd(void) { + struct rlimit rl; + rlim_t m; + + /* Return the highest possible fd, based RLIMIT_NOFILE, but enforcing FD_SETSIZE-1 as lower boundary + * and INT_MAX as upper boundary. */ + + if (getrlimit(RLIMIT_NOFILE, &rl) < 0) + return -errno; + + m = MAX(rl.rlim_cur, rl.rlim_max); + if (m < FD_SETSIZE) /* Let's always cover at least 1024 fds */ + return FD_SETSIZE-1; + + if (m == RLIM_INFINITY || m > INT_MAX) /* Saturate on overflow. After all fds are "int", hence can + * never be above INT_MAX */ + return INT_MAX; + + return (int) (m - 1); +} + int close_all_fds(const int except[], size_t n_except) { _cleanup_closedir_ DIR *d = NULL; struct dirent *de; @@ -201,20 +222,14 @@ int close_all_fds(const int except[], size_t n_except) { d = opendir("/proc/self/fd"); if (!d) { - struct rlimit rl; int fd, max_fd; - /* When /proc isn't available (for example in chroots) the fallback is brute forcing through the fd - * table */ + /* When /proc isn't available (for example in chroots) the fallback is brute forcing through + * the fd table */ - assert_se(getrlimit(RLIMIT_NOFILE, &rl) >= 0); - - if (rl.rlim_max == 0) - return -EINVAL; - - /* Let's take special care if the resource limit is set to unlimited, or actually larger than the range - * of 'int'. Let's avoid implicit overflows. */ - max_fd = (rl.rlim_max == RLIM_INFINITY || rl.rlim_max > INT_MAX) ? INT_MAX : (int) (rl.rlim_max - 1); + max_fd = get_max_fd(); + if (max_fd < 0) + return max_fd; for (fd = 3; fd >= 0; fd = fd < max_fd ? fd + 1 : -1) { int q; diff --git a/shared/systemd/src/basic/hashmap.c b/shared/systemd/src/basic/hashmap.c index 9c3a6d5a4..9cb2f9486 100644 --- a/shared/systemd/src/basic/hashmap.c +++ b/shared/systemd/src/basic/hashmap.c @@ -347,7 +347,7 @@ static unsigned base_bucket_hash(HashmapBase *h, const void *p) { } #define bucket_hash(h, p) base_bucket_hash(HASHMAP_BASE(h), p) -static inline void base_set_dirty(HashmapBase *h) { +static void base_set_dirty(HashmapBase *h) { h->dirty = true; } #define hashmap_set_dirty(h) base_set_dirty(HASHMAP_BASE(h)) diff --git a/shared/systemd/src/basic/hashmap.h b/shared/systemd/src/basic/hashmap.h index 5bf807a76..e16a9f9e3 100644 --- a/shared/systemd/src/basic/hashmap.h +++ b/shared/systemd/src/basic/hashmap.h @@ -326,7 +326,6 @@ static inline void *ordered_hashmap_first_key_and_value(OrderedHashmap *h, void return internal_hashmap_first_key_and_value(HASHMAP_BASE(h), false, ret); } - static inline void *hashmap_steal_first(Hashmap *h) { return internal_hashmap_first_key_and_value(HASHMAP_BASE(h), true, NULL); } diff --git a/shared/systemd/src/basic/in-addr-util.c b/shared/systemd/src/basic/in-addr-util.c index d2cc56062..62b3147a5 100644 --- a/shared/systemd/src/basic/in-addr-util.c +++ b/shared/systemd/src/basic/in-addr-util.c @@ -500,9 +500,8 @@ int in_addr_parse_prefixlen(int family, const char *p, unsigned char *ret) { return 0; } -int in_addr_prefix_from_string_internal( +int in_addr_prefix_from_string( const char *p, - bool use_default_prefixlen, int family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen) { @@ -536,13 +535,6 @@ int in_addr_prefix_from_string_internal( r = in_addr_parse_prefixlen(family, e+1, &k); if (r < 0) return r; - } else if (use_default_prefixlen) { - if (family == AF_INET) { - r = in4_addr_default_prefixlen(&buffer.in, &k); - if (r < 0) - return r; - } else - k = 0; } else k = FAMILY_ADDRESS_SIZE(family) * 8; @@ -556,7 +548,7 @@ int in_addr_prefix_from_string_internal( int in_addr_prefix_from_string_auto_internal( const char *p, - bool use_default_prefixlen, + InAddrPrefixLenMode mode, int *ret_family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen) { @@ -587,15 +579,24 @@ int in_addr_prefix_from_string_auto_internal( r = in_addr_parse_prefixlen(family, e+1, &k); if (r < 0) return r; - } else if (use_default_prefixlen) { - if (family == AF_INET) { - r = in4_addr_default_prefixlen(&buffer.in, &k); - if (r < 0) - return r; - } else - k = 0; } else - k = FAMILY_ADDRESS_SIZE(family) * 8; + switch (mode) { + case PREFIXLEN_FULL: + k = FAMILY_ADDRESS_SIZE(family) * 8; + break; + case PREFIXLEN_REFUSE: + return -ENOANO; /* To distinguish this error from others. */ + case PREFIXLEN_LEGACY: + if (family == AF_INET) { + r = in4_addr_default_prefixlen(&buffer.in, &k); + if (r < 0) + return r; + } else + k = 0; + break; + default: + assert_not_reached("Invalid prefixlen mode"); + } if (ret_family) *ret_family = family; diff --git a/shared/systemd/src/basic/in-addr-util.h b/shared/systemd/src/basic/in-addr-util.h index 5de85cc42..306979051 100644 --- a/shared/systemd/src/basic/in-addr-util.h +++ b/shared/systemd/src/basic/in-addr-util.h @@ -45,19 +45,17 @@ int in4_addr_default_subnet_mask(const struct in_addr *addr, struct in_addr *mas int in_addr_mask(int family, union in_addr_union *addr, unsigned char prefixlen); int in_addr_prefix_covers(int family, const union in_addr_union *prefix, unsigned char prefixlen, const union in_addr_union *address); int in_addr_parse_prefixlen(int family, const char *p, unsigned char *ret); -int in_addr_prefix_from_string_internal(const char *p, bool use_default_prefixlen, int family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen); -int in_addr_prefix_from_string_auto_internal(const char *p, bool use_default_prefixlen, int *ret_family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen); -static inline int in_addr_prefix_from_string(const char *p, int family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen) { - return in_addr_prefix_from_string_internal(p, false, family, ret_prefix, ret_prefixlen); -} +int in_addr_prefix_from_string(const char *p, int family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen); + +typedef enum InAddrPrefixLenMode { + PREFIXLEN_FULL, /* Default to prefixlen of address size, 32 for IPv4 or 128 for IPv6, if not specified. */ + PREFIXLEN_REFUSE, /* Fail with -ENOANO if prefixlen is not specified. */ + PREFIXLEN_LEGACY, /* Default to legacy default prefixlen calculation from address if not specified. */ +} InAddrPrefixLenMode; + +int in_addr_prefix_from_string_auto_internal(const char *p, InAddrPrefixLenMode mode, int *ret_family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen); static inline int in_addr_prefix_from_string_auto(const char *p, int *ret_family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen) { - return in_addr_prefix_from_string_auto_internal(p, false, ret_family, ret_prefix, ret_prefixlen); -} -static inline int in_addr_default_prefix_from_string(const char *p, int family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen) { - return in_addr_prefix_from_string_internal(p, true, family, ret_prefix, ret_prefixlen); -} -static inline int in_addr_default_prefix_from_string_auto(const char *p, int *ret_family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen) { - return in_addr_prefix_from_string_auto_internal(p, true, ret_family, ret_prefix, ret_prefixlen); + return in_addr_prefix_from_string_auto_internal(p, PREFIXLEN_FULL, ret_family, ret_prefix, ret_prefixlen); } static inline size_t FAMILY_ADDRESS_SIZE(int family) { diff --git a/shared/systemd/src/basic/io-util.c b/shared/systemd/src/basic/io-util.c index f7c259154..3f47eff55 100644 --- a/shared/systemd/src/basic/io-util.c +++ b/shared/systemd/src/basic/io-util.c @@ -10,8 +10,10 @@ #include #include "io-util.h" +#include "string-util.h" #include "time-util.h" +#if 0 /* NM_IGNORED */ int flush_fd(int fd) { struct pollfd pollfd = { .fd = fd, @@ -55,6 +57,7 @@ int flush_fd(int fd) { count += (int) l; } } +#endif /* NM_IGNORED */ ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll) { uint8_t *p = buf; @@ -115,6 +118,7 @@ int loop_read_exact(int fd, void *buf, size_t nbytes, bool do_poll) { return 0; } +#if 0 /* NM_IGNORED */ int loop_write(int fd, const void *buf, size_t nbytes, bool do_poll) { const uint8_t *p = buf; @@ -173,6 +177,7 @@ int pipe_eof(int fd) { return pollfd.revents & POLLHUP; } +#endif /* NM_IGNORED */ int fd_wait_for_event(int fd, int event, usec_t t) { @@ -193,6 +198,7 @@ int fd_wait_for_event(int fd, int event, usec_t t) { return pollfd.revents; } +#if 0 /* NM_IGNORED */ static size_t nul_length(const uint8_t *p, size_t sz) { size_t n = 0; @@ -254,3 +260,13 @@ ssize_t sparse_write(int fd, const void *p, size_t sz, size_t run_length) { return q - (const uint8_t*) p; } + +char* set_iovec_string_field(struct iovec *iovec, size_t *n_iovec, const char *field, const char *value) { + char *x; + + x = strappend(field, value); + if (x) + iovec[(*n_iovec)++] = IOVEC_MAKE_STRING(x); + return x; +} +#endif /* NM_IGNORED */ diff --git a/shared/systemd/src/basic/io-util.h b/shared/systemd/src/basic/io-util.h index ed189b582..792a64ad5 100644 --- a/shared/systemd/src/basic/io-util.h +++ b/shared/systemd/src/basic/io-util.h @@ -71,3 +71,5 @@ static inline bool FILE_SIZE_VALID_OR_INFINITY(uint64_t l) { #define IOVEC_MAKE(base, len) (struct iovec) IOVEC_INIT(base, len) #define IOVEC_INIT_STRING(string) IOVEC_INIT((char*) string, strlen(string)) #define IOVEC_MAKE_STRING(string) (struct iovec) IOVEC_INIT_STRING(string) + +char* set_iovec_string_field(struct iovec *iovec, size_t *n_iovec, const char *field, const char *value); diff --git a/shared/systemd/src/basic/missing_fcntl.h b/shared/systemd/src/basic/missing_fcntl.h new file mode 100644 index 000000000..5d1c6352f --- /dev/null +++ b/shared/systemd/src/basic/missing_fcntl.h @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#ifndef F_LINUX_SPECIFIC_BASE +#define F_LINUX_SPECIFIC_BASE 1024 +#endif + +#ifndef F_SETPIPE_SZ +#define F_SETPIPE_SZ (F_LINUX_SPECIFIC_BASE + 7) +#endif + +#ifndef F_GETPIPE_SZ +#define F_GETPIPE_SZ (F_LINUX_SPECIFIC_BASE + 8) +#endif + +#ifndef F_ADD_SEALS +#define F_ADD_SEALS (F_LINUX_SPECIFIC_BASE + 9) +#define F_GET_SEALS (F_LINUX_SPECIFIC_BASE + 10) + +#define F_SEAL_SEAL 0x0001 /* prevent further seals from being set */ +#define F_SEAL_SHRINK 0x0002 /* prevent file from shrinking */ +#define F_SEAL_GROW 0x0004 /* prevent file from growing */ +#define F_SEAL_WRITE 0x0008 /* prevent writes */ +#endif + +#ifndef F_OFD_GETLK +#define F_OFD_GETLK 36 +#define F_OFD_SETLK 37 +#define F_OFD_SETLKW 38 +#endif + +#ifndef MAX_HANDLE_SZ +#define MAX_HANDLE_SZ 128 +#endif + +/* The precise definition of __O_TMPFILE is arch specific; use the + * values defined by the kernel (note: some are hexa, some are octal, + * duplicated as-is from the kernel definitions): + * - alpha, parisc, sparc: each has a specific value; + * - others: they use the "generic" value. + */ + +#ifndef __O_TMPFILE +#if defined(__alpha__) +#define __O_TMPFILE 0100000000 +#elif defined(__parisc__) || defined(__hppa__) +#define __O_TMPFILE 0400000000 +#elif defined(__sparc__) || defined(__sparc64__) +#define __O_TMPFILE 0x2000000 +#else +#define __O_TMPFILE 020000000 +#endif +#endif + +/* a horrid kludge trying to make sure that this will fail on old kernels */ +#ifndef O_TMPFILE +#define O_TMPFILE (__O_TMPFILE | O_DIRECTORY) +#endif diff --git a/shared/systemd/src/basic/path-util.h b/shared/systemd/src/basic/path-util.h index 56ebd59c6..5204adaa1 100644 --- a/shared/systemd/src/basic/path-util.h +++ b/shared/systemd/src/basic/path-util.h @@ -133,7 +133,7 @@ char *prefix_root(const char *root, const char *path); _ret = _path; \ else { \ _l = strlen(_root) + 1 + strlen(_path) + 1; \ - _n = alloca(_l); \ + _n = newa(char, _l); \ _p = stpcpy(_n, _root); \ while (_p > _n && _p[-1] == '/') \ _p--; \ diff --git a/shared/systemd/src/basic/prioq.c b/shared/systemd/src/basic/prioq.c index b218f37d9..dc048cc73 100644 --- a/shared/systemd/src/basic/prioq.c +++ b/shared/systemd/src/basic/prioq.c @@ -261,15 +261,14 @@ int prioq_reshuffle(Prioq *q, void *data, unsigned *idx) { return 1; } -void *prioq_peek(Prioq *q) { - +void *prioq_peek_by_index(Prioq *q, unsigned idx) { if (!q) return NULL; - if (q->n_items <= 0) + if (idx >= q->n_items) return NULL; - return q->items[0].data; + return q->items[idx].data; } void *prioq_pop(Prioq *q) { diff --git a/shared/systemd/src/basic/prioq.h b/shared/systemd/src/basic/prioq.h index bba5c7caa..1fb57bfa4 100644 --- a/shared/systemd/src/basic/prioq.h +++ b/shared/systemd/src/basic/prioq.h @@ -19,8 +19,14 @@ int prioq_put(Prioq *q, void *data, unsigned *idx); int prioq_remove(Prioq *q, void *data, unsigned *idx); int prioq_reshuffle(Prioq *q, void *data, unsigned *idx); -void *prioq_peek(Prioq *q) _pure_; +void *prioq_peek_by_index(Prioq *q, unsigned idx) _pure_; +static inline void *prioq_peek(Prioq *q) { + return prioq_peek_by_index(q, 0); +} void *prioq_pop(Prioq *q); +#define PRIOQ_FOREACH_ITEM(q, p) \ + for (unsigned _i = 0; (p = prioq_peek_by_index(q, _i)); _i++) + unsigned prioq_size(Prioq *q) _pure_; bool prioq_isempty(Prioq *q) _pure_; diff --git a/shared/systemd/src/basic/process-util.c b/shared/systemd/src/basic/process-util.c index be7911a3a..b0afb5c82 100644 --- a/shared/systemd/src/basic/process-util.c +++ b/shared/systemd/src/basic/process-util.c @@ -107,7 +107,8 @@ int get_process_comm(pid_t pid, char **ret) { int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char **line) { _cleanup_fclose_ FILE *f = NULL; bool space = false; - char *k, *ans = NULL; + char *k; + _cleanup_free_ char *ans = NULL; const char *p; int c; @@ -134,6 +135,13 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char * (void) __fsetlocking(f, FSETLOCKING_BYCALLER); + if (max_length == 0) { + /* This is supposed to be a safety guard against runaway command lines. */ + long l = sysconf(_SC_ARG_MAX); + assert(l > 0); + max_length = l; + } + if (max_length == 1) { /* If there's only room for one byte, return the empty string */ @@ -141,35 +149,9 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char * if (!ans) return -ENOMEM; - *line = ans; + *line = TAKE_PTR(ans); return 0; - } else if (max_length == 0) { - size_t len = 0, allocated = 0; - - while ((c = getc(f)) != EOF) { - - if (!GREEDY_REALLOC(ans, allocated, len+3)) { - free(ans); - return -ENOMEM; - } - - if (isprint(c)) { - if (space) { - ans[len++] = ' '; - space = false; - } - - ans[len++] = c; - } else if (len > 0) - space = true; - } - - if (len > 0) - ans[len] = '\0'; - else - ans = mfree(ans); - } else { bool dotdotdot = false; size_t left; @@ -232,7 +214,7 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char * _cleanup_free_ char *t = NULL; int h; - free(ans); + ans = mfree(ans); if (!comm_fallback) return -ENOENT; @@ -241,37 +223,42 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char * if (h < 0) return h; - if (max_length == 0) + size_t l = strlen(t); + + if (l + 3 <= max_length) { ans = strjoin("[", t, "]"); - else { - size_t l; + if (!ans) + return -ENOMEM; - l = strlen(t); + } else if (max_length <= 6) { + ans = new(char, max_length); + if (!ans) + return -ENOMEM; - if (l + 3 <= max_length) - ans = strjoin("[", t, "]"); - else if (max_length <= 6) { + memcpy(ans, "[...]", max_length-1); + ans[max_length-1] = 0; + } else { + t[max_length - 6] = 0; - ans = new(char, max_length); - if (!ans) - return -ENOMEM; + /* Chop off final spaces */ + delete_trailing_chars(t, WHITESPACE); - memcpy(ans, "[...]", max_length-1); - ans[max_length-1] = 0; - } else { - t[max_length - 6] = 0; - - /* Chop off final spaces */ - delete_trailing_chars(t, WHITESPACE); - - ans = strjoin("[", t, "...]"); - } + ans = strjoin("[", t, "...]"); + if (!ans) + return -ENOMEM; } - if (!ans) - return -ENOMEM; + + *line = TAKE_PTR(ans); + return 0; } - *line = ans; + k = realloc(ans, strlen(ans) + 1); + if (!k) + return -ENOMEM; + + ans = NULL; + *line = k; + return 0; } diff --git a/shared/systemd/src/basic/process-util.h b/shared/systemd/src/basic/process-util.h index 0fad4e1ee..0425042f6 100644 --- a/shared/systemd/src/basic/process-util.h +++ b/shared/systemd/src/basic/process-util.h @@ -24,8 +24,8 @@ if (_pid_ == 0) { \ _r_ = ("/proc/self/" field); \ } else { \ - _r_ = alloca(STRLEN("/proc/") + DECIMAL_STR_MAX(pid_t) + 1 + sizeof(field)); \ - sprintf((char*) _r_, "/proc/"PID_FMT"/" field, _pid_); \ + _r_ = newa(char, STRLEN("/proc/") + DECIMAL_STR_MAX(pid_t) + 1 + sizeof(field)); \ + sprintf((char*) _r_, "/proc/"PID_FMT"/" field, _pid_); \ } \ _r_; \ }) diff --git a/shared/systemd/src/basic/stat-util.c b/shared/systemd/src/basic/stat-util.c index 8843aba85..686adaf11 100644 --- a/shared/systemd/src/basic/stat-util.c +++ b/shared/systemd/src/basic/stat-util.c @@ -70,13 +70,22 @@ int is_device_node(const char *path) { return !!(S_ISBLK(info.st_mode) || S_ISCHR(info.st_mode)); } -int dir_is_empty(const char *path) { - _cleanup_closedir_ DIR *d; +int dir_is_empty_at(int dir_fd, const char *path) { + _cleanup_close_ int fd = -1; + _cleanup_closedir_ DIR *d = NULL; struct dirent *de; - d = opendir(path); + if (path) + fd = openat(dir_fd, path, O_RDONLY|O_DIRECTORY|O_CLOEXEC); + else + fd = fcntl(fd, F_DUPFD_CLOEXEC, 3); + if (fd < 0) + return -errno; + + d = fdopendir(fd); if (!d) return -errno; + fd = -1; FOREACH_DIRENT(de, d, return -errno) return 0; @@ -343,7 +352,6 @@ int device_path_make_major_minor(mode_t mode, dev_t devno, char **ret) { return -ENOMEM; return 0; - } int device_path_make_canonical(mode_t mode, dev_t devno, char **ret) { diff --git a/shared/systemd/src/basic/stat-util.h b/shared/systemd/src/basic/stat-util.h index 0a08e642b..74fb7251b 100644 --- a/shared/systemd/src/basic/stat-util.h +++ b/shared/systemd/src/basic/stat-util.h @@ -15,7 +15,10 @@ int is_dir(const char *path, bool follow); int is_dir_fd(int fd); int is_device_node(const char *path); -int dir_is_empty(const char *path); +int dir_is_empty_at(int dir_fd, const char *path); +static inline int dir_is_empty(const char *path) { + return dir_is_empty_at(AT_FDCWD, path); +} static inline int dir_is_populated(const char *path) { int r; diff --git a/shared/systemd/src/basic/string-util.h b/shared/systemd/src/basic/string-util.h index a5b5a16a5..38070abb2 100644 --- a/shared/systemd/src/basic/string-util.h +++ b/shared/systemd/src/basic/string-util.h @@ -6,6 +6,7 @@ #include #include +#include "alloc-util.h" #include "macro.h" /* What is interpreted as whitespace? */ @@ -111,7 +112,7 @@ char *strjoin_real(const char *x, ...) _sentinel_; size_t _i_; \ for (_i_ = 0; _i_ < ELEMENTSOF(_appendees_) && _appendees_[_i_]; _i_++) \ _len_ += strlen(_appendees_[_i_]); \ - _p_ = _d_ = alloca(_len_ + 1); \ + _p_ = _d_ = newa(char, _len_ + 1); \ for (_i_ = 0; _i_ < ELEMENTSOF(_appendees_) && _appendees_[_i_]; _i_++) \ _p_ = stpcpy(_p_, _appendees_[_i_]); \ *_p_ = 0; \ diff --git a/shared/systemd/src/basic/strv.h b/shared/systemd/src/basic/strv.h index aa4cd4aac..392cab65b 100644 --- a/shared/systemd/src/basic/strv.h +++ b/shared/systemd/src/basic/strv.h @@ -156,17 +156,10 @@ void strv_print(char **l); _found; \ }) -#define FOREACH_STRING(x, ...) \ - for (char **_l = ({ \ - char **_ll = STRV_MAKE(__VA_ARGS__); \ - x = _ll ? _ll[0] : NULL; \ - _ll; \ - }); \ - _l && *_l; \ - x = ({ \ - _l ++; \ - _l[0]; \ - })) +#define FOREACH_STRING(x, y, ...) \ + for (char **_l = STRV_MAKE(({ x = y; }), ##__VA_ARGS__); \ + x; \ + x = *(++_l)) char **strv_reverse(char **l); char **strv_shell_escape(char **l, const char *bad); diff --git a/shared/systemd/src/basic/tmpfile-util.c b/shared/systemd/src/basic/tmpfile-util.c index 06e325f08..019121cb3 100644 --- a/shared/systemd/src/basic/tmpfile-util.c +++ b/shared/systemd/src/basic/tmpfile-util.c @@ -10,6 +10,7 @@ #include "hexdecoct.h" #include "macro.h" #include "memfd-util.h" +#include "missing_fcntl.h" #include "missing_syscall.h" #include "path-util.h" #include "process-util.h" diff --git a/src/systemd/src/libsystemd-network/dhcp-identifier.c b/src/systemd/src/libsystemd-network/dhcp-identifier.c index 6d932c249..7fc8248a7 100644 --- a/src/systemd/src/libsystemd-network/dhcp-identifier.c +++ b/src/systemd/src/libsystemd-network/dhcp-identifier.c @@ -13,6 +13,7 @@ #include "network-internal.h" #include "siphash24.h" #include "sparse-endian.h" +#include "stdio-util.h" #include "virt.h" #define SYSTEMD_PEN 43793 @@ -176,10 +177,10 @@ int dhcp_identifier_set_iaid( if (detect_container() <= 0) { /* not in a container, udev will be around */ - char ifindex_str[2 + DECIMAL_STR_MAX(int)]; + char ifindex_str[1 + DECIMAL_STR_MAX(int)]; int r; - sprintf(ifindex_str, "n%d", ifindex); + xsprintf(ifindex_str, "n%d", ifindex); if (sd_device_new_from_device_id(&device, ifindex_str) >= 0) { r = sd_device_get_is_initialized(device); if (r < 0) diff --git a/src/systemd/src/libsystemd-network/network-internal.c b/src/systemd/src/libsystemd-network/network-internal.c index d33c4febc..f03a30f4b 100644 --- a/src/systemd/src/libsystemd-network/network-internal.c +++ b/src/systemd/src/libsystemd-network/network-internal.c @@ -55,7 +55,7 @@ int net_get_unique_predictable_data(sd_device *device, uint64_t *result) { l = strlen(name); sz = sizeof(sd_id128_t) + l; - v = alloca(sz); + v = newa(uint8_t, sz); /* fetch some persistent data unique to this machine */ r = sd_id128_get_machine((sd_id128_t*) v); diff --git a/src/systemd/src/libsystemd/sd-event/sd-event.c b/src/systemd/src/libsystemd/sd-event/sd-event.c index e49cc9d86..6f77421b0 100644 --- a/src/systemd/src/libsystemd/sd-event/sd-event.c +++ b/src/systemd/src/libsystemd/sd-event/sd-event.c @@ -472,6 +472,17 @@ static struct clock_data* event_get_clock_data(sd_event *e, EventSourceType t) { } } +static void event_free_signal_data(sd_event *e, struct signal_data *d) { + assert(e); + + if (!d) + return; + + hashmap_remove(e->signal_data, &d->priority); + safe_close(d->fd); + free(d); +} + static int event_make_signal_data( sd_event *e, int sig, @@ -561,11 +572,8 @@ static int event_make_signal_data( return 0; fail: - if (added) { - d->fd = safe_close(d->fd); - hashmap_remove(e->signal_data, &d->priority); - free(d); - } + if (added) + event_free_signal_data(e, d); return r; } @@ -584,11 +592,8 @@ static void event_unmask_signal_data(sd_event *e, struct signal_data *d, int sig assert_se(sigdelset(&d->sigset, sig) >= 0); if (sigisemptyset(&d->sigset)) { - /* If all the mask is all-zero we can get rid of the structure */ - hashmap_remove(e->signal_data, &d->priority); - safe_close(d->fd); - free(d); + event_free_signal_data(e, d); return; }