summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2018-10-28 08:59:02 +0100
committerThomas Haller <thaller@redhat.com>2018-10-28 09:31:31 +0100
commit3648c58bc5f0e5195ad946b8a3e5efe65c89e4c0 (patch)
treeb7726e07e32f8fa623e07aef47c42ab50b99db56
parentef7312a3ae3527e68738b2a7325aaae969fc7355 (diff)
parent5437448a6404376f2e8fdadff329682bfe9c992e (diff)
downloadNetworkManager-3648c58bc5f0e5195ad946b8a3e5efe65c89e4c0.tar.gz
systemd: merge branch systemd into master
-rw-r--r--Makefile.am1
-rw-r--r--src/systemd/nm-sd.c4
-rw-r--r--src/systemd/sd-adapt/serialize.h3
-rw-r--r--src/systemd/src/basic/alloc-util.h15
-rw-r--r--src/systemd/src/basic/env-util.c157
-rw-r--r--src/systemd/src/basic/env-util.h3
-rw-r--r--src/systemd/src/basic/fd-util.c24
-rw-r--r--src/systemd/src/basic/fileio.c18
-rw-r--r--src/systemd/src/basic/fileio.h10
-rw-r--r--src/systemd/src/basic/fs-util.c32
-rw-r--r--src/systemd/src/basic/fs-util.h1
-rw-r--r--src/systemd/src/basic/hashmap.c63
-rw-r--r--src/systemd/src/basic/hashmap.h51
-rw-r--r--src/systemd/src/basic/list.h6
-rw-r--r--src/systemd/src/basic/macro.h25
-rw-r--r--src/systemd/src/basic/mempool.c18
-rw-r--r--src/systemd/src/basic/mempool.h4
-rw-r--r--src/systemd/src/basic/path-util.c20
-rw-r--r--src/systemd/src/basic/path-util.h1
-rw-r--r--src/systemd/src/basic/prioq.c13
-rw-r--r--src/systemd/src/basic/prioq.h1
-rw-r--r--src/systemd/src/basic/process-util.c46
-rw-r--r--src/systemd/src/basic/process-util.h9
-rw-r--r--src/systemd/src/basic/set.h4
-rw-r--r--src/systemd/src/basic/siphash24.h5
-rw-r--r--src/systemd/src/basic/socket-util.c146
-rw-r--r--src/systemd/src/basic/socket-util.h18
-rw-r--r--src/systemd/src/basic/string-util.c28
-rw-r--r--src/systemd/src/basic/string-util.h26
-rw-r--r--src/systemd/src/basic/strv.c9
-rw-r--r--src/systemd/src/basic/strv.h6
-rw-r--r--src/systemd/src/basic/time-util.c124
-rw-r--r--src/systemd/src/basic/time-util.h4
-rw-r--r--src/systemd/src/basic/util.c15
-rw-r--r--src/systemd/src/basic/util.h8
-rw-r--r--src/systemd/src/libsystemd-network/dhcp-network.c28
-rw-r--r--src/systemd/src/libsystemd-network/dhcp6-network.c14
-rw-r--r--src/systemd/src/libsystemd-network/sd-dhcp-client.c2
-rw-r--r--src/systemd/src/libsystemd/sd-event/sd-event.c66
-rw-r--r--src/systemd/src/systemd/sd-event.h3
40 files changed, 572 insertions, 459 deletions
diff --git a/Makefile.am b/Makefile.am
index a123d1fa1f..a57dbe4438 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1483,6 +1483,7 @@ src_libsystemd_nm_la_SOURCES = \
src/systemd/sd-adapt/raw-clone.h \
src/systemd/sd-adapt/sd-daemon.h \
src/systemd/sd-adapt/sd-device.h \
+ src/systemd/sd-adapt/serialize.h \
src/systemd/sd-adapt/stat-util.h \
src/systemd/sd-adapt/terminal-util.h \
src/systemd/sd-adapt/unaligned.h \
diff --git a/src/systemd/nm-sd.c b/src/systemd/nm-sd.c
index cbef91d1fe..44867ada4f 100644
--- a/src/systemd/nm-sd.c
+++ b/src/systemd/nm-sd.c
@@ -133,6 +133,10 @@ nm_sd_event_attach_default (void)
/*****************************************************************************/
+const bool mempool_use_allowed = true;
+
+/*****************************************************************************/
+
/* ensure that defines in nm-sd.h correspond to the internal defines. */
#include "nm-sd-adapt.h"
diff --git a/src/systemd/sd-adapt/serialize.h b/src/systemd/sd-adapt/serialize.h
new file mode 100644
index 0000000000..637892c2d6
--- /dev/null
+++ b/src/systemd/sd-adapt/serialize.h
@@ -0,0 +1,3 @@
+#pragma once
+
+/* dummy header */
diff --git a/src/systemd/src/basic/alloc-util.h b/src/systemd/src/basic/alloc-util.h
index ebe42889ea..2a6deb12ca 100644
--- a/src/systemd/src/basic/alloc-util.h
+++ b/src/systemd/src/basic/alloc-util.h
@@ -46,6 +46,21 @@ static inline void *mfree(void *memory) {
void* memdup(const void *p, size_t l) _alloc_(2);
void* memdup_suffix0(const void *p, size_t l) _alloc_(2);
+#define memdupa(p, l) \
+ ({ \
+ void *_q_; \
+ _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); \
+ })
+
static inline void freep(void *p) {
free(*(void**) p);
}
diff --git a/src/systemd/src/basic/env-util.c b/src/systemd/src/basic/env-util.c
index 36f3c2b7d7..1cd48a27e9 100644
--- a/src/systemd/src/basic/env-util.c
+++ b/src/systemd/src/basic/env-util.c
@@ -24,10 +24,6 @@
DIGITS LETTERS \
"_"
-#ifndef ARG_MAX
-#define ARG_MAX ((size_t) sysconf(_SC_ARG_MAX))
-#endif
-
static bool env_name_is_valid_n(const char *e, size_t n) {
const char *p;
@@ -45,7 +41,7 @@ static bool env_name_is_valid_n(const char *e, size_t n) {
* either. Discounting the equal sign and trailing NUL this
* hence leaves ARG_MAX-2 as longest possible variable
* name. */
- if (n > ARG_MAX - 2)
+ if (n > (size_t) sysconf(_SC_ARG_MAX) - 2)
return false;
for (p = e; p < e + n; p++)
@@ -79,7 +75,7 @@ bool env_value_is_valid(const char *e) {
* either. Discounting the shortest possible variable name of
* length 1, the equal sign and trailing NUL this hence leaves
* ARG_MAX-3 as longest possible variable value. */
- if (strlen(e) > ARG_MAX - 3)
+ if (strlen(e) > (size_t) sysconf(_SC_ARG_MAX) - 3)
return false;
return true;
@@ -102,7 +98,7 @@ bool env_assignment_is_valid(const char *e) {
* be > ARG_MAX, hence the individual variable assignments
* cannot be either, but let's leave room for one trailing NUL
* byte. */
- if (strlen(e) > ARG_MAX - 1)
+ if (strlen(e) > (size_t) sysconf(_SC_ARG_MAX) - 1)
return false;
return true;
@@ -128,30 +124,28 @@ bool strv_env_is_valid(char **e) {
}
bool strv_env_name_is_valid(char **l) {
- char **p, **q;
+ char **p;
STRV_FOREACH(p, l) {
if (!env_name_is_valid(*p))
return false;
- STRV_FOREACH(q, p + 1)
- if (streq(*p, *q))
- return false;
+ if (strv_contains(p + 1, *p))
+ return false;
}
return true;
}
bool strv_env_name_or_assignment_is_valid(char **l) {
- char **p, **q;
+ char **p;
STRV_FOREACH(p, l) {
if (!env_assignment_is_valid(*p) && !env_name_is_valid(*p))
return false;
- STRV_FOREACH(q, p + 1)
- if (streq(*p, *q))
- return false;
+ if (strv_contains(p + 1, *p))
+ return false;
}
return true;
@@ -160,20 +154,23 @@ bool strv_env_name_or_assignment_is_valid(char **l) {
static int env_append(char **r, char ***k, char **a) {
assert(r);
assert(k);
+ assert(*k >= r);
if (!a)
return 0;
- /* Add the entries of a to *k unless they already exist in *r
- * in which case they are overridden instead. This assumes
- * there is enough space in the r array. */
+ /* Expects the following arguments: 'r' shall point to the beginning of an strv we are going to append to, 'k'
+ * to a pointer pointing to the NULL entry at the end of the same array. 'a' shall point to another strv.
+ *
+ * This call adds every entry of 'a' to 'r', either overriding an existing matching entry, or appending to it.
+ *
+ * This call assumes 'r' has enough pre-allocated space to grow by all of 'a''s items. */
for (; *a; a++) {
- char **j;
+ char **j, *c;
size_t n;
n = strcspn(*a, "=");
-
if ((*a)[n] == '=')
n++;
@@ -181,24 +178,26 @@ static int env_append(char **r, char ***k, char **a) {
if (strneq(*j, *a, n))
break;
- if (j >= *k)
- (*k)++;
- else
- free(*j);
-
- *j = strdup(*a);
- if (!*j)
+ c = strdup(*a);
+ if (!c)
return -ENOMEM;
+
+ if (j >= *k) { /* Append to the end? */
+ (*k)[0] = c;
+ (*k)[1] = NULL;
+ (*k)++;
+ } else
+ free_and_replace(*j, c); /* Override existing item */
}
return 0;
}
char **strv_env_merge(size_t n_lists, ...) {
- size_t n = 0;
- char **l, **k, **r;
+ _cleanup_strv_free_ char **ret = NULL;
+ size_t n = 0, i;
+ char **l, **k;
va_list ap;
- size_t i;
/* Merges an arbitrary number of environment sets */
@@ -209,29 +208,24 @@ char **strv_env_merge(size_t n_lists, ...) {
}
va_end(ap);
- r = new(char*, n+1);
- if (!r)
+ ret = new(char*, n+1);
+ if (!ret)
return NULL;
- k = r;
+ *ret = NULL;
+ k = ret;
va_start(ap, n_lists);
for (i = 0; i < n_lists; i++) {
l = va_arg(ap, char**);
- if (env_append(r, &k, l) < 0)
- goto fail;
+ if (env_append(ret, &k, l) < 0) {
+ va_end(ap);
+ return NULL;
+ }
}
va_end(ap);
- *k = NULL;
-
- return r;
-
-fail:
- va_end(ap);
- strv_free(r);
-
- return NULL;
+ return TAKE_PTR(ret);
}
static bool env_match(const char *t, const char *pattern) {
@@ -385,22 +379,23 @@ char **strv_env_unset_many(char **l, ...) {
}
int strv_env_replace(char ***l, char *p) {
- char **f;
const char *t, *name;
+ char **f;
+ int r;
assert(p);
- /* Replace first occurrence of the env var or add a new one in the
- * string list. Drop other occurrences. Edits in-place. Does not copy p.
- * p must be a valid key=value assignment.
+ /* Replace first occurrence of the env var or add a new one in the string list. Drop other occurrences. Edits
+ * in-place. Does not copy p. p must be a valid key=value assignment.
*/
t = strchr(p, '=');
- assert(t);
+ if (!t)
+ return -EINVAL;
name = strndupa(p, t - p);
- for (f = *l; f && *f; f++)
+ STRV_FOREACH(f, *l)
if (env_entry_has_name(*f, name)) {
free_and_replace(*f, p);
strv_env_unset(f + 1, *f);
@@ -408,33 +403,40 @@ int strv_env_replace(char ***l, char *p) {
}
/* We didn't find a match, we need to append p or create a new strv */
- if (strv_push(l, p) < 0)
- return -ENOMEM;
+ r = strv_push(l, p);
+ if (r < 0)
+ return r;
+
return 1;
}
char **strv_env_set(char **x, const char *p) {
+ _cleanup_strv_free_ char **ret = NULL;
+ size_t n, m;
char **k;
- _cleanup_strv_free_ char **r = NULL;
- char* m[2] = { (char*) p, NULL };
/* Overrides the env var setting of p, returns a new copy */
- r = new(char*, strv_length(x)+2);
- if (!r)
+ n = strv_length(x);
+ m = n + 2;
+ if (m < n) /* overflow? */
return NULL;
- k = r;
- if (env_append(r, &k, x) < 0)
+ ret = new(char*, m);
+ if (!ret)
return NULL;
- if (env_append(r, &k, m) < 0)
+ *ret = NULL;
+ k = ret;
+
+ if (env_append(ret, &k, x) < 0)
return NULL;
- *k = NULL;
+ if (env_append(ret, &k, STRV_MAKE(p)) < 0)
+ return NULL;
- return TAKE_PTR(r);
+ return TAKE_PTR(ret);
}
char *strv_env_get_n(char **l, const char *name, size_t k, unsigned flags) {
@@ -755,37 +757,4 @@ int getenv_bool_secure(const char *p) {
return parse_boolean(e);
}
-
-int serialize_environment(FILE *f, char **environment) {
- char **e;
-
- STRV_FOREACH(e, environment) {
- _cleanup_free_ char *ce;
-
- ce = cescape(*e);
- if (!ce)
- return -ENOMEM;
-
- fprintf(f, "env=%s\n", ce);
- }
-
- /* caller should call ferror() */
-
- return 0;
-}
-
-int deserialize_environment(char ***environment, const char *line) {
- char *uce;
- int r;
-
- assert(line);
- assert(environment);
-
- assert(startswith(line, "env="));
- r = cunescape(line + 4, 0, &uce);
- if (r < 0)
- return r;
-
- return strv_env_replace(environment, uce);
-}
#endif /* NM_IGNORED */
diff --git a/src/systemd/src/basic/env-util.h b/src/systemd/src/basic/env-util.h
index 174433ea91..4d21ea6bef 100644
--- a/src/systemd/src/basic/env-util.h
+++ b/src/systemd/src/basic/env-util.h
@@ -45,6 +45,3 @@ char *strv_env_get(char **x, const char *n) _pure_;
int getenv_bool(const char *p);
int getenv_bool_secure(const char *p);
-
-int serialize_environment(FILE *f, char **environment);
-int deserialize_environment(char ***environment, const char *line);
diff --git a/src/systemd/src/basic/fd-util.c b/src/systemd/src/basic/fd-util.c
index 3913370a03..6c6068038a 100644
--- a/src/systemd/src/basic/fd-util.c
+++ b/src/systemd/src/basic/fd-util.c
@@ -357,22 +357,22 @@ bool fdname_is_valid(const char *s) {
}
int fd_get_path(int fd, char **ret) {
- _cleanup_close_ int dir = -1;
- char fdname[DECIMAL_STR_MAX(int)];
+ char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
int r;
- dir = open("/proc/self/fd/", O_CLOEXEC | O_DIRECTORY | O_PATH);
- if (dir < 0)
- /* /proc is not available or not set up properly, we're most likely
- * in some chroot environment. */
- return errno == ENOENT ? -EOPNOTSUPP : -errno;
+ xsprintf(procfs_path, "/proc/self/fd/%i", fd);
+ r = readlink_malloc(procfs_path, ret);
+ if (r == -ENOENT) {
+ /* ENOENT can mean two things: that the fd does not exist or that /proc is not mounted. Let's make
+ * things debuggable and distuingish the two. */
- xsprintf(fdname, "%i", fd);
+ 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;
- r = readlinkat_malloc(dir, fdname, ret);
- if (r == -ENOENT)
- /* If the file doesn't exist the fd is invalid */
- return -EBADF;
+ return -EBADF; /* The directory exists, hence it's the fd that doesn't. */
+ }
return r;
}
diff --git a/src/systemd/src/basic/fileio.c b/src/systemd/src/basic/fileio.c
index 24a1098605..b168ebf340 100644
--- a/src/systemd/src/basic/fileio.c
+++ b/src/systemd/src/basic/fileio.c
@@ -1231,6 +1231,24 @@ int mkostemp_safe(char *pattern) {
return fd;
}
+int fmkostemp_safe(char *pattern, const char *mode, FILE **ret_f) {
+ int fd;
+ FILE *f;
+
+ fd = mkostemp_safe(pattern);
+ if (fd < 0)
+ return fd;
+
+ f = fdopen(fd, mode);
+ if (!f) {
+ safe_close(fd);
+ return -errno;
+ }
+
+ *ret_f = f;
+ return 0;
+}
+
int tempfn_xxxxxx(const char *p, const char *extra, char **ret) {
const char *fn;
char *t;
diff --git a/src/systemd/src/basic/fileio.h b/src/systemd/src/basic/fileio.h
index 77e6206e95..102d33d75f 100644
--- a/src/systemd/src/basic/fileio.h
+++ b/src/systemd/src/basic/fileio.h
@@ -59,20 +59,12 @@ DIR *xopendirat(int dirfd, const char *name, int flags);
int search_and_fopen(const char *path, const char *mode, const char *root, const char **search, FILE **_f);
int search_and_fopen_nulstr(const char *path, const char *mode, const char *root, const char *search, FILE **_f);
-#define FOREACH_LINE(line, f, on_error) \
- for (;;) \
- if (!fgets(line, sizeof(line), f)) { \
- if (ferror(f)) { \
- on_error; \
- } \
- break; \
- } else
-
int fflush_and_check(FILE *f);
int fflush_sync_and_check(FILE *f);
int fopen_temporary(const char *path, FILE **_f, char **_temp_path);
int mkostemp_safe(char *pattern);
+int fmkostemp_safe(char *pattern, const char *mode, FILE**_f);
int tempfn_xxxxxx(const char *p, const char *extra, char **ret);
int tempfn_random(const char *p, const char *extra, char **ret);
diff --git a/src/systemd/src/basic/fs-util.c b/src/systemd/src/basic/fs-util.c
index 1433bb714c..5966c3835b 100644
--- a/src/systemd/src/basic/fs-util.c
+++ b/src/systemd/src/basic/fs-util.c
@@ -136,7 +136,7 @@ int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char
#endif /* NM_IGNORED */
int readlinkat_malloc(int fd, const char *p, char **ret) {
- size_t l = 100;
+ size_t l = FILENAME_MAX+1;
int r;
assert(p);
@@ -1182,7 +1182,7 @@ int unlinkat_deallocate(int fd, const char *name, int flags) {
return 0;
if (fstat(truncate_fd, &st) < 0) {
- log_debug_errno(errno, "Failed to stat file '%s' for deallocation, ignoring.", name);
+ log_debug_errno(errno, "Failed to stat file '%s' for deallocation, ignoring: %m", name);
return 0;
}
@@ -1244,6 +1244,34 @@ int fsync_directory_of_file(int fd) {
return 0;
}
+int fsync_path_at(int at_fd, const char *path) {
+ _cleanup_close_ int opened_fd = -1;
+ int fd;
+
+ if (isempty(path)) {
+ if (at_fd == AT_FDCWD) {
+ opened_fd = open(".", O_RDONLY|O_DIRECTORY|O_CLOEXEC);
+ if (opened_fd < 0)
+ return -errno;
+
+ fd = opened_fd;
+ } else
+ fd = at_fd;
+ } else {
+
+ opened_fd = openat(at_fd, path, O_RDONLY|O_CLOEXEC);
+ if (opened_fd < 0)
+ return -errno;
+
+ fd = opened_fd;
+ }
+
+ if (fsync(fd) < 0)
+ return -errno;
+
+ return 0;
+}
+
int open_parent(const char *path, int flags, mode_t mode) {
_cleanup_free_ char *parent = NULL;
int fd;
diff --git a/src/systemd/src/basic/fs-util.h b/src/systemd/src/basic/fs-util.h
index bc753d5920..955b146a6a 100644
--- a/src/systemd/src/basic/fs-util.h
+++ b/src/systemd/src/basic/fs-util.h
@@ -105,5 +105,6 @@ void unlink_tempfilep(char (*p)[]);
int unlinkat_deallocate(int fd, const char *name, int flags);
int fsync_directory_of_file(int fd);
+int fsync_path_at(int at_fd, const char *path);
int open_parent(const char *path, int flags, mode_t mode);
diff --git a/src/systemd/src/basic/hashmap.c b/src/systemd/src/basic/hashmap.c
index cfddeafe05..328c4d3a5a 100644
--- a/src/systemd/src/basic/hashmap.c
+++ b/src/systemd/src/basic/hashmap.c
@@ -8,7 +8,6 @@
#include <string.h>
#include "alloc-util.h"
-#include "env-util.h"
#include "fileio.h"
#include "hashmap.h"
#include "macro.h"
@@ -769,24 +768,12 @@ static void reset_direct_storage(HashmapBase *h) {
memset(p, DIB_RAW_INIT, sizeof(dib_raw_t) * hi->n_direct_buckets);
}
-static bool use_pool(void) {
- static int b = -1;
-
- if (!is_main_thread())
- return false;
-
- if (b < 0)
- b = getenv_bool("SYSTEMD_MEMPOOL") != 0;
-
- return b;
-}
-
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;
- up = use_pool();
+ up = mempool_enabled();
h = up ? mempool_alloc0_tile(hi->mempool) : malloc0(hi->head_size);
if (!h)
@@ -1558,18 +1545,9 @@ static unsigned find_first_entry(HashmapBase *h) {
return hashmap_iterate_entry(h, &i);
}
-void *internal_hashmap_first(HashmapBase *h) {
- unsigned idx;
-
- idx = find_first_entry(h);
- if (idx == IDX_NIL)
- return NULL;
-
- return entry_value(h, bucket_at(h, idx));
-}
-
-void *internal_hashmap_first_key(HashmapBase *h) {
+void *internal_hashmap_first_key_and_value(HashmapBase *h, bool remove, void **ret_key) {
struct hashmap_base_entry *e;
+ void *key, *data;
unsigned idx;
idx = find_first_entry(h);
@@ -1577,39 +1555,16 @@ void *internal_hashmap_first_key(HashmapBase *h) {
return NULL;
e = bucket_at(h, idx);
- return (void*) e->key;
-}
-
-void *internal_hashmap_steal_first(HashmapBase *h) {
- struct hashmap_base_entry *e;
- void *data;
- unsigned idx;
-
- idx = find_first_entry(h);
- if (idx == IDX_NIL)
- return NULL;
-
- e = bucket_at(h, idx);
+ key = (void*) e->key;
data = entry_value(h, e);
- remove_entry(h, idx);
-
- return data;
-}
-void *internal_hashmap_steal_first_key(HashmapBase *h) {
- struct hashmap_base_entry *e;
- void *key;
- unsigned idx;
-
- idx = find_first_entry(h);
- if (idx == IDX_NIL)
- return NULL;
+ if (remove)
+ remove_entry(h, idx);
- e = bucket_at(h, idx);
- key = (void*) e->key;
- remove_entry(h, idx);
+ if (ret_key)
+ *ret_key = key;
- return key;
+ return data;
}
unsigned internal_hashmap_size(HashmapBase *h) {
diff --git a/src/systemd/src/basic/hashmap.h b/src/systemd/src/basic/hashmap.h
index b771ceccdc..bb2a5c76ec 100644
--- a/src/systemd/src/basic/hashmap.h
+++ b/src/systemd/src/basic/hashmap.h
@@ -290,36 +290,51 @@ static inline void ordered_hashmap_clear_free_free(OrderedHashmap *h) {
* the first entry is O(1).
*/
-void *internal_hashmap_steal_first(HashmapBase *h);
+void *internal_hashmap_first_key_and_value(HashmapBase *h, bool remove, void **ret_key);
+static inline void *hashmap_steal_first_key_and_value(Hashmap *h, void **ret) {
+ return internal_hashmap_first_key_and_value(HASHMAP_BASE(h), true, ret);
+}
+static inline void *ordered_hashmap_steal_first_key_and_value(OrderedHashmap *h, void **ret) {
+ return internal_hashmap_first_key_and_value(HASHMAP_BASE(h), true, ret);
+}
+static inline void *hashmap_first_key_and_value(Hashmap *h, void **ret) {
+ return internal_hashmap_first_key_and_value(HASHMAP_BASE(h), false, ret);
+}
+static inline void *ordered_hashmap_first_key_and_value(OrderedHashmap *h, void **ret) {
+ return internal_hashmap_first_key_and_value(HASHMAP_BASE(h), false, ret);
+}
+
+
static inline void *hashmap_steal_first(Hashmap *h) {
- return internal_hashmap_steal_first(HASHMAP_BASE(h));
+ return internal_hashmap_first_key_and_value(HASHMAP_BASE(h), true, NULL);
}
static inline void *ordered_hashmap_steal_first(OrderedHashmap *h) {
- return internal_hashmap_steal_first(HASHMAP_BASE(h));
+ return internal_hashmap_first_key_and_value(HASHMAP_BASE(h), true, NULL);
+}
+static inline void *hashmap_first(Hashmap *h) {
+ return internal_hashmap_first_key_and_value(HASHMAP_BASE(h), false, NULL);
+}
+static inline void *ordered_hashmap_first(OrderedHashmap *h) {
+ return internal_hashmap_first_key_and_value(HASHMAP_BASE(h), false, NULL);
}
-void *internal_hashmap_steal_first_key(HashmapBase *h);
+static inline void *internal_hashmap_first_key(HashmapBase *h, bool remove) {
+ void *key = NULL;
+
+ (void) internal_hashmap_first_key_and_value(HASHMAP_BASE(h), remove, &key);
+ return key;
+}
static inline void *hashmap_steal_first_key(Hashmap *h) {
- return internal_hashmap_steal_first_key(HASHMAP_BASE(h));
+ return internal_hashmap_first_key(HASHMAP_BASE(h), true);
}
static inline void *ordered_hashmap_steal_first_key(OrderedHashmap *h) {
- return internal_hashmap_steal_first_key(HASHMAP_BASE(h));
+ return internal_hashmap_first_key(HASHMAP_BASE(h), true);
}
-
-void *internal_hashmap_first_key(HashmapBase *h) _pure_;
static inline void *hashmap_first_key(Hashmap *h) {
- return internal_hashmap_first_key(HASHMAP_BASE(h));
+ return internal_hashmap_first_key(HASHMAP_BASE(h), false);
}
static inline void *ordered_hashmap_first_key(OrderedHashmap *h) {
- return internal_hashmap_first_key(HASHMAP_BASE(h));
-}
-
-void *internal_hashmap_first(HashmapBase *h) _pure_;
-static inline void *hashmap_first(Hashmap *h) {
- return internal_hashmap_first(HASHMAP_BASE(h));
-}
-static inline void *ordered_hashmap_first(OrderedHashmap *h) {
- return internal_hashmap_first(HASHMAP_BASE(h));
+ return internal_hashmap_first_key(HASHMAP_BASE(h), false);
}
#define hashmap_clear_with_destructor(_s, _f) \
diff --git a/src/systemd/src/basic/list.h b/src/systemd/src/basic/list.h
index 643e0bea88..040680c30a 100644
--- a/src/systemd/src/basic/list.h
+++ b/src/systemd/src/basic/list.h
@@ -38,9 +38,9 @@
/* Append an item to the list */
#define LIST_APPEND(name,head,item) \
do { \
- typeof(*(head)) *_tail; \
- LIST_FIND_TAIL(name,head,_tail); \
- LIST_INSERT_AFTER(name,head,_tail,item); \
+ typeof(*(head)) **_hhead = &(head), *_tail; \
+ LIST_FIND_TAIL(name, *_hhead, _tail); \
+ LIST_INSERT_AFTER(name, *_hhead, _tail, item); \
} while (false)
/* Remove an item from the list */
diff --git a/src/systemd/src/basic/macro.h b/src/systemd/src/basic/macro.h
index 9f8bd8abf8..fdb575f447 100644
--- a/src/systemd/src/basic/macro.h
+++ b/src/systemd/src/basic/macro.h
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
+#include <assert.h>
#include <inttypes.h>
#include <stdbool.h>
#include <sys/param.h>
@@ -57,10 +58,6 @@
#if (defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))) || defined (__clang__)
/* Temporarily disable some warnings */
-#define DISABLE_WARNING_DECLARATION_AFTER_STATEMENT \
- _Pragma("GCC diagnostic push"); \
- _Pragma("GCC diagnostic ignored \"-Wdeclaration-after-statement\"")
-
#define DISABLE_WARNING_FORMAT_NONLITERAL \
_Pragma("GCC diagnostic push"); \
_Pragma("GCC diagnostic ignored \"-Wformat-nonliteral\"")
@@ -323,20 +320,13 @@ static inline int __coverity_check__(int condition) {
} while (false)
#if defined(static_assert)
-/* static_assert() is sometimes defined in a way that trips up
- * -Wdeclaration-after-statement, hence let's temporarily turn off
- * this warning around it. */
#define assert_cc(expr) \
- DISABLE_WARNING_DECLARATION_AFTER_STATEMENT; \
- static_assert(expr, #expr); \
- REENABLE_WARNING
+ static_assert(expr, #expr);
#else
#define assert_cc(expr) \
- DISABLE_WARNING_DECLARATION_AFTER_STATEMENT; \
struct CONCATENATE(_assert_struct_, __COUNTER__) { \
char x[(expr) ? 0 : -1]; \
- }; \
- REENABLE_WARNING
+ };
#endif
#define assert_return(expr, r) \
@@ -355,7 +345,7 @@ static inline int __coverity_check__(int condition) {
#define PTR_TO_INT(p) ((int) ((intptr_t) (p)))
#define INT_TO_PTR(u) ((void *) ((intptr_t) (u)))
-#define PTR_TO_UINT(p) ((unsigned int) ((uintptr_t) (p)))
+#define PTR_TO_UINT(p) ((unsigned) ((uintptr_t) (p)))
#define UINT_TO_PTR(u) ((void *) ((uintptr_t) (u)))
#define PTR_TO_LONG(p) ((long) ((intptr_t) (p)))
@@ -435,8 +425,11 @@ static inline int __coverity_check__(int condition) {
#define IN_SET(x, ...) \
({ \
bool _found = false; \
- /* If the build breaks in the line below, you need to extend the case macros */ \
- static _unused_ char _static_assert__macros_need_to_be_extended[20 - sizeof((int[]){__VA_ARGS__})/sizeof(int)]; \
+ /* If the build breaks in the line below, you need to extend the case macros. (We use "long double" as \
+ * type for the array, in the hope that checkers such as ubsan don't complain that the initializers for \
+ * the array are not representable by the base type. Ideally we'd use typeof(x) as base type, but that \
+ * doesn't work, as we want to use this on bitfields and gcc refuses typeof() on bitfields.) */ \
+ assert_cc((sizeof((long double[]){__VA_ARGS__})/sizeof(long double)) <= 20); \
switch(x) { \
FOR_EACH_MAKE_CASE(__VA_ARGS__) \
_found = true; \
diff --git a/src/systemd/src/basic/mempool.c b/src/systemd/src/basic/mempool.c
index dd1b1e5ffa..bae4f2fcd6 100644
--- a/src/systemd/src/basic/mempool.c
+++ b/src/systemd/src/basic/mempool.c
@@ -5,8 +5,10 @@
#include <stdint.h>
#include <stdlib.h>
+#include "env-util.h"
#include "macro.h"
#include "mempool.h"
+#include "process-util.h"
#include "util.h"
struct pool {
@@ -72,8 +74,21 @@ void mempool_free_tile(struct mempool *mp, void *p) {
mp->freelist = p;
}
-#if VALGRIND
+bool mempool_enabled(void) {
+ static int b = -1;
+
+ if (!is_main_thread())
+ return false;
+ if (!mempool_use_allowed)
+ b = false;
+ if (b < 0)
+ b = getenv_bool("SYSTEMD_MEMPOOL") != 0;
+
+ return b;
+}
+
+#if VALGRIND
void mempool_drop(struct mempool *mp) {
struct pool *p = mp->first_pool;
while (p) {
@@ -83,5 +98,4 @@ void mempool_drop(struct mempool *mp) {
p = n;
}
}
-
#endif
diff --git a/src/systemd/src/basic/mempool.h b/src/systemd/src/basic/mempool.h
index 4098535c6f..0eecca0f92 100644
--- a/src/systemd/src/basic/mempool.h
+++ b/src/systemd/src/basic/mempool.h
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
+#include <stdbool.h>
#include <stddef.h>
struct pool;
@@ -22,6 +23,9 @@ static struct mempool pool_name = { \
.at_least = alloc_at_least, \
}
+extern const bool mempool_use_allowed;
+bool mempool_enabled(void);
+
#if VALGRIND
void mempool_drop(struct mempool *mp);
#endif
diff --git a/src/systemd/src/basic/path-util.c b/src/systemd/src/basic/path-util.c
index 5877957822..dc37e04dd7 100644
--- a/src/systemd/src/basic/path-util.c
+++ b/src/systemd/src/basic/path-util.c
@@ -344,7 +344,7 @@ char *path_simplify(char *path, bool kill_dots) {
*/
if (isempty(path))
- return path;
+ return path;
absolute = path_is_absolute(path);
@@ -785,24 +785,32 @@ bool filename_is_valid(const char *p) {
if (*e != 0)
return false;
- if (e - p > FILENAME_MAX)
+ if (e - p > FILENAME_MAX) /* FILENAME_MAX is counted *without* the trailing NUL byte */
return false;
return true;
}
-bool path_is_normalized(const char *p) {
+bool path_is_valid(const char *p) {
if (isempty(p))
return false;
- if (dot_or_dot_dot(p))
+ if (strlen(p) >= PATH_MAX) /* PATH_MAX is counted *with* the trailing NUL byte */
return false;
- if (startswith(p, "../") || endswith(p, "/..") || strstr(p, "/../"))
+ return true;
+}
+
+bool path_is_normalized(const char *p) {
+
+ if (!path_is_valid(p))
+ return false;
+
+ if (dot_or_dot_dot(p))
return false;
- if (strlen(p)+1 > PATH_MAX)
+ if (startswith(p, "../") || endswith(p, "/..") || strstr(p, "/../"))
return false;
if (startswith(p, "./") || endswith(p, "/.") || strstr(p, "/./"))
diff --git a/src/systemd/src/basic/path-util.h b/src/systemd/src/basic/path-util.h
index 72f3ce3683..4a4bd4cd51 100644
--- a/src/systemd/src/basic/path-util.h
+++ b/src/systemd/src/basic/path-util.h
@@ -136,6 +136,7 @@ char* dirname_malloc(const char *path);
const char *last_path_component(const char *path);
bool filename_is_valid(const char *p) _pure_;
+bool path_is_valid(const char *p) _pure_;
bool path_is_normalized(const char *p) _pure_;
char *file_in_same_dir(const char *path, const char *filename);
diff --git a/src/systemd/src/basic/prioq.c b/src/systemd/src/basic/prioq.c
index 79900df353..3af3402504 100644
--- a/src/systemd/src/basic/prioq.c
+++ b/src/systemd/src/basic/prioq.c
@@ -34,11 +34,14 @@ struct Prioq {
Prioq *prioq_new(compare_func_t compare_func) {
Prioq *q;
- q = new0(Prioq, 1);
+ q = new(Prioq, 1);
if (!q)
return q;
- q->compare_func = compare_func;
+ *q = (Prioq) {
+ .compare_func = compare_func,
+ };
+
return q;
}
@@ -90,6 +93,7 @@ static void swap(Prioq *q, unsigned j, unsigned k) {
static unsigned shuffle_up(Prioq *q, unsigned idx) {
assert(q);
+ assert(idx < q->n_items);
while (idx > 0) {
unsigned k;
@@ -213,9 +217,12 @@ _pure_ static struct prioq_item* find_item(Prioq *q, void *data, unsigned *idx)
assert(q);
+ if (q->n_items <= 0)
+ return NULL;
+
if (idx) {
if (*idx == PRIOQ_IDX_NULL ||
- *idx > q->n_items)
+ *idx >= q->n_items)
return NULL;
i = q->items + *idx;
diff --git a/src/systemd/src/basic/prioq.h b/src/systemd/src/basic/prioq.h
index e036175260..bba5c7caa4 100644
--- a/src/systemd/src/basic/prioq.h
+++ b/src/systemd/src/basic/prioq.h
@@ -12,6 +12,7 @@ typedef struct Prioq Prioq;
Prioq *prioq_new(compare_func_t compare);
Prioq *prioq_free(Prioq *q);
+DEFINE_TRIVIAL_CLEANUP_FUNC(Prioq*, prioq_free);
int prioq_ensure_allocated(Prioq **q, compare_func_t compare_func);
int prioq_put(Prioq *q, void *data, unsigned *idx);
diff --git a/src/systemd/src/basic/process-util.c b/src/systemd/src/basic/process-util.c
index 71d737a373..b5f0aafd0a 100644
--- a/src/systemd/src/basic/process-util.c
+++ b/src/systemd/src/basic/process-util.c
@@ -29,6 +29,7 @@
#include "alloc-util.h"
#include "architecture.h"
+#include "def.h"
#include "escape.h"
#include "fd-util.h"
#include "fileio.h"
@@ -341,15 +342,33 @@ int rename_process(const char name[]) {
/* Now, let's tell the kernel about this new memory */
if (prctl(PR_SET_MM, PR_SET_MM_ARG_START, (unsigned long) nn, 0, 0) < 0) {
- log_debug_errno(errno, "PR_SET_MM_ARG_START failed, proceeding without: %m");
- (void) munmap(nn, nn_size);
- goto use_saved_argv;
- }
+ /* HACK: prctl() API is kind of dumb on this point. The existing end address may already be
+ * below the desired start address, in which case the kernel may have kicked this back due
+ * to a range-check failure (see linux/kernel/sys.c:validate_prctl_map() to see this in
+ * action). The proper solution would be to have a prctl() API that could set both start+end
+ * simultaneously, or at least let us query the existing address to anticipate this condition
+ * and respond accordingly. For now, we can only guess at the cause of this failure and try
+ * a workaround--which will briefly expand the arg space to something potentially huge before
+ * resizing it to what we want. */
+ log_debug_errno(errno, "PR_SET_MM_ARG_START failed, attempting PR_SET_MM_ARG_END hack: %m");
+
+ if (prctl(PR_SET_MM, PR_SET_MM_ARG_END, (unsigned long) nn + l + 1, 0, 0) < 0) {
+ log_debug_errno(errno, "PR_SET_MM_ARG_END hack failed, proceeding without: %m");
+ (void) munmap(nn, nn_size);
+ goto use_saved_argv;
+ }
- /* And update the end pointer to the new end, too. If this fails, we don't really know what to do, it's
- * pretty unlikely that we can rollback, hence we'll just accept the failure, and continue. */
- if (prctl(PR_SET_MM, PR_SET_MM_ARG_END, (unsigned long) nn + l + 1, 0, 0) < 0)
- log_debug_errno(errno, "PR_SET_MM_ARG_END failed, proceeding without: %m");
+ if (prctl(PR_SET_MM, PR_SET_MM_ARG_START, (unsigned long) nn, 0, 0) < 0) {
+ log_debug_errno(errno, "PR_SET_MM_ARG_START still failed, proceeding without: %m");
+ goto use_saved_argv;
+ }
+ } else {
+ /* And update the end pointer to the new end, too. If this fails, we don't really know what
+ * to do, it's pretty unlikely that we can rollback, hence we'll just accept the failure,
+ * and continue. */
+ if (prctl(PR_SET_MM, PR_SET_MM_ARG_END, (unsigned long) nn + l + 1, 0, 0) < 0)
+ log_debug_errno(errno, "PR_SET_MM_ARG_END failed, proceeding without: %m");
+ }
if (mm)
(void) munmap(mm, mm_size);
@@ -501,8 +520,8 @@ int get_process_exe(pid_t pid, char **name) {
static int get_process_id(pid_t pid, const char *field, uid_t *uid) {
_cleanup_fclose_ FILE *f = NULL;
- char line[LINE_MAX];
const char *p;
+ int r;
assert(field);
assert(uid);
@@ -520,9 +539,16 @@ static int get_process_id(pid_t pid, const char *field, uid_t *uid) {
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
- FOREACH_LINE(line, f, return -errno) {
+ for (;;) {
+ _cleanup_free_ char *line = NULL;
char *l;
+ r = read_line(f, LONG_LINE_MAX, &line);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ break;
+
l = strstrip(line);
if (startswith(l, field)) {
diff --git a/src/systemd/src/basic/process-util.h b/src/systemd/src/basic/process-util.h
index b16697711c..c7aa45f84f 100644
--- a/src/systemd/src/basic/process-util.h
+++ b/src/systemd/src/basic/process-util.h
@@ -134,13 +134,6 @@ static inline bool ioprio_priority_is_valid(int i) {
static inline bool pid_is_valid(pid_t p) {
return p > 0;
}
-
-static inline int sched_policy_to_string_alloc_with_check(int n, char **s) {
- if (!sched_policy_is_valid(n))
- return -EINVAL;
-
- return sched_policy_to_string_alloc(n, s);
-}
#endif /* NM_IGNORED */
int ioprio_parse_priority(const char *s, int *ret);
@@ -168,7 +161,7 @@ static inline int safe_fork(const char *name, ForkFlags flags, pid_t *ret_pid) {
return safe_fork_full(name, NULL, 0, flags, ret_pid);
}
-int fork_agent(const char *name, const int except[], size_t n_except, pid_t *pid, const char *path, ...);
+int fork_agent(const char *name, const int except[], size_t n_except, pid_t *pid, const char *path, ...) _sentinel_;
int set_oom_score_adjust(int value);
diff --git a/src/systemd/src/basic/set.h b/src/systemd/src/basic/set.h
index 664713810d..0d99d5550d 100644
--- a/src/systemd/src/basic/set.h
+++ b/src/systemd/src/basic/set.h
@@ -86,7 +86,7 @@ static inline void set_clear_free(Set *s) {
/* no set_clear_free_free */
static inline void *set_steal_first(Set *s) {
- return internal_hashmap_steal_first(HASHMAP_BASE(s));
+ return internal_hashmap_first_key_and_value(HASHMAP_BASE(s), true, NULL);
}
#define set_clear_with_destructor(_s, _f) \
@@ -105,7 +105,7 @@ static inline void *set_steal_first(Set *s) {
/* no set_first_key */
static inline void *set_first(Set *s) {
- return internal_hashmap_first(HASHMAP_BASE(s));
+ return internal_hashmap_first_key_and_value(HASHMAP_BASE(s), false, NULL);
}
/* no set_next */
diff --git a/src/systemd/src/basic/siphash24.h b/src/systemd/src/basic/siphash24.h
index 77bb9a8c07..42a4ec0a49 100644
--- a/src/systemd/src/basic/siphash24.h
+++ b/src/systemd/src/basic/siphash24.h
@@ -3,6 +3,7 @@
#include <inttypes.h>
#include <stddef.h>
#include <stdint.h>
+#include <string.h>
#include <sys/types.h>
#if 0 /* NM_IGNORED */
@@ -51,3 +52,7 @@ void siphash24_compress(const void *in, size_t inlen, struct siphash *state);
uint64_t siphash24_finalize(struct siphash *state);
uint64_t siphash24(const void *in, size_t inlen, const uint8_t k[16]);
+
+static inline uint64_t siphash24_string(const char *s, const uint8_t k[16]) {
+ return siphash24(s, strlen(s) + 1, k);
+}
diff --git a/src/systemd/src/basic/socket-util.c b/src/systemd/src/basic/socket-util.c
index 2e3c82705d..4476f3dc7a 100644
--- a/src/systemd/src/basic/socket-util.c
+++ b/src/systemd/src/basic/socket-util.c
@@ -60,8 +60,9 @@ int socket_address_parse(SocketAddress *a, const char *s) {
assert(a);
assert(s);
- zero(*a);
- a->type = SOCK_STREAM;
+ *a = (SocketAddress) {
+ .type = SOCK_STREAM,
+ };
if (*s == '[') {
uint16_t port;
@@ -99,7 +100,9 @@ int socket_address_parse(SocketAddress *a, const char *s) {
size_t l;
l = strlen(s);
- if (l >= sizeof(a->sockaddr.un.sun_path))
+ if (l >= sizeof(a->sockaddr.un.sun_path)) /* Note that we refuse non-NUL-terminated sockets when
+ * parsing (the kernel itself is less strict here in what it
+ * accepts) */
return -EINVAL;
a->sockaddr.un.sun_family = AF_UNIX;
@@ -111,7 +114,11 @@ int socket_address_parse(SocketAddress *a, const char *s) {
size_t l;
l = strlen(s+1);
- if (l >= sizeof(a->sockaddr.un.sun_path) - 1)
+ if (l >= sizeof(a->sockaddr.un.sun_path) - 1) /* Note that we refuse non-NUL-terminate sockets here
+ * when parsing, even though abstract namespace sockets
+ * explicitly allow embedded NUL bytes and don't consider
+ * them special. But it's simply annoying to debug such
+ * sockets. */
return -EINVAL;
a->sockaddr.un.sun_family = AF_UNIX;
@@ -289,19 +296,28 @@ int socket_address_verify(const SocketAddress *a) {
case AF_UNIX:
if (a->size < offsetof(struct sockaddr_un, sun_path))
return -EINVAL;
+ if (a->size > sizeof(struct sockaddr_un)+1) /* Allow one extra byte, since getsockname() on Linux will
+ * append a NUL byte if we have path sockets that are above
+ * sun_path' full size */
+ return -EINVAL;
- if (a->size > offsetof(struct sockaddr_un, sun_path)) {
-
- if (a->sockaddr.un.sun_path[0] != 0) {
- char *e;
+ if (a->size > offsetof(struct sockaddr_un, sun_path) &&
+ a->sockaddr.un.sun_path[0] != 0) { /* Only validate file system sockets here */
- /* path */
- e = memchr(a->sockaddr.un.sun_path, 0, sizeof(a->sockaddr.un.sun_path));
- if (!e)
- return -EINVAL;
+ const char *e;
+ e = memchr(a->sockaddr.un.sun_path, 0, sizeof(a->sockaddr.un.sun_path));
+ if (e) {
+ /* If there's an embedded NUL byte, make sure the size of the socket addresses matches it */
if (a->size != offsetof(struct sockaddr_un, sun_path) + (e - a->sockaddr.un.sun_path) + 1)
return -EINVAL;
+ } else {
+ /* If there's no embedded NUL byte, then then the size needs to match the whole
+ * structure or the structure with one extra NUL byte suffixed. (Yeah, Linux is awful,
+ * and considers both equivalent: getsockname() even extends sockaddr_un beyond its
+ * size if the path is non NUL terminated.)*/
+ if (!IN_SET(a->size, sizeof(a->sockaddr.un.sun_path), sizeof(a->sockaddr.un.sun_path)+1))
+ return -EINVAL;
}
}
@@ -485,6 +501,10 @@ const char* socket_address_get_path(const SocketAddress *a) {
if (a->sockaddr.un.sun_path[0] == 0)
return NULL;
+ /* Note that this is only safe because we know that there's an extra NUL byte after the sockaddr_un
+ * structure. On Linux AF_UNIX file system socket addresses don't have to be NUL terminated if they take up the
+ * full sun_path space. */
+ assert_cc(sizeof(union sockaddr_union) >= sizeof(struct sockaddr_un)+1);
return a->sockaddr.un.sun_path;
}
@@ -750,21 +770,6 @@ int socknameinfo_pretty(union sockaddr_union *sa, socklen_t salen, char **_ret)
return 0;
}
-int socket_address_unlink(SocketAddress *a) {
- assert(a);
-
- if (socket_address_family(a) != AF_UNIX)
- return 0;
-
- if (a->sockaddr.un.sun_path[0] == 0)
- return 0;
-
- if (unlink(a->sockaddr.un.sun_path) < 0)
- return -errno;
-
- return 1;
-}
-
static const char* const netlink_family_table[] = {
[NETLINK_ROUTE] = "route",
[NETLINK_FIREWALL] = "firewall",
@@ -837,10 +842,11 @@ int fd_inc_sndbuf(int fd, size_t n) {
/* If we have the privileges we will ignore the kernel limit. */
- value = (int) n;
- if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value)) < 0)
- if (setsockopt(fd, SOL_SOCKET, SO_SNDBUFFORCE, &value, sizeof(value)) < 0)
- return -errno;
+ if (setsockopt_int(fd, SOL_SOCKET, SO_SNDBUF, n) < 0) {
+ r = setsockopt_int(fd, SOL_SOCKET, SO_SNDBUFFORCE, n);
+ if (r < 0)
+ return r;
+ }
return 1;
}
@@ -855,10 +861,12 @@ int fd_inc_rcvbuf(int fd, size_t n) {
/* If we have the privileges we will ignore the kernel limit. */
- value = (int) n;
- if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value)) < 0)
- if (setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE, &value, sizeof(value)) < 0)
- return -errno;
+ if (setsockopt_int(fd, SOL_SOCKET, SO_RCVBUF, n) < 0) {
+ r = setsockopt_int(fd, SOL_SOCKET, SO_RCVBUFFORCE, n);
+ if (r < 0)
+ return r;
+ }
+
return 1;
}
@@ -1251,4 +1259,72 @@ int socket_ioctl_fd(void) {
return fd;
}
+
+int sockaddr_un_unlink(const struct sockaddr_un *sa) {
+ const char *p, * nul;
+
+ assert(sa);
+
+ if (sa->sun_family != AF_UNIX)
+ return -EPROTOTYPE;
+
+ if (sa->sun_path[0] == 0) /* Nothing to do for abstract sockets */
+ return 0;
+
+ /* The path in .sun_path is not necessarily NUL terminated. Let's fix that. */
+ nul = memchr(sa->sun_path, 0, sizeof(sa->sun_path));
+ if (nul)
+ p = sa->sun_path;
+ else
+ p = memdupa_suffix0(sa->sun_path, sizeof(sa->sun_path));
+
+ if (unlink(p) < 0)
+ return -errno;
+
+ return 1;
+}
+
+int sockaddr_un_set_path(struct sockaddr_un *ret, const char *path) {
+ size_t l;
+
+ assert(ret);
+ assert(path);
+
+ /* Initialize ret->sun_path from the specified argument. This will interpret paths starting with '@' as
+ * abstract namespace sockets, and those starting with '/' as regular filesystem sockets. It won't accept
+ * anything else (i.e. no relative paths), to avoid ambiguities. Note that this function cannot be used to
+ * reference paths in the abstract namespace that include NUL bytes in the name. */
+
+ l = strlen(path);
+ if (l == 0)
+ 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
+ * addresses!), which the kernel doesn't. We do this to reduce chance of incompatibility with other apps that
+ * do not expect non-NUL terminated file system path*/
+ if (l+1 > sizeof(ret->sun_path))
+ return -EINVAL;
+
+ *ret = (struct sockaddr_un) {
+ .sun_family = AF_UNIX,
+ };
+
+ if (path[0] == '@') {
+ /* Abstract namespace socket */
+ memcpy(ret->sun_path + 1, path + 1, l); /* copy *with* trailing NUL byte */
+ return (int) (offsetof(struct sockaddr_un, sun_path) + l); /* 🔥 *don't* 🔥 include trailing NUL in size */
+
+ } else {
+ assert(path[0] == '/');
+
+ /* File system socket */
+ memcpy(ret->sun_path, path, l + 1); /* copy *with* trailing NUL byte */
+ return (int) (offsetof(struct sockaddr_un, sun_path) + l + 1); /* include trailing NUL in size */
+ }
+}
#endif /* NM_IGNORED */
diff --git a/src/systemd/src/basic/socket-util.h b/src/systemd/src/basic/socket-util.h
index d7b814aefb..1ac30de5a3 100644
--- a/src/systemd/src/basic/socket-util.h
+++ b/src/systemd/src/basic/socket-util.h
@@ -73,7 +73,12 @@ int socket_address_parse_and_warn(SocketAddress *a, const char *s);
int socket_address_parse_netlink(SocketAddress *a, const char *s);
int socket_address_print(const SocketAddress *a, char **p);
int socket_address_verify(const SocketAddress *a) _pure_;
-int socket_address_unlink(SocketAddress *a);
+
+int sockaddr_un_unlink(const struct sockaddr_un *sa);
+
+static inline int socket_address_unlink(const SocketAddress *a) {
+ return socket_address_family(a) == AF_UNIX ? sockaddr_un_unlink(&a->sockaddr.un) : 0;
+}
bool socket_address_can_accept(const SocketAddress *a) _pure_;
@@ -181,7 +186,16 @@ struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t leng
offsetof(struct sockaddr_un, sun_path) + \
(_sa->sun_path[0] == 0 ? \
1 + strnlen(_sa->sun_path+1, sizeof(_sa->sun_path)-1) : \
- strnlen(_sa->sun_path, sizeof(_sa->sun_path))); \
+ strnlen(_sa->sun_path, sizeof(_sa->sun_path))+1); \
})
int socket_ioctl_fd(void);
+
+int sockaddr_un_set_path(struct sockaddr_un *ret, const char *path);
+
+static inline int setsockopt_int(int fd, int level, int optname, int value) {
+ if (setsockopt(fd, level, optname, &value, sizeof(value)) < 0)
+ return -errno;
+
+ return 0;
+}
diff --git a/src/systemd/src/basic/string-util.c b/src/systemd/src/basic/string-util.c
index a182555f39..1651239d8c 100644
--- a/src/systemd/src/basic/string-util.c
+++ b/src/systemd/src/basic/string-util.c
@@ -130,7 +130,7 @@ static size_t strcspn_escaped(const char *s, const char *reject) {
}
/* Split a string into words. */
-const char* split(const char **state, size_t *l, const char *separator, bool quoted) {
+const char* split(const char **state, size_t *l, const char *separator, SplitFlags flags) {
const char *current;
current = *state;
@@ -146,20 +146,24 @@ const char* split(const char **state, size_t *l, const char *separator, bool quo
return NULL;
}
- if (quoted && strchr("\'\"", *current)) {
+ if (flags & SPLIT_QUOTES && strchr("\'\"", *current)) {
char quotechars[2] = {*current, '\0'};
*l = strcspn_escaped(current + 1, quotechars);
if (current[*l + 1] == '\0' || current[*l + 1] != quotechars[0] ||
(current[*l + 2] && !strchr(separator, current[*l + 2]))) {
/* right quote missing or garbage at the end */
+ if (flags & SPLIT_RELAX) {
+ *state = current + *l + 1 + (current[*l + 1] != '\0');
+ return current + 1;
+ }
*state = current;
return NULL;
}
*state = current++ + *l + 2;
- } else if (quoted) {
+ } else if (flags & SPLIT_QUOTES) {
*l = strcspn_escaped(current, separator);
- if (current[*l] && !strchr(separator, current[*l])) {
+ if (current[*l] && !strchr(separator, current[*l]) && !(flags & SPLIT_RELAX)) {
/* unfinished escape */
*state = current;
return NULL;
@@ -398,12 +402,7 @@ int ascii_strcasecmp_nn(const char *a, size_t n, const char *b, size_t m) {
if (r != 0)
return r;
- if (n < m)
- return -1;
- else if (n > m)
- return 1;
- else
- return 0;
+ return CMP(n, m);
}
bool chars_intersect(const char *a, const char *b) {
@@ -1068,8 +1067,11 @@ typedef void *(*memset_t)(void *,int,size_t);
static volatile memset_t memset_func = memset;
-void explicit_bzero(void *p, size_t l) {
- memset_func(p, '\0', l);
+void* explicit_bzero_safe(void *p, size_t l) {
+ if (l > 0)
+ memset_func(p, '\0', l);
+
+ return p;
}
#endif
@@ -1079,7 +1081,7 @@ char* string_erase(char *x) {
/* A delicious drop of snake-oil! To be called on memory where
* we stored passphrases or so, after we used them. */
- explicit_bzero(x, strlen(x));
+ explicit_bzero_safe(x, strlen(x));
return x;
}
diff --git a/src/systemd/src/basic/string-util.h b/src/systemd/src/basic/string-util.h
index 72c075aa39..a5b5a16a5d 100644
--- a/src/systemd/src/basic/string-util.h
+++ b/src/systemd/src/basic/string-util.h
@@ -81,16 +81,21 @@ char *endswith_no_case(const char *s, const char *postfix) _pure_;
char *first_word(const char *s, const char *word) _pure_;
-const char* split(const char **state, size_t *l, const char *separator, bool quoted);
+typedef enum SplitFlags {
+ SPLIT_QUOTES = 0x01 << 0,
+ SPLIT_RELAX = 0x01 << 1,
+} SplitFlags;
+
+const char* split(const char **state, size_t *l, const char *separator, SplitFlags flags);
#define FOREACH_WORD(word, length, s, state) \
- _FOREACH_WORD(word, length, s, WHITESPACE, false, state)
+ _FOREACH_WORD(word, length, s, WHITESPACE, 0, state)
#define FOREACH_WORD_SEPARATOR(word, length, s, separator, state) \
- _FOREACH_WORD(word, length, s, separator, false, state)
+ _FOREACH_WORD(word, length, s, separator, 0, state)
-#define _FOREACH_WORD(word, length, s, separator, quoted, state) \
- for ((state) = (s), (word) = split(&(state), &(length), (separator), (quoted)); (word); (word) = split(&(state), &(length), (separator), (quoted)))
+#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 *strappend(const char *s, const char *suffix);
char *strnappend(const char *s, const char *suffix, size_t length);
@@ -193,8 +198,15 @@ static inline void *memmem_safe(const void *haystack, size_t haystacklen, const
return memmem(haystack, haystacklen, needle, needlelen);
}
-#if !HAVE_EXPLICIT_BZERO
-void explicit_bzero(void *p, size_t l);
+#if HAVE_EXPLICIT_BZERO
+static inline void* explicit_bzero_safe(void *p, size_t l) {
+ if (l > 0)
+ explicit_bzero(p, l);
+
+ return p;
+}
+#else
+void *explicit_bzero_safe(void *p, size_t l);
#endif
char *string_erase(char *x);
diff --git a/src/systemd/src/basic/strv.c b/src/systemd/src/basic/strv.c
index 7951fa5022..992e448567 100644
--- a/src/systemd/src/basic/strv.c
+++ b/src/systemd/src/basic/strv.c
@@ -247,7 +247,7 @@ int strv_extend_strv_concat(char ***a, char **b, const char *suffix) {
return 0;
}
-char **strv_split(const char *s, const char *separator) {
+char **strv_split_full(const char *s, const char *separator, SplitFlags flags) {
const char *word, *state;
size_t l;
size_t n, i;
@@ -255,12 +255,15 @@ char **strv_split(const char *s, const char *separator) {
assert(s);
+ if (!separator)
+ separator = WHITESPACE;
+
s += strspn(s, separator);
if (isempty(s))
return new0(char*, 1);
n = 0;
- FOREACH_WORD_SEPARATOR(word, l, s, separator, state)
+ _FOREACH_WORD(word, l, s, separator, flags, state)
n++;
r = new(char*, n+1);
@@ -268,7 +271,7 @@ char **strv_split(const char *s, const char *separator) {
return NULL;
i = 0;
- FOREACH_WORD_SEPARATOR(word, l, s, separator, state) {
+ _FOREACH_WORD(word, l, s, separator, flags, state) {
r[i] = strndup(word, l);
if (!r[i]) {
strv_free(r);
diff --git a/src/systemd/src/basic/strv.h b/src/systemd/src/basic/strv.h
index 34a660cb92..e9e6063f58 100644
--- a/src/systemd/src/basic/strv.h
+++ b/src/systemd/src/basic/strv.h
@@ -9,6 +9,7 @@
#include "alloc-util.h"
#include "extract-word.h"
#include "macro.h"
+#include "string-util.h"
#include "util.h"
char *strv_find(char **l, const char *name) _pure_;
@@ -66,7 +67,10 @@ static inline bool strv_isempty(char * const *l) {
return !l || !*l;
}
-char **strv_split(const char *s, const char *separator);
+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);
diff --git a/src/systemd/src/basic/time-util.c b/src/systemd/src/basic/time-util.c
index 5bceac6b9c..31417d8d51 100644
--- a/src/systemd/src/basic/time-util.c
+++ b/src/systemd/src/basic/time-util.c
@@ -16,6 +16,7 @@
#include <unistd.h>
#include "alloc-util.h"
+#include "def.h"
#include "fd-util.h"
#include "fileio.h"
#include "fs-util.h"
@@ -25,6 +26,7 @@
#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
+#include "serialize.h"
#include "stat-util.h"
#include "string-util.h"
#include "strv.h"
@@ -282,7 +284,7 @@ static char *format_timestamp_internal(
/* Let's not format times with years > 9999 */
if (t > USEC_TIMESTAMP_FORMATTABLE_MAX) {
- assert(l >= strlen("--- XXXX-XX-XX XX:XX:XX") + 1);
+ assert(l >= STRLEN("--- XXXX-XX-XX XX:XX:XX") + 1);
strcpy(buf, "--- XXXX-XX-XX XX:XX:XX");
return buf;
}
@@ -534,64 +536,6 @@ char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy) {
}
#if 0 /* NM_IGNORED */
-void dual_timestamp_serialize(FILE *f, const char *name, dual_timestamp *t) {
-
- assert(f);
- assert(name);
- assert(t);
-
- if (!dual_timestamp_is_set(t))
- return;
-
- fprintf(f, "%s="USEC_FMT" "USEC_FMT"\n",
- name,
- t->realtime,
- t->monotonic);
-}
-
-int dual_timestamp_deserialize(const char *value, dual_timestamp *t) {
- uint64_t a, b;
- int r, pos;
-
- assert(value);
- assert(t);
-
- pos = strspn(value, WHITESPACE);
- if (value[pos] == '-')
- return -EINVAL;
- pos += strspn(value + pos, DIGITS);
- pos += strspn(value + pos, WHITESPACE);
- if (value[pos] == '-')
- return -EINVAL;
-
- r = sscanf(value, "%" PRIu64 "%" PRIu64 "%n", &a, &b, &pos);
- if (r != 2) {
- log_debug("Failed to parse dual timestamp value \"%s\".", value);
- return -EINVAL;
- }
-
- if (value[pos] != '\0')
- /* trailing garbage */
- return -EINVAL;
-
- t->realtime = a;
- t->monotonic = b;
-
- return 0;
-}
-
-int timestamp_deserialize(const char *value, usec_t *timestamp) {
- int r;
-
- assert(value);
-
- r = safe_atou64(value, timestamp);
- if (r < 0)
- return log_debug_errno(r, "Failed to parse timestamp value \"%s\": %m", value);
-
- return r;
-}
-
static int parse_timestamp_impl(const char *t, usec_t *usec, bool with_tz) {
static const struct {
const char *name;
@@ -1030,7 +974,7 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
char *b = e + 1;
/* Don't allow "0.-0", "3.+1" or "3. 1" */
- if (*b == '-' || *b == '+' || isspace(*b))
+ if (IN_SET(*b, '-', '+') || isspace(*b))
return -EINVAL;
errno = 0;
@@ -1052,12 +996,21 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
something = true;
+
+ k = ((usec_t) -1) / multiplier;
+ if ((usec_t) l + 1 >= k || (usec_t) z >= k)
+ return -ERANGE;
+
k = (usec_t) z * multiplier;
for (; n > 0; n--)
k /= 10;
- r += (usec_t) l * multiplier + k;
+ k += (usec_t) l * multiplier;
+ if (k >= ((usec_t) -1) - r)
+ return -ERANGE;
+
+ r += k;
}
*usec = r;
@@ -1069,18 +1022,19 @@ int parse_sec(const char *t, usec_t *usec) {
return parse_time(t, usec, USEC_PER_SEC);
}
-int parse_sec_fix_0(const char *t, usec_t *usec) {
- assert(t);
- assert(usec);
+int parse_sec_fix_0(const char *t, usec_t *ret) {
+ usec_t k;
+ int r;
- t += strspn(t, WHITESPACE);
+ assert(t);
+ assert(ret);
- if (streq(t, "0")) {
- *usec = USEC_INFINITY;
- return 0;
- }
+ r = parse_sec(t, &k);
+ if (r < 0)
+ return r;
- return parse_sec(t, usec);
+ *ret = k == 0 ? USEC_INFINITY : k;
+ return r;
}
int parse_nsec(const char *t, nsec_t *nsec) {
@@ -1168,7 +1122,7 @@ int parse_nsec(const char *t, nsec_t *nsec) {
if (*e == '.') {
char *b = e + 1;
- if (*b == '-' || *b == '+' || isspace(*b))
+ if (IN_SET(*b, '-', '+') || isspace(*b))
return -EINVAL;
errno = 0;
@@ -1189,12 +1143,22 @@ int parse_nsec(const char *t, nsec_t *nsec) {
for (i = 0; i < ELEMENTSOF(table); i++)
if (startswith(e, table[i].suffix)) {
- nsec_t k = (nsec_t) z * table[i].nsec;
+ nsec_t k;
+
+ k = ((nsec_t) -1) / table[i].nsec;
+ if ((nsec_t) l + 1 >= k || (nsec_t) z >= k)
+ return -ERANGE;
+
+ k = (nsec_t) z * table[i].nsec;
for (; n > 0; n--)
k /= 10;
- r += (nsec_t) l * table[i].nsec + k;
+ k += (nsec_t) l * table[i].nsec;
+ if (k >= ((nsec_t) -1) - r)
+ return -ERANGE;
+
+ r += k;
p = e + strlen(table[i].suffix);
something = true;
@@ -1227,6 +1191,7 @@ int get_timezones(char ***ret) {
_cleanup_fclose_ FILE *f = NULL;
_cleanup_strv_free_ char **zones = NULL;
size_t n_zones = 0, n_allocated = 0;
+ int r;
assert(ret);
@@ -1239,13 +1204,18 @@ int get_timezones(char ***ret) {
f = fopen("/usr/share/zoneinfo/zone.tab", "re");
if (f) {
- char l[LINE_MAX];
-
- FOREACH_LINE(l, f, return -errno) {
+ for (;;) {
+ _cleanup_free_ char *line = NULL;
char *p, *w;
size_t k;
- p = strstrip(l);
+ r = read_line(f, LONG_LINE_MAX, &line);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ break;
+
+ p = strstrip(line);
if (isempty(p) || *p == '#')
continue;
diff --git a/src/systemd/src/basic/time-util.h b/src/systemd/src/basic/time-util.h
index 344f2dc52e..5316305062 100644
--- a/src/systemd/src/basic/time-util.h
+++ b/src/systemd/src/basic/time-util.h
@@ -108,10 +108,6 @@ char *format_timestamp_us_utc(char *buf, size_t l, usec_t t);
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);
-void dual_timestamp_serialize(FILE *f, const char *name, dual_timestamp *t);
-int dual_timestamp_deserialize(const char *value, dual_timestamp *t);
-int timestamp_deserialize(const char *value, usec_t *timestamp);
-
int parse_timestamp(const char *t, usec_t *usec);
int parse_sec(const char *t, usec_t *usec);
diff --git a/src/systemd/src/basic/util.c b/src/systemd/src/basic/util.c
index 40f50039d5..7cff013910 100644
--- a/src/systemd/src/basic/util.c
+++ b/src/systemd/src/basic/util.c
@@ -25,6 +25,7 @@
#include "def.h"
#include "device-nodes.h"
#include "dirent-util.h"
+#include "env-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "format-util.h"
@@ -111,6 +112,7 @@ int prot_from_flags(int flags) {
bool in_initrd(void) {
struct statfs s;
+ int r;
if (saved_in_initrd >= 0)
return saved_in_initrd;
@@ -125,9 +127,16 @@ bool in_initrd(void) {
* emptying when transititioning to the main systemd.
*/
- saved_in_initrd = access("/etc/initrd-release", F_OK) >= 0 &&
- statfs("/", &s) >= 0 &&
- is_temporary_fs(&s);
+ r = getenv_bool_secure("SYSTEMD_IN_INITRD");
+ if (r < 0 && r != -ENXIO)
+ log_debug_errno(r, "Failed to parse $SYSTEMD_IN_INITRD, ignoring: %m");
+
+ if (r >= 0)
+ saved_in_initrd = r > 0;
+ else
+ saved_in_initrd = access("/etc/initrd-release", F_OK) >= 0 &&
+ statfs("/", &s) >= 0 &&
+ is_temporary_fs(&s);
return saved_in_initrd;
}
diff --git a/src/systemd/src/basic/util.h b/src/systemd/src/basic/util.h
index 5f3f982190..8cba4ed726 100644
--- a/src/systemd/src/basic/util.h
+++ b/src/systemd/src/basic/util.h
@@ -150,7 +150,13 @@ static inline int memcmp_safe(const void *s1, const void *s2, size_t n) {
int on_ac_power(void);
-#define memzero(x,l) (memset((x), 0, (l)))
+#define memzero(x,l) \
+ ({ \
+ size_t _l_ = (l); \
+ void *_x_ = (x); \
+ _l_ == 0 ? _x_ : memset(_x_, 0, _l_); \
+ })
+
#define zero(x) (memzero(&(x), sizeof(x)))
static inline void *mempset(void *s, int c, size_t n) {
diff --git a/src/systemd/src/libsystemd-network/dhcp-network.c b/src/systemd/src/libsystemd-network/dhcp-network.c
index 80e9577cd5..8d8cdf9da7 100644
--- a/src/systemd/src/libsystemd-network/dhcp-network.c
+++ b/src/systemd/src/libsystemd-network/dhcp-network.c
@@ -80,7 +80,7 @@ static int _bind_raw_socket(int ifindex, union sockaddr_union *link,
.filter = filter
};
_cleanup_close_ int s = -1;
- int r, on = 1;
+ int r;
assert(ifindex > 0);
assert(link);
@@ -89,9 +89,9 @@ static int _bind_raw_socket(int ifindex, union sockaddr_union *link,
if (s < 0)
return -errno;
- r = setsockopt(s, SOL_PACKET, PACKET_AUXDATA, &on, sizeof(on));
+ r = setsockopt_int(s, SOL_PACKET, PACKET_AUXDATA, true);
if (r < 0)
- return -errno;
+ return r;
r = setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, &fprog, sizeof(fprog));
if (r < 0)
@@ -151,19 +151,19 @@ int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port) {
};
_cleanup_close_ int s = -1;
char ifname[IF_NAMESIZE] = "";
- int r, on = 1, tos = IPTOS_CLASS_CS6;
+ int r;
s = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
if (s < 0)
return -errno;
- r = setsockopt(s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
+ r = setsockopt_int(s, IPPROTO_IP, IP_TOS, IPTOS_CLASS_CS6);
if (r < 0)
- return -errno;
+ return r;
- r = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+ r = setsockopt_int(s, SOL_SOCKET, SO_REUSEADDR, true);
if (r < 0)
- return -errno;
+ return r;
if (ifindex > 0) {
if (if_indextoname(ifindex, ifname) == 0)
@@ -175,18 +175,18 @@ int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port) {
}
if (address == INADDR_ANY) {
- r = setsockopt(s, IPPROTO_IP, IP_PKTINFO, &on, sizeof(on));
+ r = setsockopt_int(s, IPPROTO_IP, IP_PKTINFO, true);
if (r < 0)
- return -errno;
+ return r;
- r = setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on));
+ r = setsockopt_int(s, SOL_SOCKET, SO_BROADCAST, true);
if (r < 0)
- return -errno;
+ return r;
} else {
- r = setsockopt(s, IPPROTO_IP, IP_FREEBIND, &on, sizeof(on));
+ r = setsockopt_int(s, IPPROTO_IP, IP_FREEBIND, true);
if (r < 0)
- return -errno;
+ return r;
}
r = bind(s, &src.sa, sizeof(src.in));
diff --git a/src/systemd/src/libsystemd-network/dhcp6-network.c b/src/systemd/src/libsystemd-network/dhcp6-network.c
index 98aa6261eb..22e4201746 100644
--- a/src/systemd/src/libsystemd-network/dhcp6-network.c
+++ b/src/systemd/src/libsystemd-network/dhcp6-network.c
@@ -27,7 +27,7 @@ int dhcp6_network_bind_udp_socket(int index, struct in6_addr *local_address) {
.in6.sin6_scope_id = index,
};
_cleanup_close_ int s = -1;
- int r, off = 0, on = 1;
+ int r;
assert(index > 0);
assert(local_address);
@@ -38,17 +38,17 @@ int dhcp6_network_bind_udp_socket(int index, struct in6_addr *local_address) {
if (s < 0)
return -errno;
- r = setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on));
+ r = setsockopt_int(s, IPPROTO_IPV6, IPV6_V6ONLY, true);
if (r < 0)
- return -errno;
+ return r;
- r = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &off, sizeof(off));
+ r = setsockopt_int(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, false);
if (r < 0)
- return -errno;
+ return r;
- r = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+ r = setsockopt_int(s, SOL_SOCKET, SO_REUSEADDR, true);
if (r < 0)
- return -errno;
+ return r;
r = bind(s, &src.sa, sizeof(src.in6));
if (r < 0)
diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-client.c b/src/systemd/src/libsystemd-network/sd-dhcp-client.c
index 7fd57cfe3c..6b77116969 100644
--- a/src/systemd/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/systemd/src/libsystemd-network/sd-dhcp-client.c
@@ -88,7 +88,7 @@ struct sd_dhcp_client {
uint32_t mtu;
uint32_t xid;
usec_t start_time;
- unsigned int attempt;
+ unsigned attempt;
usec_t request_sent;
sd_event_source *timeout_t1;
sd_event_source *timeout_t2;
diff --git a/src/systemd/src/libsystemd/sd-event/sd-event.c b/src/systemd/src/libsystemd/sd-event/sd-event.c
index 4c2f62a37d..714591c3fb 100644
--- a/src/systemd/src/libsystemd/sd-event/sd-event.c
+++ b/src/systemd/src/libsystemd/sd-event/sd-event.c
@@ -316,6 +316,7 @@ static sd_event *event_resolve(sd_event *e) {
static int pending_prioq_compare(const void *a, const void *b) {
const sd_event_source *x = a, *y = b;
+ int r;
assert(x->pending);
assert(y->pending);
@@ -327,22 +328,17 @@ static int pending_prioq_compare(const void *a, const void *b) {
return 1;
/* Lower priority values first */
- if (x->priority < y->priority)
- return -1;
- if (x->priority > y->priority)
- return 1;
+ r = CMP(x->priority, y->priority);
+ if (r != 0)
+ return r;
/* Older entries first */
- if (x->pending_iteration < y->pending_iteration)
- return -1;
- if (x->pending_iteration > y->pending_iteration)
- return 1;
-
- return 0;
+ return CMP(x->pending_iteration, y->pending_iteration);
}
static int prepare_prioq_compare(const void *a, const void *b) {
const sd_event_source *x = a, *y = b;
+ int r;
assert(x->prepare);
assert(y->prepare);
@@ -356,18 +352,12 @@ static int prepare_prioq_compare(const void *a, const void *b) {
/* Move most recently prepared ones last, so that we can stop
* preparing as soon as we hit one that has already been
* prepared in the current iteration */
- if (x->prepare_iteration < y->prepare_iteration)
- return -1;
- if (x->prepare_iteration > y->prepare_iteration)
- return 1;
+ r = CMP(x->prepare_iteration, y->prepare_iteration);
+ if (r != 0)
+ return r;
/* Lower priority values first */
- if (x->priority < y->priority)
- return -1;
- if (x->priority > y->priority)
- return 1;
-
- return 0;
+ return CMP(x->priority, y->priority);
}
static int earliest_time_prioq_compare(const void *a, const void *b) {
@@ -389,12 +379,7 @@ static int earliest_time_prioq_compare(const void *a, const void *b) {
return 1;
/* Order by time */
- if (x->time.next < y->time.next)
- return -1;
- if (x->time.next > y->time.next)
- return 1;
-
- return 0;
+ return CMP(x->time.next, y->time.next);
}
static usec_t time_event_source_latest(const sd_event_source *s) {
@@ -420,12 +405,7 @@ static int latest_time_prioq_compare(const void *a, const void *b) {
return 1;
/* Order by time */
- if (time_event_source_latest(x) < time_event_source_latest(y))
- return -1;
- if (time_event_source_latest(x) > time_event_source_latest(y))
- return 1;
-
- return 0;
+ return CMP(time_event_source_latest(x), time_event_source_latest(y));
}
static int exit_prioq_compare(const void *a, const void *b) {
@@ -441,12 +421,7 @@ static int exit_prioq_compare(const void *a, const void *b) {
return 1;
/* Lower priority values first */
- if (x->priority < y->priority)
- return -1;
- if (x->priority > y->priority)
- return 1;
-
- return 0;
+ return CMP(x->priority, y->priority);
}
static void free_clock_data(struct clock_data *d) {
@@ -1594,21 +1569,16 @@ static int event_make_inotify_data(
static int inode_data_compare(const void *a, const void *b) {
const struct inode_data *x = a, *y = b;
+ int r;
assert(x);
assert(y);
- if (x->dev < y->dev)
- return -1;
- if (x->dev > y->dev)
- return 1;
-
- if (x->ino < y->ino)
- return -1;
- if (x->ino > y->ino)
- return 1;
+ r = CMP(x->dev, y->dev);
+ if (r != 0)
+ return r;
- return 0;
+ return CMP(x->ino, y->ino);
}
static void inode_data_hash_func(const void *p, struct siphash *state) {
diff --git a/src/systemd/src/systemd/sd-event.h b/src/systemd/src/systemd/sd-event.h
index eb35b83431..c38eb84beb 100644
--- a/src/systemd/src/systemd/sd-event.h
+++ b/src/systemd/src/systemd/sd-event.h
@@ -33,7 +33,8 @@
- Supports event source prioritization
- Scales better with a large number of time events because it does not require one timerfd each
- Automatically tries to coalesce timer events system-wide
- - Handles signals and child PIDs
+ - Handles signals, child PIDs, inotify events
+ - Supports systemd-style automatic watchdog event generation
*/
_SD_BEGIN_DECLARATIONS;